diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2023-05-18 11:24:03 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2023-05-18 11:24:03 +1000 |
commit | 981c82a29ba3f58f19f51a08167b657b96d0b9e5 (patch) | |
tree | 30aefcd8fbcca8844451574415cae9da7d8cc07e | |
parent | 7856761916cf8cb3d5e92b0344f78bc6f9bedd22 (diff) | |
parent | 8d087a09c7017f1425f3f1d36807eb4988410942 (diff) | |
download | linux-next-981c82a29ba3f58f19f51a08167b657b96d0b9e5.tar.gz |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy.git
20 files changed, 1257 insertions, 406 deletions
diff --git a/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.txt b/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.txt deleted file mode 100644 index 3dc8b3d2ffbb..000000000000 --- a/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.txt +++ /dev/null @@ -1,15 +0,0 @@ -BROADCOM KONA USB2 PHY - -Required properties: - - compatible: brcm,kona-usb2-phy - - reg: offset and length of the PHY registers - - #phy-cells: must be 0 -Refer to phy/phy-bindings.txt for the generic PHY binding properties - -Example: - - usbphy: usb-phy@3f130000 { - compatible = "brcm,kona-usb2-phy"; - reg = <0x3f130000 0x28>; - #phy-cells = <0>; - }; diff --git a/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.yaml b/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.yaml new file mode 100644 index 000000000000..d7faeb81f7a7 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.yaml @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/brcm,kona-usb2-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Kona family USB 2.0 PHY + +maintainers: + - Florian Fainelli <f.fainelli@gmail.com> + +properties: + compatible: + const: brcm,kona-usb2-phy + + reg: + maxItems: 1 + + '#phy-cells': + const: 0 + +required: + - compatible + - reg + - '#phy-cells' + +additionalProperties: false + +examples: + - | + usb-phy@3f130000 { + compatible = "brcm,kona-usb2-phy"; + reg = <0x3f130000 0x28>; + #phy-cells = <0>; + }; +... diff --git a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml index c4f8e6ffa5c3..6566353f1a02 100644 --- a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml @@ -43,6 +43,9 @@ properties: "#phy-cells": const: 0 + power-domains: + maxItems: 1 + vdda-phy-supply: true vdda-pll-supply: true diff --git a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml index 543c1a2811a5..95eecbaef05c 100644 --- a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml @@ -18,13 +18,14 @@ properties: oneOf: - items: - enum: + - qcom,ipq6018-qusb2-phy - qcom,ipq8074-qusb2-phy + - qcom,ipq9574-qusb2-phy - qcom,msm8953-qusb2-phy - qcom,msm8996-qusb2-phy - qcom,msm8998-qusb2-phy - qcom,qcm2290-qusb2-phy - qcom,sdm660-qusb2-phy - - qcom,ipq6018-qusb2-phy - qcom,sm4250-qusb2-phy - qcom,sm6115-qusb2-phy - items: diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml index 94c0fab065a8..a1897a7606df 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml @@ -78,9 +78,9 @@ allOf: then: properties: clocks: - maxItems: 3 + minItems: 3 clock-names: - maxItems: 3 + minItems: 3 else: properties: clocks: diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml index 16fce1038285..a272c4033652 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml @@ -16,6 +16,8 @@ description: properties: compatible: enum: + - qcom,ipq9574-qmp-usb3-phy + - qcom,sa8775p-qmp-usb3-uni-phy - qcom,sc8280xp-qmp-usb3-uni-phy reg: @@ -25,11 +27,7 @@ properties: maxItems: 4 clock-names: - items: - - const: aux - - const: ref - - const: com_aux - - const: pipe + maxItems: 4 power-domains: maxItems: 1 @@ -60,7 +58,6 @@ required: - reg - clocks - clock-names - - power-domains - resets - reset-names - vdda-phy-supply @@ -69,6 +66,42 @@ required: - clock-output-names - "#phy-cells" +allOf: + - if: + properties: + compatible: + contains: + enum: + - qcom,ipq9574-qmp-usb3-phy + then: + properties: + clock-names: + items: + - const: aux + - const: ref + - const: cfg_ahb + - const: pipe + + - if: + properties: + compatible: + contains: + enum: + - qcom,sa8775p-qmp-usb3-uni-phy + - qcom,sc8280xp-qmp-usb3-uni-phy + then: + properties: + clocks: + maxItems: 4 + clock-names: + items: + - const: aux + - const: ref + - const: com_aux + - const: pipe + required: + - power-domains + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml index a26524b7e7b7..0f200e3f97a9 100644 --- a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml @@ -20,6 +20,7 @@ properties: - qcom,usb-snps-femto-v2-phy - items: - enum: + - qcom,sa8775p-usb-hs-phy - qcom,sc8280xp-usb-hs-phy - const: qcom,usb-snps-hs-5nm-phy - items: diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml index d84281926f10..4a36e2b6c8fb 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml @@ -23,6 +23,7 @@ properties: - qcom,msm8998-dwc3 - qcom,qcm2290-dwc3 - qcom,qcs404-dwc3 + - qcom,sa8775p-dwc3 - qcom,sc7180-dwc3 - qcom,sc7280-dwc3 - qcom,sc8280xp-dwc3 @@ -180,6 +181,7 @@ allOf: - qcom,msm8953-dwc3 - qcom,msm8996-dwc3 - qcom,msm8998-dwc3 + - qcom,sa8775p-dwc3 - qcom,sc7180-dwc3 - qcom,sc7280-dwc3 - qcom,sdm670-dwc3 @@ -455,6 +457,25 @@ allOf: - const: dm_hs_phy_irq - const: ss_phy_irq + - if: + properties: + compatible: + contains: + enum: + - qcom,sa8775p-dwc3 + then: + properties: + interrupts: + minItems: 3 + maxItems: 4 + interrupt-names: + minItems: 3 + items: + - const: pwr_event + - const: dp_hs_phy_irq + - const: dm_hs_phy_irq + - const: ss_phy_irq + additionalProperties: false examples: diff --git a/drivers/phy/amlogic/phy-meson-g12a-usb2.c b/drivers/phy/amlogic/phy-meson-g12a-usb2.c index 9d1efa0d9394..ec2555bb83d5 100644 --- a/drivers/phy/amlogic/phy-meson-g12a-usb2.c +++ b/drivers/phy/amlogic/phy-meson-g12a-usb2.c @@ -172,10 +172,16 @@ static int phy_meson_g12a_usb2_init(struct phy *phy) int ret; unsigned int value; - ret = reset_control_reset(priv->reset); + ret = clk_prepare_enable(priv->clk); if (ret) return ret; + ret = reset_control_reset(priv->reset); + if (ret) { + clk_disable_unprepare(priv->clk); + return ret; + } + udelay(RESET_COMPLETE_TIME); /* usb2_otg_aca_en == 0 */ @@ -277,8 +283,13 @@ static int phy_meson_g12a_usb2_init(struct phy *phy) static int phy_meson_g12a_usb2_exit(struct phy *phy) { struct phy_meson_g12a_usb2_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = reset_control_reset(priv->reset); + if (!ret) + clk_disable_unprepare(priv->clk); - return reset_control_reset(priv->reset); + return ret; } /* set_mode is not needed, mode setting is handled via the UTMI bus */ diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c index 3831f596d50c..3b0e4daa9de9 100644 --- a/drivers/phy/cadence/phy-cadence-torrent.c +++ b/drivers/phy/cadence/phy-cadence-torrent.c @@ -38,6 +38,9 @@ #define POLL_TIMEOUT_US 5000 #define PLL_LOCK_TIMEOUT 100000 +#define DP_PLL0 BIT(0) +#define DP_PLL1 BIT(1) + #define TORRENT_COMMON_CDB_OFFSET 0x0 #define TORRENT_TX_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \ @@ -66,16 +69,11 @@ */ #define PHY_AUX_CTRL 0x04 #define PHY_RESET 0x20 -#define PMA_TX_ELEC_IDLE_MASK 0xF0U #define PMA_TX_ELEC_IDLE_SHIFT 4 -#define PHY_L00_RESET_N_MASK 0x01U #define PHY_PMA_XCVR_PLLCLK_EN 0x24 #define PHY_PMA_XCVR_PLLCLK_EN_ACK 0x28 #define PHY_PMA_XCVR_POWER_STATE_REQ 0x2c -#define PHY_POWER_STATE_LN_0 0x0000 -#define PHY_POWER_STATE_LN_1 0x0008 -#define PHY_POWER_STATE_LN_2 0x0010 -#define PHY_POWER_STATE_LN_3 0x0018 +#define PHY_POWER_STATE_LN(ln) ((ln) * 8) #define PMA_XCVR_POWER_STATE_REQ_LN_MASK 0x3FU #define PHY_PMA_XCVR_POWER_STATE_ACK 0x30 #define PHY_PMA_CMN_READY 0x34 @@ -323,6 +321,7 @@ struct cdns_torrent_phy { void __iomem *base; /* DPTX registers base */ void __iomem *sd_base; /* SD0801 registers base */ u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */ + u32 dp_pll; struct reset_control *phy_rst; struct reset_control *apb_rst; struct device *dev; @@ -905,88 +904,129 @@ void cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(struct cdns_torrent_phy *cdns_phy, /* Setting VCO for 10.8GHz */ case 2700: case 5400: - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028); - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C); + if (cdns_phy->dp_pll & DP_PLL0) + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022); + + if (cdns_phy->dp_pll & DP_PLL1) { + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028); + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022); + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C); + } break; /* Setting VCO for 9.72GHz */ case 1620: case 2430: case 3240: - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061); - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042); - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + if (cdns_phy->dp_pll & DP_PLL0) { + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + } + if (cdns_phy->dp_pll & DP_PLL1) { + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + } break; /* Setting VCO for 8.64GHz */ case 2160: case 4320: - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056); - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A); - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + if (cdns_phy->dp_pll & DP_PLL0) { + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + } + if (cdns_phy->dp_pll & DP_PLL1) { + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + } break; /* Setting VCO for 8.1GHz */ case 8100: - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051); - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036); - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + if (cdns_phy->dp_pll & DP_PLL0) { + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + } + if (cdns_phy->dp_pll & DP_PLL1) { + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + } break; } } +/* Set PLL used for DP configuration */ +static int cdns_torrent_dp_get_pll(struct cdns_torrent_phy *cdns_phy, + enum cdns_torrent_phy_type phy_t2) +{ + switch (phy_t2) { + case TYPE_PCIE: + case TYPE_USB: + cdns_phy->dp_pll = DP_PLL1; + break; + case TYPE_SGMII: + case TYPE_QSGMII: + cdns_phy->dp_pll = DP_PLL0; + break; + case TYPE_NONE: + cdns_phy->dp_pll = DP_PLL0 | DP_PLL1; + break; + default: + dev_err(cdns_phy->dev, "Unsupported PHY configuration\n"); + return -EINVAL; + } + + return 0; +} + /* * Enable or disable PLL for selected lanes. */ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, struct phy_configure_opts_dp *dp, bool enable) { - u32 rd_val; - u32 ret; struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; + u32 rd_val, pll_ack_val; + int ret; /* * Used to determine, which bits to check for or enable in @@ -996,28 +1036,18 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, /* Used to enable or disable lanes. */ u32 pll_val; - /* Select values of registers and mask, depending on enabled lane - * count. - */ - switch (dp->lanes) { - /* lane 0 */ - case (1): - pll_bits = 0x00000001; - break; - /* lanes 0-1 */ - case (2): - pll_bits = 0x00000003; - break; - /* lanes 0-3, all */ - default: - pll_bits = 0x0000000F; - break; - } + /* Select values of registers and mask, depending on enabled lane count. */ + pll_val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); - if (enable) - pll_val = pll_bits; - else - pll_val = 0x00000000; + if (enable) { + pll_bits = ((1 << dp->lanes) - 1); + pll_val |= pll_bits; + pll_ack_val = pll_bits; + } else { + pll_bits = ((1 << inst->num_lanes) - 1); + pll_val &= (~pll_bits); + pll_ack_val = 0; + } cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, pll_val); @@ -1025,22 +1055,23 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_PLLCLK_EN_ACK, rd_val, - (rd_val & pll_bits) == pll_val, + (rd_val & pll_bits) == pll_ack_val, 0, POLL_TIMEOUT_US); ndelay(100); return ret; } static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, u32 num_lanes, enum phy_powerstate powerstate) { /* Register value for power state for a single byte. */ - u32 value_part; - u32 value; - u32 mask; + u32 value_part, i; + u32 value = 0; + u32 mask = 0; u32 read_val; - u32 ret; + int ret; struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; switch (powerstate) { @@ -1056,29 +1087,11 @@ static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, break; } - /* Select values of registers and mask, depending on enabled - * lane count. - */ - switch (num_lanes) { - /* lane 0 */ - case (1): - value = value_part; - mask = 0x0000003FU; - break; - /* lanes 0-1 */ - case (2): - value = (value_part - | (value_part << 8)); - mask = 0x00003F3FU; - break; - /* lanes 0-3, all */ - default: - value = (value_part - | (value_part << 8) - | (value_part << 16) - | (value_part << 24)); - mask = 0x3F3F3F3FU; - break; + /* Select values of registers and mask, depending on enabled lane count. */ + + for (i = 0; i < num_lanes; i++) { + value |= (value_part << PHY_POWER_STATE_LN(i)); + mask |= (PMA_XCVR_POWER_STATE_REQ_LN_MASK << PHY_POWER_STATE_LN(i)); } /* Set power state A<n>. */ @@ -1093,7 +1106,8 @@ static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, return ret; } -static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) +static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, u32 num_lanes) { unsigned int read_val; int ret; @@ -1114,12 +1128,12 @@ static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) ndelay(100); - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes, POWERSTATE_A2); if (ret) return ret; - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes, POWERSTATE_A0); return ret; @@ -1143,6 +1157,7 @@ static int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy) } static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, u32 rate, u32 num_lanes) { unsigned int clk_sel_val = 0; @@ -1175,14 +1190,17 @@ static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, break; } - cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, - CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val); - cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, - CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val); + if (cdns_phy->dp_pll & DP_PLL0) + cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, + CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val); + + if (cdns_phy->dp_pll & DP_PLL1) + cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, + CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val); /* PMA lane configuration to deal with multi-link operation */ for (i = 0; i < num_lanes; i++) - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + i], XCVR_DIAG_HSCLK_DIV, hsclk_div_val); } @@ -1191,23 +1209,44 @@ static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, * set and PLL disable request was processed. */ static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, struct phy_configure_opts_dp *dp) { - u32 read_val, ret; + u32 read_val, field_val; + int ret; - /* Disable the cmn_pll0_en before re-programming the new data rate. */ - regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x0); + /* + * Disable the associated PLL (cmn_pll0_en or cmn_pll1_en) before + * re-programming the new data rate. + */ + ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val); + if (ret) + return ret; + field_val &= ~(cdns_phy->dp_pll); + regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val); /* * Wait for PLL ready de-assertion. * For PLL0 - PHY_PMA_CMN_CTRL2[2] == 1 + * For PLL1 - PHY_PMA_CMN_CTRL2[3] == 1 */ - ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, - read_val, - ((read_val >> 2) & 0x01) != 0, - 0, POLL_TIMEOUT_US); - if (ret) - return ret; + if (cdns_phy->dp_pll & DP_PLL0) { + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, + read_val, + ((read_val >> 2) & 0x01) != 0, + 0, POLL_TIMEOUT_US); + if (ret) + return ret; + } + + if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1) { + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, + read_val, + ((read_val >> 3) & 0x01) != 0, + 0, POLL_TIMEOUT_US); + if (ret) + return ret; + } ndelay(200); /* DP Rate Change - VCO Output settings. */ @@ -1221,19 +1260,35 @@ static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy, /* PMA common configuration 100MHz */ cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(cdns_phy, dp->link_rate, dp->ssc); - cdns_torrent_dp_pma_cmn_rate(cdns_phy, dp->link_rate, dp->lanes); + cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, dp->link_rate, dp->lanes); - /* Enable the cmn_pll0_en. */ - regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x3); + /* Enable the associated PLL (cmn_pll0_en or cmn_pll1_en) */ + ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val); + if (ret) + return ret; + field_val |= cdns_phy->dp_pll; + regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val); /* * Wait for PLL ready assertion. * For PLL0 - PHY_PMA_CMN_CTRL2[0] == 1 + * For PLL1 - PHY_PMA_CMN_CTRL2[1] == 1 */ - ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, - read_val, - (read_val & 0x01) != 0, - 0, POLL_TIMEOUT_US); + if (cdns_phy->dp_pll & DP_PLL0) { + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, + read_val, + (read_val & 0x01) != 0, + 0, POLL_TIMEOUT_US); + if (ret) + return ret; + } + + if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1) + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, + read_val, + ((read_val >> 1) & 0x01) != 0, + 0, POLL_TIMEOUT_US); + return ret; } @@ -1301,6 +1356,7 @@ static int cdns_torrent_dp_verify_config(struct cdns_torrent_inst *inst, /* Set power state A0 and PLL clock enable to 0 on enabled lanes. */ static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, u32 num_lanes) { struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; @@ -1308,27 +1364,13 @@ static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy, PHY_PMA_XCVR_POWER_STATE_REQ); u32 pll_clk_en = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); + u32 i; - /* Lane 0 is always enabled. */ - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << - PHY_POWER_STATE_LN_0); - pll_clk_en &= ~0x01U; - - if (num_lanes > 1) { - /* lane 1 */ - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << - PHY_POWER_STATE_LN_1); - pll_clk_en &= ~(0x01U << 1); - } + for (i = 0; i < num_lanes; i++) { + pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK + << PHY_POWER_STATE_LN(inst->mlane + i)); - if (num_lanes > 2) { - /* lanes 2 and 3 */ - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << - PHY_POWER_STATE_LN_2); - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << - PHY_POWER_STATE_LN_3); - pll_clk_en &= ~(0x01U << 2); - pll_clk_en &= ~(0x01U << 3); + pll_clk_en &= ~(0x01U << (inst->mlane + i)); } cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, pwr_state); @@ -1337,36 +1379,57 @@ static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy, /* Configure lane count as required. */ static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, struct phy_configure_opts_dp *dp) { - u32 value; - u32 ret; + u32 value, i; + int ret; struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; u8 lane_mask = (1 << dp->lanes) - 1; + u8 pma_tx_elec_idle_mask = 0; + u32 clane = inst->mlane; + + lane_mask <<= clane; value = cdns_torrent_dp_read(regmap, PHY_RESET); /* clear pma_tx_elec_idle_ln_* bits. */ - value &= ~PMA_TX_ELEC_IDLE_MASK; + pma_tx_elec_idle_mask = ((1 << inst->num_lanes) - 1) << clane; + + pma_tx_elec_idle_mask <<= PMA_TX_ELEC_IDLE_SHIFT; + + value &= ~pma_tx_elec_idle_mask; + /* Assert pma_tx_elec_idle_ln_* for disabled lanes. */ value |= ((~lane_mask) << PMA_TX_ELEC_IDLE_SHIFT) & - PMA_TX_ELEC_IDLE_MASK; + pma_tx_elec_idle_mask; + cdns_torrent_dp_write(regmap, PHY_RESET, value); - /* reset the link by asserting phy_l00_reset_n low */ + /* reset the link by asserting master lane phy_l0*_reset_n low */ cdns_torrent_dp_write(regmap, PHY_RESET, - value & (~PHY_L00_RESET_N_MASK)); + value & (~(1 << clane))); /* - * Assert lane reset on unused lanes and lane 0 so they remain in reset + * Assert lane reset on unused lanes and master lane so they remain in reset * and powered down when re-enabling the link */ - value = (value & 0x0000FFF0) | (0x0000000E & lane_mask); + for (i = 0; i < inst->num_lanes; i++) + value &= (~(1 << (clane + i))); + + for (i = 1; i < inst->num_lanes; i++) + value |= ((1 << (clane + i)) & lane_mask); + cdns_torrent_dp_write(regmap, PHY_RESET, value); - cdns_torrent_dp_set_a0_pll(cdns_phy, dp->lanes); + cdns_torrent_dp_set_a0_pll(cdns_phy, inst, dp->lanes); /* release phy_l0*_reset_n based on used laneCount */ - value = (value & 0x0000FFF0) | (0x0000000F & lane_mask); + for (i = 0; i < inst->num_lanes; i++) + value &= (~(1 << (clane + i))); + + for (i = 0; i < inst->num_lanes; i++) + value |= ((1 << (clane + i)) & lane_mask); + cdns_torrent_dp_write(regmap, PHY_RESET, value); /* Wait, until PHY gets ready after releasing PHY reset signal. */ @@ -1377,41 +1440,44 @@ static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy, ndelay(100); /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */ - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001); + value = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); + value |= (1 << clane); + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, value); - ret = cdns_torrent_dp_run(cdns_phy, dp->lanes); + ret = cdns_torrent_dp_run(cdns_phy, inst, dp->lanes); return ret; } /* Configure link rate as required. */ static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, struct phy_configure_opts_dp *dp) { - u32 ret; + int ret; - ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes, + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes, POWERSTATE_A3); if (ret) return ret; - ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, false); + ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, false); if (ret) return ret; ndelay(200); - ret = cdns_torrent_dp_configure_rate(cdns_phy, dp); + ret = cdns_torrent_dp_configure_rate(cdns_phy, inst, dp); if (ret) return ret; ndelay(200); - ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, true); + ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, true); if (ret) return ret; - ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes, + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes, POWERSTATE_A2); if (ret) return ret; - ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes, + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes, POWERSTATE_A0); if (ret) return ret; @@ -1422,44 +1488,45 @@ static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy, /* Configure voltage swing and pre-emphasis for all enabled lanes. */ static void cdns_torrent_dp_set_voltages(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, struct phy_configure_opts_dp *dp) { u8 lane; u16 val; for (lane = 0; lane < dp->lanes; lane++) { - val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane], + val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_DIAG_ACYA); /* * Write 1 to register bit TX_DIAG_ACYA[0] to freeze the * current state of the analog TX driver. */ val |= TX_DIAG_ACYA_HBDC_MASK; - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_DIAG_ACYA, val); - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_TXCC_CTRL, 0x08A4); val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].diag_tx_drv; - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], DRV_DIAG_TX_DRV, val); val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].mgnfs_mult; - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_TXCC_MGNFS_MULT_000, val); val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].cpost_mult; - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_TXCC_CPOST_MULT_00, val); - val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane], + val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_DIAG_ACYA); /* * Write 0 to register bit TX_DIAG_ACYA[0] to allow the state of * analog TX driver to reflect the new programmed one. */ val &= ~TX_DIAG_ACYA_HBDC_MASK; - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_DIAG_ACYA, val); } }; @@ -1478,7 +1545,7 @@ static int cdns_torrent_dp_configure(struct phy *phy, } if (opts->dp.set_lanes) { - ret = cdns_torrent_dp_set_lanes(cdns_phy, &opts->dp); + ret = cdns_torrent_dp_set_lanes(cdns_phy, inst, &opts->dp); if (ret) { dev_err(&phy->dev, "cdns_torrent_dp_set_lanes failed\n"); return ret; @@ -1486,7 +1553,7 @@ static int cdns_torrent_dp_configure(struct phy *phy, } if (opts->dp.set_rate) { - ret = cdns_torrent_dp_set_rate(cdns_phy, &opts->dp); + ret = cdns_torrent_dp_set_rate(cdns_phy, inst, &opts->dp); if (ret) { dev_err(&phy->dev, "cdns_torrent_dp_set_rate failed\n"); return ret; @@ -1494,7 +1561,7 @@ static int cdns_torrent_dp_configure(struct phy *phy, } if (opts->dp.set_voltages) - cdns_torrent_dp_set_voltages(cdns_phy, &opts->dp); + cdns_torrent_dp_set_voltages(cdns_phy, inst, &opts->dp); return ret; } @@ -1562,6 +1629,7 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy, { struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; unsigned char lane_bits; + u32 val; cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */ @@ -1569,18 +1637,23 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy, * Set lines power state to A0 * Set lines pll clk enable to 0 */ - cdns_torrent_dp_set_a0_pll(cdns_phy, inst->num_lanes); + cdns_torrent_dp_set_a0_pll(cdns_phy, inst, inst->num_lanes); /* * release phy_l0*_reset_n and pma_tx_elec_idle_ln_* based on * used lanes */ lane_bits = (1 << inst->num_lanes) - 1; - cdns_torrent_dp_write(regmap, PHY_RESET, - ((0xF & ~lane_bits) << 4) | (0xF & lane_bits)); + + val = cdns_torrent_dp_read(regmap, PHY_RESET); + val |= (0xF & lane_bits); + val &= ~(lane_bits << 4); + cdns_torrent_dp_write(regmap, PHY_RESET, val); /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */ - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001); + val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); + val |= 1; + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, val); /* * PHY PMA registers configuration functions @@ -1599,7 +1672,7 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy, cdns_phy->max_bit_rate, false); - cdns_torrent_dp_pma_cmn_rate(cdns_phy, cdns_phy->max_bit_rate, + cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, cdns_phy->max_bit_rate, inst->num_lanes); /* take out of reset */ @@ -1612,13 +1685,15 @@ static int cdns_torrent_dp_start(struct cdns_torrent_phy *cdns_phy, { int ret; - cdns_torrent_phy_on(phy); + ret = cdns_torrent_phy_on(phy); + if (ret) + return ret; ret = cdns_torrent_dp_wait_pma_cmn_ready(cdns_phy); if (ret) return ret; - ret = cdns_torrent_dp_run(cdns_phy, inst->num_lanes); + ret = cdns_torrent_dp_run(cdns_phy, inst, inst->num_lanes); return ret; } @@ -1627,6 +1702,7 @@ static int cdns_torrent_dp_init(struct phy *phy) { struct cdns_torrent_inst *inst = phy_get_drvdata(phy); struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); + int ret; switch (cdns_phy->ref_clk_rate) { case CLK_19_2_MHZ: @@ -1639,6 +1715,24 @@ static int cdns_torrent_dp_init(struct phy *phy) return -EINVAL; } + ret = cdns_torrent_dp_get_pll(cdns_phy, TYPE_NONE); + if (ret) + return ret; + + cdns_torrent_dp_common_init(cdns_phy, inst); + + return cdns_torrent_dp_start(cdns_phy, inst, phy); +} + +static int cdns_torrent_dp_multilink_init(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, + struct phy *phy) +{ + if (cdns_phy->ref_clk_rate != CLK_100_MHZ) { + dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n"); + return -EINVAL; + } + cdns_torrent_dp_common_init(cdns_phy, inst); return cdns_torrent_dp_start(cdns_phy, inst, phy); @@ -2155,8 +2249,11 @@ static int cdns_torrent_phy_init(struct phy *phy) u32 num_regs; int i, j; - if (cdns_phy->nsubnodes > 1) + if (cdns_phy->nsubnodes > 1) { + if (phy_type == TYPE_DP) + return cdns_torrent_dp_multilink_init(cdns_phy, inst, phy); return 0; + } /** * Spread spectrum generation is not required or supported @@ -2398,6 +2495,12 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy) } } + if (phy_t1 == TYPE_DP) { + ret = cdns_torrent_dp_get_pll(cdns_phy, phy_t2); + if (ret) + return ret; + } + reset_control_deassert(cdns_phy->phys[node].lnk_rst); } @@ -2793,6 +2896,109 @@ static void cdns_torrent_phy_remove(struct platform_device *pdev) cdns_torrent_clk_cleanup(cdns_phy); } +/* USB and DP link configuration */ +static struct cdns_reg_pairs usb_dp_link_cmn_regs[] = { + {0x0002, PHY_PLL_CFG}, + {0x8600, CMN_PDIAG_PLL0_CLK_SEL_M0} +}; + +static struct cdns_reg_pairs usb_dp_xcvr_diag_ln_regs[] = { + {0x0000, XCVR_DIAG_HSCLK_SEL}, + {0x0001, XCVR_DIAG_HSCLK_DIV}, + {0x0041, XCVR_DIAG_PLLDRC_CTRL} +}; + +static struct cdns_reg_pairs dp_usb_xcvr_diag_ln_regs[] = { + {0x0001, XCVR_DIAG_HSCLK_SEL}, + {0x0009, XCVR_DIAG_PLLDRC_CTRL} +}; + +static struct cdns_torrent_vals usb_dp_link_cmn_vals = { + .reg_pairs = usb_dp_link_cmn_regs, + .num_regs = ARRAY_SIZE(usb_dp_link_cmn_regs), +}; + +static struct cdns_torrent_vals usb_dp_xcvr_diag_ln_vals = { + .reg_pairs = usb_dp_xcvr_diag_ln_regs, + .num_regs = ARRAY_SIZE(usb_dp_xcvr_diag_ln_regs), +}; + +static struct cdns_torrent_vals dp_usb_xcvr_diag_ln_vals = { + .reg_pairs = dp_usb_xcvr_diag_ln_regs, + .num_regs = ARRAY_SIZE(dp_usb_xcvr_diag_ln_regs), +}; + +/* PCIe and DP link configuration */ +static struct cdns_reg_pairs pcie_dp_link_cmn_regs[] = { + {0x0003, PHY_PLL_CFG}, + {0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0}, + {0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1} +}; + +static struct cdns_reg_pairs pcie_dp_xcvr_diag_ln_regs[] = { + {0x0000, XCVR_DIAG_HSCLK_SEL}, + {0x0001, XCVR_DIAG_HSCLK_DIV}, + {0x0012, XCVR_DIAG_PLLDRC_CTRL} +}; + +static struct cdns_reg_pairs dp_pcie_xcvr_diag_ln_regs[] = { + {0x0001, XCVR_DIAG_HSCLK_SEL}, + {0x0009, XCVR_DIAG_PLLDRC_CTRL} +}; + +static struct cdns_torrent_vals pcie_dp_link_cmn_vals = { + .reg_pairs = pcie_dp_link_cmn_regs, + .num_regs = ARRAY_SIZE(pcie_dp_link_cmn_regs), +}; + +static struct cdns_torrent_vals pcie_dp_xcvr_diag_ln_vals = { + .reg_pairs = pcie_dp_xcvr_diag_ln_regs, + .num_regs = ARRAY_SIZE(pcie_dp_xcvr_diag_ln_regs), +}; + +static struct cdns_torrent_vals dp_pcie_xcvr_diag_ln_vals = { + .reg_pairs = dp_pcie_xcvr_diag_ln_regs, + .num_regs = ARRAY_SIZE(dp_pcie_xcvr_diag_ln_regs), +}; + +/* DP Multilink, 100 MHz Ref clk, no SSC */ +static struct cdns_reg_pairs dp_100_no_ssc_cmn_regs[] = { + {0x007F, CMN_TXPUCAL_TUNE}, + {0x007F, CMN_TXPDCAL_TUNE} +}; + +static struct cdns_reg_pairs dp_100_no_ssc_tx_ln_regs[] = { + {0x00FB, TX_PSC_A0}, + {0x04AA, TX_PSC_A2}, + {0x04AA, TX_PSC_A3}, + {0x000F, XCVR_DIAG_BIDI_CTRL} +}; + +static struct cdns_reg_pairs dp_100_no_ssc_rx_ln_regs[] = { + {0x0000, RX_PSC_A0}, + {0x0000, RX_PSC_A2}, + {0x0000, RX_PSC_A3}, + {0x0000, RX_PSC_CAL}, + {0x0000, RX_REE_GCSM1_CTRL}, + {0x0000, RX_REE_GCSM2_CTRL}, + {0x0000, RX_REE_PERGCSM_CTRL} +}; + +static struct cdns_torrent_vals dp_100_no_ssc_cmn_vals = { + .reg_pairs = dp_100_no_ssc_cmn_regs, + .num_regs = ARRAY_SIZE(dp_100_no_ssc_cmn_regs), +}; + +static struct cdns_torrent_vals dp_100_no_ssc_tx_ln_vals = { + .reg_pairs = dp_100_no_ssc_tx_ln_regs, + .num_regs = ARRAY_SIZE(dp_100_no_ssc_tx_ln_regs), +}; + +static struct cdns_torrent_vals dp_100_no_ssc_rx_ln_vals = { + .reg_pairs = dp_100_no_ssc_rx_ln_regs, + .num_regs = ARRAY_SIZE(dp_100_no_ssc_rx_ln_regs), +}; + /* Single DisplayPort(DP) link configuration */ static struct cdns_reg_pairs sl_dp_link_cmn_regs[] = { {0x0000, PHY_PLL_CFG}, @@ -3735,6 +3941,12 @@ static const struct cdns_torrent_data cdns_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_link_cmn_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &pcie_dp_link_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &usb_dp_link_cmn_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -3757,6 +3969,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &pcie_usb_link_cmn_vals, [INTERNAL_SSC] = &pcie_usb_link_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_dp_link_cmn_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -3809,6 +4024,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_dp_link_cmn_vals, + }, }, }, .xcvr_diag_vals = { @@ -3816,6 +4034,12 @@ static const struct cdns_torrent_data cdns_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_xcvr_diag_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_pcie_xcvr_diag_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_usb_xcvr_diag_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -3838,6 +4062,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, [INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_dp_xcvr_diag_ln_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -3890,6 +4117,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, [INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_dp_xcvr_diag_ln_vals, + }, }, }, .pcs_cmn_vals = { @@ -3914,6 +4144,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_phy_pcs_cmn_vals, + }, }, }, .cmn_vals = { @@ -3936,6 +4169,12 @@ static const struct cdns_torrent_data cdns_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -3958,6 +4197,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = NULL, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4010,6 +4252,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_cmn_vals, + }, }, }, }, @@ -4033,6 +4278,12 @@ static const struct cdns_torrent_data cdns_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4055,6 +4306,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = NULL, [INTERNAL_SSC] = NULL, }, + [TYPE_DP] = { + [NO_SSC] = NULL, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4107,6 +4361,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, }, }, }, @@ -4130,6 +4387,12 @@ static const struct cdns_torrent_data cdns_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4152,6 +4415,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4204,6 +4470,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, }, }, }, @@ -4217,6 +4486,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_link_cmn_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &pcie_dp_link_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &usb_dp_link_cmn_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4239,6 +4514,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &pcie_usb_link_cmn_vals, [INTERNAL_SSC] = &pcie_usb_link_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_dp_link_cmn_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4291,6 +4569,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_dp_link_cmn_vals, + }, }, }, .xcvr_diag_vals = { @@ -4298,6 +4579,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_xcvr_diag_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_pcie_xcvr_diag_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_usb_xcvr_diag_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4320,6 +4607,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, [INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_dp_xcvr_diag_ln_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4372,6 +4662,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, [INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_dp_xcvr_diag_ln_vals, + }, }, }, .pcs_cmn_vals = { @@ -4396,6 +4689,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_phy_pcs_cmn_vals, + }, }, }, .cmn_vals = { @@ -4418,6 +4714,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4440,6 +4742,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = NULL, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4492,6 +4797,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_cmn_vals, + }, }, }, }, @@ -4515,6 +4823,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4537,6 +4851,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = NULL, [INTERNAL_SSC] = NULL, }, + [TYPE_DP] = { + [NO_SSC] = NULL, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4589,6 +4906,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, }, }, }, @@ -4612,6 +4932,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4634,6 +4960,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4686,6 +5015,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, }, }, }, diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c index afc63552ecaf..d4c92498ad1e 100644 --- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c +++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c @@ -206,7 +206,6 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct imx8_pcie_phy *imx8_phy; - struct resource *res; imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL); if (!imx8_phy) @@ -259,8 +258,7 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev) "Failed to get PCIE PHY PERST control\n"); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - imx8_phy->base = devm_ioremap_resource(dev, res); + imx8_phy->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(imx8_phy->base)) return PTR_ERR(imx8_phy->base); diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig index d3b92c288554..6c89136fc8c2 100644 --- a/drivers/phy/hisilicon/Kconfig +++ b/drivers/phy/hisilicon/Kconfig @@ -54,7 +54,7 @@ config PHY_HISTB_COMBPHY config PHY_HISI_INNO_USB2 tristate "HiSilicon INNO USB2 PHY support" - depends on (ARCH_HISI && ARM64) || COMPILE_TEST + depends on ARCH_HISI || COMPILE_TEST select GENERIC_PHY select MFD_SYSCON help diff --git a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c index b133ae06757a..15dafe359552 100644 --- a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c +++ b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c @@ -9,7 +9,7 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/platform_device.h> +#include <linux/of_device.h> #include <linux/phy/phy.h> #include <linux/reset.h> @@ -20,12 +20,25 @@ #define PHY_CLK_STABLE_TIME 2 /* unit:ms */ #define UTMI_RST_COMPLETE_TIME 2 /* unit:ms */ #define POR_RST_COMPLETE_TIME 300 /* unit:us */ + +#define PHY_TYPE_0 0 +#define PHY_TYPE_1 1 + #define PHY_TEST_DATA GENMASK(7, 0) -#define PHY_TEST_ADDR GENMASK(15, 8) -#define PHY_TEST_PORT GENMASK(18, 16) -#define PHY_TEST_WREN BIT(21) -#define PHY_TEST_CLK BIT(22) /* rising edge active */ -#define PHY_TEST_RST BIT(23) /* low active */ +#define PHY_TEST_ADDR_OFFSET 8 +#define PHY0_TEST_ADDR GENMASK(15, 8) +#define PHY0_TEST_PORT_OFFSET 16 +#define PHY0_TEST_PORT GENMASK(18, 16) +#define PHY0_TEST_WREN BIT(21) +#define PHY0_TEST_CLK BIT(22) /* rising edge active */ +#define PHY0_TEST_RST BIT(23) /* low active */ +#define PHY1_TEST_ADDR GENMASK(11, 8) +#define PHY1_TEST_PORT_OFFSET 12 +#define PHY1_TEST_PORT BIT(12) +#define PHY1_TEST_WREN BIT(13) +#define PHY1_TEST_CLK BIT(14) /* rising edge active */ +#define PHY1_TEST_RST BIT(15) /* low active */ + #define PHY_CLK_ENABLE BIT(2) struct hisi_inno_phy_port { @@ -37,6 +50,7 @@ struct hisi_inno_phy_priv { void __iomem *mmio; struct clk *ref_clk; struct reset_control *por_rst; + unsigned int type; struct hisi_inno_phy_port ports[INNO_PHY_PORT_NUM]; }; @@ -45,17 +59,27 @@ static void hisi_inno_phy_write_reg(struct hisi_inno_phy_priv *priv, { void __iomem *reg = priv->mmio; u32 val; - - val = (data & PHY_TEST_DATA) | - ((addr << 8) & PHY_TEST_ADDR) | - ((port << 16) & PHY_TEST_PORT) | - PHY_TEST_WREN | PHY_TEST_RST; + u32 value; + + if (priv->type == PHY_TYPE_0) + val = (data & PHY_TEST_DATA) | + ((addr << PHY_TEST_ADDR_OFFSET) & PHY0_TEST_ADDR) | + ((port << PHY0_TEST_PORT_OFFSET) & PHY0_TEST_PORT) | + PHY0_TEST_WREN | PHY0_TEST_RST; + else + val = (data & PHY_TEST_DATA) | + ((addr << PHY_TEST_ADDR_OFFSET) & PHY1_TEST_ADDR) | + ((port << PHY1_TEST_PORT_OFFSET) & PHY1_TEST_PORT) | + PHY1_TEST_WREN | PHY1_TEST_RST; writel(val, reg); - val |= PHY_TEST_CLK; - writel(val, reg); + value = val; + if (priv->type == PHY_TYPE_0) + value |= PHY0_TEST_CLK; + else + value |= PHY1_TEST_CLK; + writel(value, reg); - val &= ~PHY_TEST_CLK; writel(val, reg); } @@ -135,6 +159,8 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) if (IS_ERR(priv->por_rst)) return PTR_ERR(priv->por_rst); + priv->type = (uintptr_t) of_device_get_match_data(dev); + for_each_child_of_node(np, child) { struct reset_control *rst; struct phy *phy; @@ -170,8 +196,12 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) } static const struct of_device_id hisi_inno_phy_of_match[] = { - { .compatible = "hisilicon,inno-usb2-phy", }, - { .compatible = "hisilicon,hi3798cv200-usb2-phy", }, + { .compatible = "hisilicon,inno-usb2-phy", + .data = (void *) PHY_TYPE_0 }, + { .compatible = "hisilicon,hi3798cv200-usb2-phy", + .data = (void *) PHY_TYPE_0 }, + { .compatible = "hisilicon,hi3798mv100-usb2-phy", + .data = (void *) PHY_TYPE_1 }, { }, }; MODULE_DEVICE_TABLE(of, hisi_inno_phy_of_match); diff --git a/drivers/phy/microchip/sparx5_serdes.c b/drivers/phy/microchip/sparx5_serdes.c index ab1b0986aa67..01bd5ea620c5 100644 --- a/drivers/phy/microchip/sparx5_serdes.c +++ b/drivers/phy/microchip/sparx5_serdes.c @@ -25,12 +25,17 @@ #define SPX5_SERDES_10G_START 13 #define SPX5_SERDES_25G_START 25 +#define SPX5_SERDES_6G10G_CNT SPX5_SERDES_25G_START + +/* Optimal power settings from GUC */ +#define SPX5_SERDES_QUIET_MODE_VAL 0x01ef4e0c enum sparx5_10g28cmu_mode { SPX5_SD10G28_CMU_MAIN = 0, SPX5_SD10G28_CMU_AUX1 = 1, SPX5_SD10G28_CMU_AUX2 = 3, SPX5_SD10G28_CMU_NONE = 4, + SPX5_SD10G28_CMU_MAX, }; enum sparx5_sd25g28_mode_preset_type { @@ -922,6 +927,222 @@ static void sparx5_sd10g28_get_params(struct sparx5_serdes_macro *macro, *params = init; } +static int sparx5_cmu_apply_cfg(struct sparx5_serdes_private *priv, + u32 cmu_idx, + void __iomem *cmu_tgt, + void __iomem *cmu_cfg_tgt, + u32 spd10g) +{ + void __iomem **regs = priv->regs; + struct device *dev = priv->dev; + int value; + + cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); + cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); + + if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || + cmu_idx == 10 || cmu_idx == 13) { + spd10g = 0; + } + + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(1), + SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, + cmu_cfg_tgt, + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), + SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, + cmu_cfg_tgt, + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(1), + SD_CMU_CFG_SD_CMU_CFG_CMU_RST, + cmu_cfg_tgt, + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT_SET(0x1) | + SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT_SET(0x1) | + SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT_SET(0x1) | + SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT_SET(0x1) | + SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(0x0), + SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT | + SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT | + SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT | + SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT | + SD_CMU_CMU_45_R_EN_RATECHG_CTRL, + cmu_tgt, + SD_CMU_CMU_45(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(0), + SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0, + cmu_tgt, + SD_CMU_CMU_47(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(0), + SD_CMU_CMU_1B_CFG_RESERVE_7_0, + cmu_tgt, + SD_CMU_CMU_1B(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_JC_BYP_SET(0x1), + SD_CMU_CMU_0D_CFG_JC_BYP, + cmu_tgt, + SD_CMU_CMU_0D(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_1F_CFG_VTUNE_SEL_SET(1), + SD_CMU_CMU_1F_CFG_VTUNE_SEL, + cmu_tgt, + SD_CMU_CMU_1F(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_SET(3), + SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0, + cmu_tgt, + SD_CMU_CMU_00(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_SET(3), + SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, + cmu_tgt, + SD_CMU_CMU_05(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(1), + SD_CMU_CMU_30_R_PLL_DLOL_EN, + cmu_tgt, + SD_CMU_CMU_30(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_09_CFG_SW_10G_SET(spd10g), + SD_CMU_CMU_09_CFG_SW_10G, + cmu_tgt, + SD_CMU_CMU_09(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(0), + SD_CMU_CFG_SD_CMU_CFG_CMU_RST, + cmu_cfg_tgt, + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); + + msleep(20); + + sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(0), + SD_CMU_CMU_44_R_PLL_RSTN, + cmu_tgt, + SD_CMU_CMU_44(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(1), + SD_CMU_CMU_44_R_PLL_RSTN, + cmu_tgt, + SD_CMU_CMU_44(cmu_idx)); + + msleep(20); + + value = readl(sdx5_addr(regs, SD_CMU_CMU_E0(cmu_idx))); + value = SD_CMU_CMU_E0_PLL_LOL_UDL_GET(value); + + if (value) { + dev_err(dev, "CMU PLL Loss of Lock: 0x%x\n", value); + return -EINVAL; + } + sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD_SET(0), + SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD, + cmu_tgt, + SD_CMU_CMU_0D(cmu_idx)); + return 0; +} + +static int sparx5_cmu_cfg(struct sparx5_serdes_private *priv, u32 cmu_idx) +{ + void __iomem *cmu_tgt, *cmu_cfg_tgt; + u32 spd10g = 1; + + if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || + cmu_idx == 10 || cmu_idx == 13) { + spd10g = 0; + } + + cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); + cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); + + return sparx5_cmu_apply_cfg(priv, cmu_idx, cmu_tgt, cmu_cfg_tgt, spd10g); +} + +/* Map of 6G/10G serdes mode and index to CMU index. */ +static const int +sparx5_serdes_cmu_map[SPX5_SD10G28_CMU_MAX][SPX5_SERDES_6G10G_CNT] = { + [SPX5_SD10G28_CMU_MAIN] = { 2, 2, 2, 2, 2, + 2, 2, 2, 5, 5, + 5, 5, 5, 5, 5, + 5, 8, 11, 11, 11, + 11, 11, 11, 11, 11 }, + [SPX5_SD10G28_CMU_AUX1] = { 0, 0, 3, 3, 3, + 3, 3, 3, 3, 3, + 6, 6, 6, 6, 6, + 6, 6, 9, 9, 12, + 12, 12, 12, 12, 12 }, + [SPX5_SD10G28_CMU_AUX2] = { 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, + 4, 4, 7, 7, 7, + 7, 7, 10, 10, 10, + 10, 13, 13, 13, 13 }, + [SPX5_SD10G28_CMU_NONE] = { 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, + 4, 4, 7, 7, 7, + 7, 7, 10, 10, 10, + 10, 13, 13, 13, 13 }, +}; + +/* Get the index of the CMU which provides the clock for the specified serdes + * mode and index. + */ +static int sparx5_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index) +{ + return sparx5_serdes_cmu_map[mode][sd_index]; +} + +static void sparx5_serdes_cmu_power_off(struct sparx5_serdes_private *priv) +{ + void __iomem *cmu_inst, *cmu_cfg_inst; + int i; + + /* Power down each CMU */ + for (i = 0; i < SPX5_CMU_MAX; i++) { + cmu_inst = sdx5_inst_get(priv, TARGET_SD_CMU, i); + cmu_cfg_inst = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, i); + + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), + SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, cmu_cfg_inst, + SD_CMU_CFG_SD_CMU_CFG(0)); + + sdx5_inst_rmw(SD_CMU_CMU_05_CFG_REFCK_TERM_EN_SET(0), + SD_CMU_CMU_05_CFG_REFCK_TERM_EN, cmu_inst, + SD_CMU_CMU_05(0)); + + sdx5_inst_rmw(SD_CMU_CMU_09_CFG_EN_TX_CK_DN_SET(0), + SD_CMU_CMU_09_CFG_EN_TX_CK_DN, cmu_inst, + SD_CMU_CMU_09(0)); + + sdx5_inst_rmw(SD_CMU_CMU_06_CFG_VCO_PD_SET(1), + SD_CMU_CMU_06_CFG_VCO_PD, cmu_inst, + SD_CMU_CMU_06(0)); + + sdx5_inst_rmw(SD_CMU_CMU_09_CFG_EN_TX_CK_UP_SET(0), + SD_CMU_CMU_09_CFG_EN_TX_CK_UP, cmu_inst, + SD_CMU_CMU_09(0)); + + sdx5_inst_rmw(SD_CMU_CMU_08_CFG_CK_TREE_PD_SET(1), + SD_CMU_CMU_08_CFG_CK_TREE_PD, cmu_inst, + SD_CMU_CMU_08(0)); + + sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_REFCK_PD_SET(1) | + SD_CMU_CMU_0D_CFG_PD_DIV64_SET(1) | + SD_CMU_CMU_0D_CFG_PD_DIV66_SET(1), + SD_CMU_CMU_0D_CFG_REFCK_PD | + SD_CMU_CMU_0D_CFG_PD_DIV64 | + SD_CMU_CMU_0D_CFG_PD_DIV66, cmu_inst, + SD_CMU_CMU_0D(0)); + + sdx5_inst_rmw(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_SET(1), + SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, cmu_inst, + SD_CMU_CMU_06(0)); + } +} + static void sparx5_sd25g28_reset(void __iomem *regs[], struct sparx5_sd25g28_params *params, u32 sd_index) @@ -1422,7 +1643,17 @@ static int sparx5_sd10g28_apply_params(struct sparx5_serdes_macro *macro, u32 lane_index = macro->sidx; u32 sd_index = macro->stpidx; void __iomem *sd_inst; - u32 value; + u32 value, cmu_idx; + int err; + + /* Do not configure serdes if CMU is not to be configured too */ + if (params->skip_cmu_cfg) + return 0; + + cmu_idx = sparx5_serdes_cmu_get(params->cmu_sel, lane_index); + err = sparx5_cmu_cfg(priv, cmu_idx); + if (err) + return err; if (params->is_6g) sd_inst = sdx5_inst_get(priv, TARGET_SD6G_LANE, sd_index); @@ -1884,6 +2115,7 @@ static int sparx5_sd10g28_config(struct sparx5_serdes_macro *macro, bool reset) .rxinvert = 1, .txswing = 240, .reg_rst = reset, + .skip_cmu_cfg = reset, }; int err; @@ -1899,7 +2131,7 @@ static int sparx5_sd10g28_config(struct sparx5_serdes_macro *macro, bool reset) static int sparx5_serdes_power_save(struct sparx5_serdes_macro *macro, u32 pwdn) { struct sparx5_serdes_private *priv = macro->priv; - void __iomem *sd_inst; + void __iomem *sd_inst, *sd_lane_inst; if (macro->serdestype == SPX5_SDT_6G) sd_inst = sdx5_inst_get(priv, TARGET_SD6G_LANE, macro->stpidx); @@ -1909,12 +2141,36 @@ static int sparx5_serdes_power_save(struct sparx5_serdes_macro *macro, u32 pwdn) sd_inst = sdx5_inst_get(priv, TARGET_SD25G_LANE, macro->stpidx); if (macro->serdestype == SPX5_SDT_25G) { + sd_lane_inst = sdx5_inst_get(priv, TARGET_SD_LANE_25G, + macro->stpidx); + /* Take serdes out of reset */ + sdx5_inst_rmw(SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST_SET(0), + SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST, sd_lane_inst, + SD_LANE_25G_SD_LANE_CFG(0)); + + /* Configure optimal settings for quiet mode */ + sdx5_inst_rmw(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_SET(SPX5_SERDES_QUIET_MODE_VAL), + SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, + sd_lane_inst, SD_LANE_25G_QUIET_MODE_6G(0)); + sdx5_inst_rmw(SD25G_LANE_LANE_04_LN_CFG_PD_DRIVER_SET(pwdn), SD25G_LANE_LANE_04_LN_CFG_PD_DRIVER, sd_inst, SD25G_LANE_LANE_04(0)); } else { /* 6G and 10G */ + sd_lane_inst = sdx5_inst_get(priv, TARGET_SD_LANE, macro->sidx); + + /* Take serdes out of reset */ + sdx5_inst_rmw(SD_LANE_SD_LANE_CFG_EXT_CFG_RST_SET(0), + SD_LANE_SD_LANE_CFG_EXT_CFG_RST, sd_lane_inst, + SD_LANE_SD_LANE_CFG(0)); + + /* Configure optimal settings for quiet mode */ + sdx5_inst_rmw(SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(SPX5_SERDES_QUIET_MODE_VAL), + SD_LANE_QUIET_MODE_6G_QUIET_MODE, sd_lane_inst, + SD_LANE_QUIET_MODE_6G(0)); + sdx5_inst_rmw(SD10G_LANE_LANE_06_CFG_PD_DRIVER_SET(pwdn), SD10G_LANE_LANE_06_CFG_PD_DRIVER, sd_inst, @@ -1939,159 +2195,6 @@ static int sparx5_serdes_clock_config(struct sparx5_serdes_macro *macro) return 0; } -static int sparx5_cmu_apply_cfg(struct sparx5_serdes_private *priv, - u32 cmu_idx, - void __iomem *cmu_tgt, - void __iomem *cmu_cfg_tgt, - u32 spd10g) -{ - void __iomem **regs = priv->regs; - struct device *dev = priv->dev; - int value; - - cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); - cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); - - if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || - cmu_idx == 10 || cmu_idx == 13) { - spd10g = 0; - } - - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(1), - SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, - cmu_cfg_tgt, - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), - SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, - cmu_cfg_tgt, - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(1), - SD_CMU_CFG_SD_CMU_CFG_CMU_RST, - cmu_cfg_tgt, - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT_SET(0x1) | - SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT_SET(0x1) | - SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT_SET(0x1) | - SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT_SET(0x1) | - SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(0x0), - SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT | - SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT | - SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT | - SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT | - SD_CMU_CMU_45_R_EN_RATECHG_CTRL, - cmu_tgt, - SD_CMU_CMU_45(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(0), - SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0, - cmu_tgt, - SD_CMU_CMU_47(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(0), - SD_CMU_CMU_1B_CFG_RESERVE_7_0, - cmu_tgt, - SD_CMU_CMU_1B(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_JC_BYP_SET(0x1), - SD_CMU_CMU_0D_CFG_JC_BYP, - cmu_tgt, - SD_CMU_CMU_0D(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_1F_CFG_VTUNE_SEL_SET(1), - SD_CMU_CMU_1F_CFG_VTUNE_SEL, - cmu_tgt, - SD_CMU_CMU_1F(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_SET(3), - SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0, - cmu_tgt, - SD_CMU_CMU_00(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_SET(3), - SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, - cmu_tgt, - SD_CMU_CMU_05(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(1), - SD_CMU_CMU_30_R_PLL_DLOL_EN, - cmu_tgt, - SD_CMU_CMU_30(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_09_CFG_SW_10G_SET(spd10g), - SD_CMU_CMU_09_CFG_SW_10G, - cmu_tgt, - SD_CMU_CMU_09(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(0), - SD_CMU_CFG_SD_CMU_CFG_CMU_RST, - cmu_cfg_tgt, - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); - - msleep(20); - - sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(0), - SD_CMU_CMU_44_R_PLL_RSTN, - cmu_tgt, - SD_CMU_CMU_44(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(1), - SD_CMU_CMU_44_R_PLL_RSTN, - cmu_tgt, - SD_CMU_CMU_44(cmu_idx)); - - msleep(20); - - value = readl(sdx5_addr(regs, SD_CMU_CMU_E0(cmu_idx))); - value = SD_CMU_CMU_E0_PLL_LOL_UDL_GET(value); - - if (value) { - dev_err(dev, "CMU PLL Loss of Lock: 0x%x\n", value); - return -EINVAL; - } - sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD_SET(0), - SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD, - cmu_tgt, - SD_CMU_CMU_0D(cmu_idx)); - return 0; -} - -static int sparx5_cmu_cfg(struct sparx5_serdes_private *priv, u32 cmu_idx) -{ - void __iomem *cmu_tgt, *cmu_cfg_tgt; - u32 spd10g = 1; - - if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || - cmu_idx == 10 || cmu_idx == 13) { - spd10g = 0; - } - - cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); - cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); - - return sparx5_cmu_apply_cfg(priv, cmu_idx, cmu_tgt, cmu_cfg_tgt, spd10g); -} - -static int sparx5_serdes_cmu_enable(struct sparx5_serdes_private *priv) -{ - int idx, err = 0; - - if (!priv->cmu_enabled) { - for (idx = 0; idx < SPX5_CMU_MAX; idx++) { - err = sparx5_cmu_cfg(priv, idx); - if (err) { - dev_err(priv->dev, "CMU %u, error: %d\n", idx, err); - goto leave; - } - } - priv->cmu_enabled = true; - } -leave: - return err; -} - static int sparx5_serdes_get_serdesmode(phy_interface_t portmode, int speed) { switch (portmode) { @@ -2120,10 +2223,6 @@ static int sparx5_serdes_config(struct sparx5_serdes_macro *macro) int serdesmode; int err; - err = sparx5_serdes_cmu_enable(macro->priv); - if (err) - return err; - serdesmode = sparx5_serdes_get_serdesmode(macro->portmode, macro->speed); if (serdesmode < 0) { dev_err(dev, "SerDes %u, interface not supported: %s\n", @@ -2215,9 +2314,6 @@ static int sparx5_serdes_reset(struct phy *phy) struct sparx5_serdes_macro *macro = phy_get_drvdata(phy); int err; - err = sparx5_serdes_cmu_enable(macro->priv); - if (err) - return err; if (macro->serdestype == SPX5_SDT_25G) err = sparx5_sd25g28_config(macro, true); else @@ -2308,6 +2404,9 @@ static int sparx5_phy_create(struct sparx5_serdes_private *priv, phy_set_drvdata(*phy, macro); + /* Power off serdes by default */ + sparx5_serdes_power_off(*phy); + return 0; } @@ -2491,6 +2590,9 @@ static int sparx5_serdes_probe(struct platform_device *pdev) return err; } + /* Power down all CMUs by default */ + sparx5_serdes_cmu_power_off(priv); + provider = devm_of_phy_provider_register(priv->dev, sparx5_serdes_xlate); return PTR_ERR_OR_ZERO(provider); diff --git a/drivers/phy/microchip/sparx5_serdes.h b/drivers/phy/microchip/sparx5_serdes.h index 0a3e496e6210..13f94a29225a 100644 --- a/drivers/phy/microchip/sparx5_serdes.h +++ b/drivers/phy/microchip/sparx5_serdes.h @@ -30,7 +30,6 @@ struct sparx5_serdes_private { struct device *dev; void __iomem *regs[NUM_TARGETS]; struct phy *phys[SPX5_SERDES_MAX]; - bool cmu_enabled; unsigned long coreclock; }; diff --git a/drivers/phy/microchip/sparx5_serdes_regs.h b/drivers/phy/microchip/sparx5_serdes_regs.h index b96386a4df5a..d0543fd3dc94 100644 --- a/drivers/phy/microchip/sparx5_serdes_regs.h +++ b/drivers/phy/microchip/sparx5_serdes_regs.h @@ -2149,6 +2149,92 @@ enum sparx5_serdes_target { #define SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_GET(x)\ FIELD_GET(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, x) +/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_06 */ +#define SD_CMU_CMU_06(t) \ + __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 4, 0, 1, 4) + +#define SD_CMU_CMU_06_CFG_DISLOS BIT(0) +#define SD_CMU_CMU_06_CFG_DISLOS_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_DISLOS, x) +#define SD_CMU_CMU_06_CFG_DISLOS_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_DISLOS, x) + +#define SD_CMU_CMU_06_CFG_DISLOL BIT(1) +#define SD_CMU_CMU_06_CFG_DISLOL_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_DISLOL, x) +#define SD_CMU_CMU_06_CFG_DISLOL_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_DISLOL, x) + +#define SD_CMU_CMU_06_CFG_DCLOL BIT(2) +#define SD_CMU_CMU_06_CFG_DCLOL_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_DCLOL, x) +#define SD_CMU_CMU_06_CFG_DCLOL_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_DCLOL, x) + +#define SD_CMU_CMU_06_CFG_FORCE_RX_FILT BIT(3) +#define SD_CMU_CMU_06_CFG_FORCE_RX_FILT_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_FORCE_RX_FILT, x) +#define SD_CMU_CMU_06_CFG_FORCE_RX_FILT_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_FORCE_RX_FILT, x) + +#define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD BIT(4) +#define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, x) +#define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, x) + +#define SD_CMU_CMU_06_CFG_VCO_PD BIT(5) +#define SD_CMU_CMU_06_CFG_VCO_PD_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_PD, x) +#define SD_CMU_CMU_06_CFG_VCO_PD_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_VCO_PD, x) + +#define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN BIT(6) +#define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_CAL_RESETN, x) +#define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_RESETN, x) + +#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP BIT(7) +#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x) +#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x) + +/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_08 */ +#define SD_CMU_CMU_08(t) \ + __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 12, 0, 1, 4) + +#define SD_CMU_CMU_08_CFG_VFILT2PAD BIT(0) +#define SD_CMU_CMU_08_CFG_VFILT2PAD_SET(x)\ + FIELD_PREP(SD_CMU_CMU_08_CFG_VFILT2PAD, x) +#define SD_CMU_CMU_08_CFG_VFILT2PAD_GET(x)\ + FIELD_GET(SD_CMU_CMU_08_CFG_VFILT2PAD, x) + +#define SD_CMU_CMU_08_CFG_EN_DUMMY BIT(1) +#define SD_CMU_CMU_08_CFG_EN_DUMMY_SET(x)\ + FIELD_PREP(SD_CMU_CMU_08_CFG_EN_DUMMY, x) +#define SD_CMU_CMU_08_CFG_EN_DUMMY_GET(x)\ + FIELD_GET(SD_CMU_CMU_08_CFG_EN_DUMMY, x) + +#define SD_CMU_CMU_08_CFG_CK_TREE_PD BIT(2) +#define SD_CMU_CMU_08_CFG_CK_TREE_PD_SET(x)\ + FIELD_PREP(SD_CMU_CMU_08_CFG_CK_TREE_PD, x) +#define SD_CMU_CMU_08_CFG_CK_TREE_PD_GET(x)\ + FIELD_GET(SD_CMU_CMU_08_CFG_CK_TREE_PD, x) + +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN BIT(3) +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_SET(x)\ + FIELD_PREP(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN, x) +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_GET(x)\ + FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN, x) + +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN BIT(4) +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_SET(x)\ + FIELD_PREP(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x) +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_GET(x)\ + FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x) + /* SD10G_CMU_TARGET:CMU_GRP_1:CMU_09 */ #define SD_CMU_CMU_09(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 16, 0, 1, 4) @@ -2443,6 +2529,16 @@ enum sparx5_serdes_target { #define SD_LANE_SD_LANE_STAT_DBG_OBS_GET(x)\ FIELD_GET(SD_LANE_SD_LANE_STAT_DBG_OBS, x) +/* SD_LANE_TARGET:SD_PWR_CFG:QUIET_MODE_6G */ +#define SD_LANE_QUIET_MODE_6G(t) \ + __REG(TARGET_SD_LANE, t, 25, 24, 0, 1, 8, 4, 0, 1, 4) + +#define SD_LANE_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0) +#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(x)\ + FIELD_PREP(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x) +#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_GET(x)\ + FIELD_GET(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x) + /* SD_LANE_TARGET:CFG_STAT_FX100:MISC */ #define SD_LANE_MISC(t) __REG(TARGET_SD_LANE, t, 25, 56, 0, 1, 56, 0, 0, 1, 4) @@ -2692,4 +2788,14 @@ enum sparx5_serdes_target { #define SD_LANE_25G_SD_LANE_STAT_DBG_OBS_GET(x)\ FIELD_GET(SD_LANE_25G_SD_LANE_STAT_DBG_OBS, x) +/* SD25G_CFG_TARGET:SD_PWR_CFG:QUIET_MODE_6G */ +#define SD_LANE_25G_QUIET_MODE_6G(t) \ + __REG(TARGET_SD_LANE_25G, t, 8, 28, 0, 1, 8, 4, 0, 1, 4) + +#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0) +#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_SET(x)\ + FIELD_PREP(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, x) +#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_GET(x)\ + FIELD_GET(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, x) + #endif /* _SPARX5_SERDES_REGS_H_ */ diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c index a49711c5a63d..6f2798bbe513 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c @@ -139,6 +139,88 @@ static const unsigned int qmp_v5_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V5_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR, }; +static const struct qmp_phy_init_tbl ipq9574_usb3_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), + /* PLL and Loop filter settings */ + QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x68), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0xab), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x09), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x29), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), + /* SSC settings */ + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x7d), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x05), +}; + +static const struct qmp_phy_init_tbl ipq9574_usb3_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), + QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), + QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), +}; + +static const struct qmp_phy_init_tbl ipq9574_usb3_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6c), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0c), +}; + +static const struct qmp_phy_init_tbl ipq9574_usb3_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0e), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), +}; + static const struct qmp_phy_init_tbl ipq8074_usb3_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), @@ -1408,6 +1490,26 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), }; +static const struct qmp_phy_init_tbl sa8775p_usb3_uniphy_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG1, 0xc4), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG2, 0x89), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG3, 0x20), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG6, 0x13), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0xaa), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCS_TX_RX_CONFIG, 0x0c), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_POWER_STATE_CONFIG1, 0x6f), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_CDR_RESET_TIME, 0x0a), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0x88), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x13), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG1, 0x4b), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG5, 0x10), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), +}; + struct qmp_usb_offsets { u16 serdes; u16 pcs; @@ -1558,6 +1660,14 @@ static const char * const qmp_phy_vreg_l[] = { "vdda-phy", "vdda-pll", }; +static const struct qmp_usb_offsets qmp_usb_offsets_ipq9574 = { + .serdes = 0, + .pcs = 0x800, + .pcs_usb = 0x800, + .tx = 0x200, + .rx = 0x400, +}; + static const struct qmp_usb_offsets qmp_usb_offsets_v5 = { .serdes = 0, .pcs = 0x0200, @@ -1586,6 +1696,28 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { .regs = qmp_v3_usb3phy_regs_layout, }; +static const struct qmp_phy_cfg ipq9574_usb3phy_cfg = { + .lanes = 1, + + .offsets = &qmp_usb_offsets_ipq9574, + + .serdes_tbl = ipq9574_usb3_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(ipq9574_usb3_serdes_tbl), + .tx_tbl = ipq9574_usb3_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(ipq9574_usb3_tx_tbl), + .rx_tbl = ipq9574_usb3_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(ipq9574_usb3_rx_tbl), + .pcs_tbl = ipq9574_usb3_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(ipq9574_usb3_pcs_tbl), + .clk_list = msm8996_phy_clk_l, + .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), + .reset_list = qcm2290_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v3_usb3phy_regs_layout, +}; + static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { .lanes = 1, @@ -1629,6 +1761,28 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { .has_phy_dp_com_ctrl = true, }; +static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = { + .lanes = 1, + + .offsets = &qmp_usb_offsets_v5, + + .serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_serdes_tbl), + .tx_tbl = sc8280xp_usb3_uniphy_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_tx_tbl), + .rx_tbl = sc8280xp_usb3_uniphy_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_rx_tbl), + .pcs_tbl = sa8775p_usb3_uniphy_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_tbl), + .clk_list = qmp_v4_phy_clk_l, + .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), + .reset_list = qcm2290_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v5_usb3phy_regs_layout, +}; + static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { .lanes = 2, @@ -2589,6 +2743,9 @@ static const struct of_device_id qmp_usb_of_match_table[] = { .compatible = "qcom,ipq8074-qmp-usb3-phy", .data = &ipq8074_usb3phy_cfg, }, { + .compatible = "qcom,ipq9574-qmp-usb3-phy", + .data = &ipq9574_usb3phy_cfg, + }, { .compatible = "qcom,msm8996-qmp-usb3-phy", .data = &msm8996_usb3phy_cfg, }, { @@ -2598,6 +2755,9 @@ static const struct of_device_id qmp_usb_of_match_table[] = { .compatible = "qcom,qcm2290-qmp-usb3-phy", .data = &qcm2290_usb3phy_cfg, }, { + .compatible = "qcom,sa8775p-qmp-usb3-uni-phy", + .data = &sa8775p_usb3_uniphy_cfg, + }, { .compatible = "qcom,sc7180-qmp-usb3-phy", .data = &sc7180_usb3phy_cfg, }, { diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 2ef638b32e8f..bec6e40d5280 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -912,6 +912,9 @@ static const struct of_device_id qusb2_phy_of_match_table[] = { .compatible = "qcom,ipq8074-qusb2-phy", .data = &msm8996_phy_cfg, }, { + .compatible = "qcom,ipq9574-qusb2-phy", + .data = &ipq6018_phy_cfg, + }, { .compatible = "qcom,msm8953-qusb2-phy", .data = &msm8996_phy_cfg, }, { diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig index 3ccaabf2850a..f10afa3d7ff5 100644 --- a/drivers/phy/samsung/Kconfig +++ b/drivers/phy/samsung/Kconfig @@ -59,7 +59,7 @@ config PHY_EXYNOS4210_USB2 config PHY_EXYNOS4X12_USB2 bool depends on PHY_SAMSUNG_USB2 - default SOC_EXYNOS3250 || SOC_EXYNOS4412 + default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412 config PHY_EXYNOS5250_USB2 bool diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c index 8c667819c39a..6286cf25a426 100644 --- a/drivers/phy/ti/phy-gmii-sel.c +++ b/drivers/phy/ti/phy-gmii-sel.c @@ -23,7 +23,9 @@ #define AM33XX_GMII_SEL_MODE_RGMII 2 /* J72xx SoC specific definitions for the CONTROL port */ +#define J72XX_GMII_SEL_MODE_SGMII 3 #define J72XX_GMII_SEL_MODE_QSGMII 4 +#define J72XX_GMII_SEL_MODE_USXGMII 5 #define J72XX_GMII_SEL_MODE_QSGMII_SUB 6 #define PHY_GMII_PORT(n) BIT((n) - 1) @@ -106,6 +108,20 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode) gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII_SUB; break; + case PHY_INTERFACE_MODE_SGMII: + if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_SGMII))) + goto unsupported; + else + gmii_sel_mode = J72XX_GMII_SEL_MODE_SGMII; + break; + + case PHY_INTERFACE_MODE_USXGMII: + if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_USXGMII))) + goto unsupported; + else + gmii_sel_mode = J72XX_GMII_SEL_MODE_USXGMII; + break; + default: goto unsupported; } @@ -213,7 +229,7 @@ static const struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = { .use_of_data = true, .regfields = phy_gmii_sel_fields_am654, - .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII), + .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII), .num_ports = 4, .num_qsgmii_main_ports = 1, }; @@ -222,7 +238,17 @@ static const struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = { .use_of_data = true, .regfields = phy_gmii_sel_fields_am654, - .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII), + .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII), + .num_ports = 8, + .num_qsgmii_main_ports = 2, +}; + +static const +struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j784s4 = { + .use_of_data = true, + .regfields = phy_gmii_sel_fields_am654, + .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | + BIT(PHY_INTERFACE_MODE_USXGMII), .num_ports = 8, .num_qsgmii_main_ports = 2, }; @@ -256,6 +282,10 @@ static const struct of_device_id phy_gmii_sel_id_table[] = { .compatible = "ti,j721e-cpsw9g-phy-gmii-sel", .data = &phy_gmii_sel_cpsw9g_soc_j721e, }, + { + .compatible = "ti,j784s4-cpsw9g-phy-gmii-sel", + .data = &phy_gmii_sel_cpsw9g_soc_j784s4, + }, {} }; MODULE_DEVICE_TABLE(of, phy_gmii_sel_id_table); |