Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'phy-for-6.5_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy

Pull phy updates from Vinod Koul:
"New Support:
- Debugfs support for phy core and mediatek driver
- Hisilicon inno-usb2-phy driver supporting Hi3798MV100
- Qualcomm SGMII SerDes PHY driver, SM6115 & QCM2290 QMP-USB support,
SA8775P USB PHY & USB3 UNI support, QUSB2 support for IPQ9574,
IPQ9574 USB3 PHY

UpdatesL
- Sparx5 serdes phy power optimzation
- cadence salvo usb properties and updates and torrent DP with PCIe &
USB support
- Yaml conversion for Broadcom kona USB bindings and MXS USB binding"

* tag 'phy-for-6.5_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (67 commits)
dt-bindings: phy: brcm,brcmstb-usb-phy: Fix error in "compatible" conditional schema
dt-bindings: phy: mixel,mipi-dsi-phy: Remove assigned-clock* properties
dt-bindings: phy: intel,combo-phy: restrict node name suffixes
dt-bindings: phy: qcom,usb-hs-phy: Add compatible
phy: tegra: xusb: check return value of devm_kzalloc()
phy: qcom: qmp-combo: fix Display Port PHY configuration for SM8550
phy: qcom: add the SGMII SerDes PHY driver
dt-bindings: phy: describe the Qualcomm SGMII PHY
phy: qualcomm: fix indentation in Makefile
phy: usb: suppress OC condition for 7439b2
phy: usb: Turn off phy when port is in suspend
phy: tegra: xusb: Clear the driver reference in usb-phy dev
dt-bindings: phy: mxs-usb-phy: add imx8ulp and imx8qm compatible
dt-bindings: phy: mxs-usb-phy: convert to DT schema format
dt-bindings: phy: qcom,qmp-usb: fix bindings error
dt-bindings: phy: qcom,qmp-ufs: fix the sc8180x regs
dt-bindings: phy: qcom,qmp-pcie: fix the sc8180x regs
phy: mediatek: tphy: add debugfs files
phy: core: add debugfs files
phy: fsl-imx8mp-usb: add support for phy tuning
...

+3005 -560
+2 -2
Documentation/devicetree/bindings/phy/brcm,brcmstb-usb-phy.yaml
··· 115 115 compatible: 116 116 contains: 117 117 enum: 118 - - const: brcm,bcm4908-usb-phy 119 - - const: brcm,brcmstb-usb-phy 118 + - brcm,bcm4908-usb-phy 119 + - brcm,brcmstb-usb-phy 120 120 then: 121 121 properties: 122 122 reg:
-15
Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.txt
··· 1 - BROADCOM KONA USB2 PHY 2 - 3 - Required properties: 4 - - compatible: brcm,kona-usb2-phy 5 - - reg: offset and length of the PHY registers 6 - - #phy-cells: must be 0 7 - Refer to phy/phy-bindings.txt for the generic PHY binding properties 8 - 9 - Example: 10 - 11 - usbphy: usb-phy@3f130000 { 12 - compatible = "brcm,kona-usb2-phy"; 13 - reg = <0x3f130000 0x28>; 14 - #phy-cells = <0>; 15 - };
+36
Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/phy/brcm,kona-usb2-phy.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Broadcom Kona family USB 2.0 PHY 8 + 9 + maintainers: 10 + - Florian Fainelli <f.fainelli@gmail.com> 11 + 12 + properties: 13 + compatible: 14 + const: brcm,kona-usb2-phy 15 + 16 + reg: 17 + maxItems: 1 18 + 19 + '#phy-cells': 20 + const: 0 21 + 22 + required: 23 + - compatible 24 + - reg 25 + - '#phy-cells' 26 + 27 + additionalProperties: false 28 + 29 + examples: 30 + - | 31 + usb-phy@3f130000 { 32 + compatible = "brcm,kona-usb2-phy"; 33 + reg = <0x3f130000 0x28>; 34 + #phy-cells = <0>; 35 + }; 36 + ...
+6
Documentation/devicetree/bindings/phy/cdns,salvo-phy.yaml
··· 31 31 "#phy-cells": 32 32 const: 0 33 33 34 + cdns,usb2-disconnect-threshold-microvolt: 35 + description: The microvolt threshold value utilized for detecting 36 + USB disconnection event. 37 + enum: [575, 610, 645] 38 + default: 575 39 + 34 40 required: 35 41 - compatible 36 42 - reg
+47
Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml
··· 35 35 description: 36 36 A phandle to the regulator for USB VBUS. 37 37 38 + fsl,phy-tx-vref-tune-percent: 39 + description: 40 + Tunes the HS DC level relative to the nominal level 41 + minimum: 94 42 + maximum: 124 43 + 44 + fsl,phy-tx-rise-tune-percent: 45 + description: 46 + Adjusts the rise/fall time duration of the HS waveform relative to 47 + its nominal value 48 + minimum: 97 49 + maximum: 103 50 + 51 + fsl,phy-tx-preemp-amp-tune-microamp: 52 + description: 53 + Adjust amount of current sourced to DPn and DMn after a J-to-K 54 + or K-to-J transition. Default is 0 (disabled). 55 + minimum: 0 56 + maximum: 1800 57 + 58 + fsl,phy-tx-vboost-level-microvolt: 59 + description: 60 + Adjust the boosted transmit launch pk-pk differential amplitude 61 + minimum: 880 62 + maximum: 1120 63 + 64 + fsl,phy-comp-dis-tune-percent: 65 + description: 66 + Adjust the voltage level used to detect a disconnect event at the host 67 + relative to the nominal value 68 + minimum: 91 69 + maximum: 115 70 + 71 + fsl,phy-pcs-tx-deemph-3p5db-attenuation-db: 72 + description: 73 + Adjust TX de-emphasis attenuation in dB at nominal 74 + 3.5dB point as per USB specification 75 + $ref: /schemas/types.yaml#/definitions/uint32 76 + minimum: 0 77 + maximum: 36 78 + 79 + fsl,phy-pcs-tx-swing-full-percent: 80 + description: 81 + Scaling of the voltage defined by fsl,phy-tx-vboost-level-microvolt 82 + minimum: 0 83 + maximum: 100 84 + 38 85 required: 39 86 - compatible 40 87 - reg
+128
Documentation/devicetree/bindings/phy/fsl,mxs-usbphy.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/phy/fsl,mxs-usbphy.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Freescale MXS USB Phy Device 8 + 9 + maintainers: 10 + - Xu Yang <xu.yang_2@nxp.com> 11 + 12 + properties: 13 + compatible: 14 + oneOf: 15 + - enum: 16 + - fsl,imx23-usbphy 17 + - fsl,imx7ulp-usbphy 18 + - fsl,vf610-usbphy 19 + - items: 20 + - enum: 21 + - fsl,imx28-usbphy 22 + - fsl,imx6ul-usbphy 23 + - fsl,imx6sl-usbphy 24 + - fsl,imx6sx-usbphy 25 + - fsl,imx6q-usbphy 26 + - const: fsl,imx23-usbphy 27 + - items: 28 + - const: fsl,imx6sll-usbphy 29 + - const: fsl,imx6ul-usbphy 30 + - const: fsl,imx23-usbphy 31 + - items: 32 + - enum: 33 + - fsl,imx8dxl-usbphy 34 + - fsl,imx8qm-usbphy 35 + - fsl,imx8ulp-usbphy 36 + - const: fsl,imx7ulp-usbphy 37 + 38 + reg: 39 + maxItems: 1 40 + 41 + interrupts: 42 + maxItems: 1 43 + 44 + clocks: 45 + maxItems: 1 46 + 47 + '#phy-cells': 48 + const: 0 49 + 50 + power-domains: 51 + maxItems: 1 52 + 53 + fsl,anatop: 54 + description: 55 + phandle for anatop register, it is only for imx6 SoC series. 56 + $ref: /schemas/types.yaml#/definitions/phandle 57 + 58 + phy-3p0-supply: 59 + description: 60 + One of USB PHY's power supply. Can be used to keep a good signal 61 + quality. 62 + 63 + fsl,tx-cal-45-dn-ohms: 64 + description: 65 + Resistance (in ohms) of switchable high-speed trimming resistor 66 + connected in parallel with the 45 ohm resistor that terminates 67 + the DN output signal. 68 + minimum: 35 69 + maximum: 54 70 + default: 45 71 + 72 + fsl,tx-cal-45-dp-ohms: 73 + description: 74 + Resistance (in ohms) of switchable high-speed trimming resistor 75 + connected in parallel with the 45 ohm resistor that terminates 76 + the DP output signal. 77 + minimum: 35 78 + maximum: 54 79 + default: 45 80 + 81 + fsl,tx-d-cal: 82 + description: 83 + Current trimming value (as a percentage) of the 17.78 mA TX 84 + reference current. 85 + $ref: /schemas/types.yaml#/definitions/uint32 86 + minimum: 79 87 + maximum: 119 88 + default: 100 89 + 90 + required: 91 + - compatible 92 + - reg 93 + - clocks 94 + 95 + allOf: 96 + - if: 97 + properties: 98 + compatible: 99 + oneOf: 100 + - enum: 101 + - fsl,imx6q-usbphy 102 + - fsl,imx6sl-usbphy 103 + - fsl,imx6sx-usbphy 104 + - fsl,imx6sll-usbphy 105 + - fsl,vf610-usbphy 106 + - items: 107 + - const: fsl,imx6ul-usbphy 108 + - const: fsl,imx23-usbphy 109 + then: 110 + required: 111 + - fsl,anatop 112 + 113 + additionalProperties: false 114 + 115 + examples: 116 + - | 117 + #include <dt-bindings/interrupt-controller/arm-gic.h> 118 + #include <dt-bindings/clock/imx6qdl-clock.h> 119 + 120 + usbphy1: usb-phy@20c9000 { 121 + compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; 122 + reg = <0x020c9000 0x1000>; 123 + clocks = <&clks IMX6QDL_CLK_USBPHY1>; 124 + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; 125 + fsl,anatop = <&anatop>; 126 + }; 127 + 128 + ...
+1 -1
Documentation/devicetree/bindings/phy/intel,combo-phy.yaml
··· 15 15 16 16 properties: 17 17 $nodename: 18 - pattern: "combophy(@.*|-[0-9a-f])*$" 18 + pattern: "combophy(@.*|-([0-9]|[1-9][0-9]+))?$" 19 19 20 20 compatible: 21 21 items:
-9
Documentation/devicetree/bindings/phy/mixel,mipi-dsi-phy.yaml
··· 32 32 clock-names: 33 33 const: phy_ref 34 34 35 - assigned-clocks: 36 - maxItems: 1 37 - 38 - assigned-clock-parents: 39 - maxItems: 1 40 - 41 - assigned-clock-rates: 42 - maxItems: 1 43 - 44 35 "#phy-cells": 45 36 const: 0 46 37
-33
Documentation/devicetree/bindings/phy/mxs-usb-phy.txt
··· 1 - * Freescale MXS USB Phy Device 2 - 3 - Required properties: 4 - - compatible: should contain: 5 - * "fsl,imx23-usbphy" for imx23 and imx28 6 - * "fsl,imx6q-usbphy" for imx6dq and imx6dl 7 - * "fsl,imx6sl-usbphy" for imx6sl 8 - * "fsl,vf610-usbphy" for Vybrid vf610 9 - * "fsl,imx6sx-usbphy" for imx6sx 10 - * "fsl,imx7ulp-usbphy" for imx7ulp 11 - * "fsl,imx8dxl-usbphy" for imx8dxl 12 - "fsl,imx23-usbphy" is still a fallback for other strings 13 - - reg: Should contain registers location and length 14 - - interrupts: Should contain phy interrupt 15 - - fsl,anatop: phandle for anatop register, it is only for imx6 SoC series 16 - 17 - Optional properties: 18 - - fsl,tx-cal-45-dn-ohms: Integer [35-54]. Resistance (in ohms) of switchable 19 - high-speed trimming resistor connected in parallel with the 45 ohm resistor 20 - that terminates the DN output signal. Default: 45 21 - - fsl,tx-cal-45-dp-ohms: Integer [35-54]. Resistance (in ohms) of switchable 22 - high-speed trimming resistor connected in parallel with the 45 ohm resistor 23 - that terminates the DP output signal. Default: 45 24 - - fsl,tx-d-cal: Integer [79-119]. Current trimming value (as a percentage) of 25 - the 17.78mA TX reference current. Default: 100 26 - 27 - Example: 28 - usbphy1: usb-phy@20c9000 { 29 - compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; 30 - reg = <0x020c9000 0x1000>; 31 - interrupts = <0 44 0x04>; 32 - fsl,anatop = <&anatop>; 33 - };
+3
Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml
··· 43 43 "#phy-cells": 44 44 const: 0 45 45 46 + power-domains: 47 + maxItems: 1 48 + 46 49 vdda-phy-supply: true 47 50 vdda-pll-supply: true 48 51
+1 -1
Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml
··· 203 203 compatible: 204 204 contains: 205 205 enum: 206 + - qcom,sc8180x-qmp-pcie-phy 206 207 - qcom,sm8250-qmp-gen3x2-pcie-phy 207 208 - qcom,sm8250-qmp-modem-pcie-phy 208 209 - qcom,sm8450-qmp-gen4x2-pcie-phy ··· 225 224 compatible: 226 225 contains: 227 226 enum: 228 - - qcom,sc8180x-qmp-pcie-phy 229 227 - qcom,sdm845-qmp-pcie-phy 230 228 - qcom,sdx55-qmp-pcie-phy 231 229 - qcom,sm8250-qmp-gen3x1-pcie-phy
+1 -17
Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-ufs-phy.yaml
··· 160 160 contains: 161 161 enum: 162 162 - qcom,msm8998-qmp-ufs-phy 163 + - qcom,sc8180x-qmp-ufs-phy 163 164 - qcom,sdm845-qmp-ufs-phy 164 165 - qcom,sm6350-qmp-ufs-phy 165 166 - qcom,sm8150-qmp-ufs-phy ··· 178 177 - description: PCS 179 178 - description: TX lane 2 180 179 - description: RX lane 2 181 - 182 - - if: 183 - properties: 184 - compatible: 185 - contains: 186 - enum: 187 - - qcom,sc8180x-qmp-ufs-phy 188 - then: 189 - patternProperties: 190 - "^phy@[0-9a-f]+$": 191 - properties: 192 - reg: 193 - items: 194 - - description: TX 195 - - description: RX 196 - - description: PCS 197 - - description: PCS_MISC 198 180 199 181 - if: 200 182 properties:
-27
Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-usb3-phy.yaml
··· 23 23 - qcom,ipq8074-qmp-usb3-phy 24 24 - qcom,msm8996-qmp-usb3-phy 25 25 - qcom,msm8998-qmp-usb3-phy 26 - - qcom,qcm2290-qmp-usb3-phy 27 26 - qcom,sc7180-qmp-usb3-phy 28 27 - qcom,sc8180x-qmp-usb3-phy 29 28 - qcom,sdm845-qmp-usb3-phy 30 29 - qcom,sdm845-qmp-usb3-uni-phy 31 30 - qcom,sdx55-qmp-usb3-uni-phy 32 31 - qcom,sdx65-qmp-usb3-uni-phy 33 - - qcom,sm6115-qmp-usb3-phy 34 32 - qcom,sm8150-qmp-usb3-phy 35 33 - qcom,sm8150-qmp-usb3-uni-phy 36 34 - qcom,sm8250-qmp-usb3-phy ··· 251 253 compatible: 252 254 contains: 253 255 enum: 254 - - qcom,qcm2290-qmp-usb3-phy 255 - - qcom,sm6115-qmp-usb3-phy 256 - then: 257 - properties: 258 - clocks: 259 - maxItems: 3 260 - clock-names: 261 - items: 262 - - const: cfg_ahb 263 - - const: ref 264 - - const: com_aux 265 - resets: 266 - maxItems: 2 267 - reset-names: 268 - items: 269 - - const: phy_phy 270 - - const: phy 271 - 272 - - if: 273 - properties: 274 - compatible: 275 - contains: 276 - enum: 277 256 - qcom,sdm845-qmp-usb3-phy 278 257 - qcom,sm8150-qmp-usb3-phy 279 258 - qcom,sm8350-qmp-usb3-phy ··· 293 318 enum: 294 319 - qcom,ipq6018-qmp-usb3-phy 295 320 - qcom,ipq8074-qmp-usb3-phy 296 - - qcom,qcm2290-qmp-usb3-phy 297 321 - qcom,sc7180-qmp-usb3-phy 298 322 - qcom,sc8180x-qmp-usb3-phy 299 323 - qcom,sdx55-qmp-usb3-uni-phy 300 324 - qcom,sdx65-qmp-usb3-uni-phy 301 - - qcom,sm6115-qmp-usb3-phy 302 325 - qcom,sm8150-qmp-usb3-uni-phy 303 326 - qcom,sm8250-qmp-usb3-phy 304 327 then:
+2 -1
Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
··· 18 18 oneOf: 19 19 - items: 20 20 - enum: 21 + - qcom,ipq6018-qusb2-phy 21 22 - qcom,ipq8074-qusb2-phy 23 + - qcom,ipq9574-qusb2-phy 22 24 - qcom,msm8953-qusb2-phy 23 25 - qcom,msm8996-qusb2-phy 24 26 - qcom,msm8998-qusb2-phy 25 27 - qcom,qcm2290-qusb2-phy 26 28 - qcom,sdm660-qusb2-phy 27 - - qcom,ipq6018-qusb2-phy 28 29 - qcom,sm4250-qusb2-phy 29 30 - qcom,sm6115-qusb2-phy 30 31 - items:
+55
Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm SerDes/SGMII ethernet PHY controller 8 + 9 + maintainers: 10 + - Bartosz Golaszewski <bartosz.golaszewski@linaro.org> 11 + 12 + description: 13 + The SerDes PHY sits between the MAC and the external PHY and provides 14 + separate Rx Tx lines. 15 + 16 + properties: 17 + compatible: 18 + const: qcom,sa8775p-dwmac-sgmii-phy 19 + 20 + reg: 21 + items: 22 + - description: serdes 23 + 24 + clocks: 25 + maxItems: 1 26 + 27 + clock-names: 28 + const: sgmi_ref 29 + 30 + phy-supply: 31 + description: 32 + Phandle to a regulator that provides power to the PHY. 33 + 34 + "#phy-cells": 35 + const: 0 36 + 37 + required: 38 + - compatible 39 + - reg 40 + - "#phy-cells" 41 + - clocks 42 + - clock-names 43 + 44 + additionalProperties: false 45 + 46 + examples: 47 + - | 48 + #include <dt-bindings/clock/qcom,sa8775p-gcc.h> 49 + serdes_phy: phy@8901000 { 50 + compatible = "qcom,sa8775p-dwmac-sgmii-phy"; 51 + reg = <0x08901000 0xe10>; 52 + clocks = <&gcc GCC_SGMI_CLKREF_EN>; 53 + clock-names = "sgmi_ref"; 54 + #phy-cells = <0>; 55 + };
+2 -2
Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
··· 78 78 then: 79 79 properties: 80 80 clocks: 81 - maxItems: 3 81 + minItems: 3 82 82 clock-names: 83 - maxItems: 3 83 + minItems: 3 84 84 else: 85 85 properties: 86 86 clocks:
+59 -6
Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml
··· 16 16 properties: 17 17 compatible: 18 18 enum: 19 + - qcom,ipq9574-qmp-usb3-phy 20 + - qcom,qcm2290-qmp-usb3-phy 21 + - qcom,sa8775p-qmp-usb3-uni-phy 19 22 - qcom,sc8280xp-qmp-usb3-uni-phy 23 + - qcom,sm6115-qmp-usb3-phy 20 24 21 25 reg: 22 26 maxItems: 1 ··· 29 25 maxItems: 4 30 26 31 27 clock-names: 32 - items: 33 - - const: aux 34 - - const: ref 35 - - const: com_aux 36 - - const: pipe 28 + maxItems: 4 37 29 38 30 power-domains: 39 31 maxItems: 1 ··· 60 60 - reg 61 61 - clocks 62 62 - clock-names 63 - - power-domains 64 63 - resets 65 64 - reset-names 66 65 - vdda-phy-supply ··· 67 68 - "#clock-cells" 68 69 - clock-output-names 69 70 - "#phy-cells" 71 + 72 + allOf: 73 + - if: 74 + properties: 75 + compatible: 76 + contains: 77 + enum: 78 + - qcom,ipq9574-qmp-usb3-phy 79 + then: 80 + properties: 81 + clock-names: 82 + items: 83 + - const: aux 84 + - const: ref 85 + - const: cfg_ahb 86 + - const: pipe 87 + 88 + - if: 89 + properties: 90 + compatible: 91 + contains: 92 + enum: 93 + - qcom,qcm2290-qmp-usb3-phy 94 + - qcom,sm6115-qmp-usb3-phy 95 + then: 96 + properties: 97 + clocks: 98 + maxItems: 4 99 + clock-names: 100 + items: 101 + - const: cfg_ahb 102 + - const: ref 103 + - const: com_aux 104 + - const: pipe 105 + 106 + - if: 107 + properties: 108 + compatible: 109 + contains: 110 + enum: 111 + - qcom,sa8775p-qmp-usb3-uni-phy 112 + - qcom,sc8280xp-qmp-usb3-uni-phy 113 + then: 114 + properties: 115 + clocks: 116 + maxItems: 4 117 + clock-names: 118 + items: 119 + - const: aux 120 + - const: ref 121 + - const: com_aux 122 + - const: pipe 123 + required: 124 + - power-domains 70 125 71 126 additionalProperties: false 72 127
+51
Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml
··· 60 60 description: 61 61 See include/dt-bindings/dt-bindings/phy/phy-qcom-qmp.h 62 62 63 + orientation-switch: 64 + description: 65 + Flag the PHY as possible handler of USB Type-C orientation switching 66 + type: boolean 67 + 68 + ports: 69 + $ref: /schemas/graph.yaml#/properties/ports 70 + properties: 71 + port@0: 72 + $ref: /schemas/graph.yaml#/properties/port 73 + description: Output endpoint of the PHY 74 + 75 + port@1: 76 + $ref: /schemas/graph.yaml#/properties/port 77 + description: Incoming endpoint from the USB controller 78 + 79 + port@2: 80 + $ref: /schemas/graph.yaml#/properties/port 81 + description: Incoming endpoint from the DisplayPort controller 82 + 63 83 required: 64 84 - compatible 65 85 - reg ··· 118 98 vdda-phy-supply = <&vreg_l9d>; 119 99 vdda-pll-supply = <&vreg_l4d>; 120 100 101 + orientation-switch; 102 + 121 103 #clock-cells = <1>; 122 104 #phy-cells = <1>; 105 + 106 + ports { 107 + #address-cells = <1>; 108 + #size-cells = <0>; 109 + 110 + port@0 { 111 + reg = <0>; 112 + 113 + endpoint { 114 + remote-endpoint = <&typec_connector_ss>; 115 + }; 116 + }; 117 + 118 + port@1 { 119 + reg = <1>; 120 + 121 + endpoint { 122 + remote-endpoint = <&dwc3_ss_out>; 123 + }; 124 + }; 125 + 126 + port@2 { 127 + reg = <2>; 128 + 129 + endpoint { 130 + remote-endpoint = <&mdss_dp_out>; 131 + }; 132 + }; 133 + }; 123 134 };
+4 -1
Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.yaml
··· 13 13 properties: 14 14 compatible: 15 15 contains: 16 - const: qcom,usb-hs-phy-apq8064 16 + enum: 17 + - qcom,usb-hs-phy-apq8064 18 + - qcom,usb-hs-phy-msm8960 17 19 then: 18 20 properties: 19 21 resets: ··· 42 40 - qcom,usb-hs-phy-apq8064 43 41 - qcom,usb-hs-phy-msm8226 44 42 - qcom,usb-hs-phy-msm8916 43 + - qcom,usb-hs-phy-msm8960 45 44 - qcom,usb-hs-phy-msm8974 46 45 - const: qcom,usb-hs-phy 47 46
+1
Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml
··· 20 20 - qcom,usb-snps-femto-v2-phy 21 21 - items: 22 22 - enum: 23 + - qcom,sa8775p-usb-hs-phy 23 24 - qcom,sc8280xp-usb-hs-phy 24 25 - const: qcom,usb-snps-hs-5nm-phy 25 26 - items:
+21
Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
··· 24 24 - qcom,msm8998-dwc3 25 25 - qcom,qcm2290-dwc3 26 26 - qcom,qcs404-dwc3 27 + - qcom,sa8775p-dwc3 27 28 - qcom,sc7180-dwc3 28 29 - qcom,sc7280-dwc3 29 30 - qcom,sc8280xp-dwc3 ··· 182 181 - qcom,msm8953-dwc3 183 182 - qcom,msm8996-dwc3 184 183 - qcom,msm8998-dwc3 184 + - qcom,sa8775p-dwc3 185 185 - qcom,sc7180-dwc3 186 186 - qcom,sc7280-dwc3 187 187 - qcom,sdm670-dwc3 ··· 452 450 interrupts: 453 451 maxItems: 4 454 452 interrupt-names: 453 + items: 454 + - const: pwr_event 455 + - const: dp_hs_phy_irq 456 + - const: dm_hs_phy_irq 457 + - const: ss_phy_irq 458 + 459 + - if: 460 + properties: 461 + compatible: 462 + contains: 463 + enum: 464 + - qcom,sa8775p-dwc3 465 + then: 466 + properties: 467 + interrupts: 468 + minItems: 3 469 + maxItems: 4 470 + interrupt-names: 471 + minItems: 3 455 472 items: 456 473 - const: pwr_event 457 474 - const: dp_hs_phy_irq
+13 -2
drivers/phy/amlogic/phy-meson-g12a-usb2.c
··· 172 172 int ret; 173 173 unsigned int value; 174 174 175 - ret = reset_control_reset(priv->reset); 175 + ret = clk_prepare_enable(priv->clk); 176 176 if (ret) 177 177 return ret; 178 + 179 + ret = reset_control_reset(priv->reset); 180 + if (ret) { 181 + clk_disable_unprepare(priv->clk); 182 + return ret; 183 + } 178 184 179 185 udelay(RESET_COMPLETE_TIME); 180 186 ··· 283 277 static int phy_meson_g12a_usb2_exit(struct phy *phy) 284 278 { 285 279 struct phy_meson_g12a_usb2_priv *priv = phy_get_drvdata(phy); 280 + int ret; 286 281 287 - return reset_control_reset(priv->reset); 282 + ret = reset_control_reset(priv->reset); 283 + if (!ret) 284 + clk_disable_unprepare(priv->clk); 285 + 286 + return ret; 288 287 } 289 288 290 289 /* set_mode is not needed, mode setting is handled via the UTMI bus */
+13 -2
drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
··· 59 59 #define USB_CTLR_TP_DIAG1_wake_MASK BIT(1) 60 60 #define USB_CTRL_CTLR_CSHCR 0x50 61 61 #define USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK BIT(18) 62 + #define USB_CTRL_P0_U2PHY_CFG1 0x68 63 + #define USB_CTRL_P0_U2PHY_CFG1_COMMONONN_MASK BIT(10) 62 64 63 65 /* Register definitions for the USB_PHY block in 7211b0 */ 64 66 #define USB_PHY_PLL_CTL 0x00 ··· 92 90 #define BDC_EC_AXIRDA_RTS_MASK GENMASK(31, 28) 93 91 #define BDC_EC_AXIRDA_RTS_SHIFT 28 94 92 93 + #define USB_XHCI_GBL_GUSB2PHYCFG 0x100 94 + #define USB_XHCI_GBL_GUSB2PHYCFG_U2_FREECLK_EXISTS_MASK BIT(30) 95 95 96 96 static void usb_mdio_write_7211b0(struct brcm_usb_init_params *params, 97 97 uint8_t addr, uint16_t data) ··· 144 140 int on_off) 145 141 { 146 142 void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; 143 + void __iomem *xhci_gbl = params->regs[BRCM_REGS_XHCI_GBL]; 147 144 148 145 /* Assert reset */ 149 - if (on_off) 146 + if (on_off) { 150 147 USB_CTRL_UNSET(ctrl, USB_PM, XHC_SOFT_RESETB); 151 148 /* De-assert reset */ 152 - else 149 + } else { 153 150 USB_CTRL_SET(ctrl, USB_PM, XHC_SOFT_RESETB); 151 + /* Required for COMMONONN to be set */ 152 + USB_XHCI_GBL_UNSET(xhci_gbl, GUSB2PHYCFG, U2_FREECLK_EXISTS); 153 + } 154 154 } 155 155 156 156 static void usb_init_ipp(struct brcm_usb_init_params *params) ··· 327 319 328 320 /* 1 millisecond - for USB clocks to settle down */ 329 321 usleep_range(1000, 2000); 322 + 323 + /* Disable PHY when port is suspended */ 324 + USB_CTRL_SET(ctrl, P0_U2PHY_CFG1, COMMONONN); 330 325 331 326 usb_wake_enable_7216(params, false); 332 327 usb_init_common(params);
+34
drivers/phy/broadcom/phy-brcm-usb-init.c
··· 35 35 #define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK BIT(25) /* option */ 36 36 #define USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK BIT(26) /* option */ 37 37 #define USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK BIT(27) /* opt */ 38 + #define USB_CTRL_SETUP_OC_DISABLE_PORT0_MASK BIT(28) 39 + #define USB_CTRL_SETUP_OC_DISABLE_PORT1_MASK BIT(29) 40 + #define USB_CTRL_SETUP_OC_DISABLE_MASK GENMASK(29, 28) /* option */ 41 + #define USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK BIT(30) 42 + #define USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK BIT(31) 38 43 #define USB_CTRL_SETUP_OC3_DISABLE_MASK GENMASK(31, 30) /* option */ 39 44 #define USB_CTRL_PLL_CTL 0x04 40 45 #define USB_CTRL_PLL_CTL_PLL_SUSPEND_EN_MASK BIT(27) ··· 119 114 USB_CTRL_SETUP_SCB2_EN_SELECTOR, 120 115 USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR, 121 116 USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR, 117 + USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR, 118 + USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR, 122 119 USB_CTRL_SETUP_OC3_DISABLE_SELECTOR, 123 120 USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR, 124 121 USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR, ··· 197 190 USB_CTRL_SETUP_SCB2_EN_MASK, 198 191 USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, 199 192 USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, 193 + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, 194 + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, 200 195 USB_CTRL_SETUP_OC3_DISABLE_MASK, 201 196 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ 202 197 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ ··· 241 232 USB_CTRL_SETUP_SCB2_EN_MASK, 242 233 USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, 243 234 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ 235 + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, 236 + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, 244 237 USB_CTRL_SETUP_OC3_DISABLE_MASK, 245 238 USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, 246 239 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ ··· 264 253 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */ 265 254 USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, 266 255 USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, 256 + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, 257 + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, 267 258 USB_CTRL_SETUP_OC3_DISABLE_MASK, 268 259 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ 269 260 USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, ··· 287 274 USB_CTRL_SETUP_SCB2_EN_MASK, 288 275 USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, 289 276 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ 277 + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, 278 + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, 290 279 USB_CTRL_SETUP_OC3_DISABLE_MASK, 291 280 USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, 292 281 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ ··· 310 295 USB_CTRL_SETUP_SCB2_EN_MASK, 311 296 USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, 312 297 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ 298 + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, 299 + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, 313 300 USB_CTRL_SETUP_OC3_DISABLE_MASK, 314 301 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ 315 302 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ ··· 333 316 USB_CTRL_SETUP_SCB2_EN_MASK, 334 317 USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK, 335 318 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ 319 + 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK */ 320 + 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK */ 336 321 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */ 337 322 USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, 338 323 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ ··· 356 337 USB_CTRL_SETUP_SCB2_EN_MASK, 357 338 USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, 358 339 USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, 340 + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, 341 + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, 359 342 USB_CTRL_SETUP_OC3_DISABLE_MASK, 360 343 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ 361 344 USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, ··· 379 358 USB_CTRL_SETUP_SCB2_EN_MASK, 380 359 USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK, 381 360 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ 361 + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, 362 + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, 382 363 USB_CTRL_SETUP_OC3_DISABLE_MASK, 383 364 USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, 384 365 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ ··· 402 379 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */ 403 380 USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, 404 381 USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, 382 + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, 383 + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, 405 384 USB_CTRL_SETUP_OC3_DISABLE_MASK, 406 385 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ 407 386 USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, ··· 425 400 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */ 426 401 0, /*USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */ 427 402 USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, 403 + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, 404 + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, 428 405 USB_CTRL_SETUP_OC3_DISABLE_MASK, 429 406 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ 430 407 USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, ··· 898 871 brcm_usb_writel(reg, USB_CTRL_REG(ctrl, SETUP)); 899 872 900 873 brcmusb_memc_fix(params); 874 + 875 + /* Workaround for false positive OC for 7439b2 in DRD/Device mode */ 876 + if ((params->family_id == 0x74390012) && 877 + (params->supported_port_modes != USB_CTLR_MODE_HOST)) { 878 + USB_CTRL_SET(ctrl, SETUP, OC_DISABLE_PORT1); 879 + USB_CTRL_SET_FAMILY(params, SETUP, OC3_DISABLE_PORT1); 880 + } 901 881 902 882 if (USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1, PORT_MODE)) { 903 883 reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
+8
drivers/phy/broadcom/phy-brcm-usb-init.h
··· 34 34 brcm_usb_ctrl_unset(USB_CTRL_REG(base, reg), \ 35 35 USB_CTRL_##reg##_##field##_MASK) 36 36 37 + #define USB_XHCI_GBL_REG(base, reg) ((void __iomem *)base + USB_XHCI_GBL_##reg) 38 + #define USB_XHCI_GBL_SET(base, reg, field) \ 39 + brcm_usb_ctrl_set(USB_XHCI_GBL_REG(base, reg), \ 40 + USB_XHCI_GBL_##reg##_##field##_MASK) 41 + #define USB_XHCI_GBL_UNSET(base, reg, field) \ 42 + brcm_usb_ctrl_unset(USB_XHCI_GBL_REG(base, reg), \ 43 + USB_XHCI_GBL_##reg##_##field##_MASK) 44 + 37 45 struct brcm_usb_init_params; 38 46 39 47 struct brcm_usb_init_ops {
+87 -8
drivers/phy/cadence/phy-cadence-salvo.c
··· 6 6 * Copyright (c) 2019-2020 NXP 7 7 */ 8 8 9 + #include <linux/bitfield.h> 9 10 #include <linux/clk.h> 10 11 #include <linux/io.h> 11 12 #include <linux/module.h> ··· 16 15 #include <linux/of.h> 17 16 #include <linux/of_platform.h> 18 17 19 - /* PHY register definition */ 18 + #define USB3_PHY_OFFSET 0x0 19 + #define USB2_PHY_OFFSET 0x38000 20 + /* USB3 PHY register definition */ 20 21 #define PHY_PMA_CMN_CTRL1 0xC800 21 22 #define TB_ADDR_CMN_DIAG_HSCLK_SEL 0x01e0 22 23 #define TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR 0x0084 ··· 90 87 #define TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR 0x40f2 91 88 #define TB_ADDR_TX_RCVDETSC_CTRL 0x4124 92 89 90 + /* USB2 PHY register definition */ 91 + #define UTMI_REG15 0xaf 92 + #define UTMI_AFE_RX_REG0 0x0d 93 + #define UTMI_AFE_RX_REG5 0x12 94 + #define UTMI_AFE_BC_REG4 0x29 95 + 96 + /* Align UTMI_AFE_RX_REG0 bit[7:6] define */ 97 + enum usb2_disconn_threshold { 98 + USB2_DISCONN_THRESHOLD_575 = 0x0, 99 + USB2_DISCONN_THRESHOLD_610 = 0x1, 100 + USB2_DISCONN_THRESHOLD_645 = 0x3, 101 + }; 102 + 103 + #define RX_USB2_DISCONN_MASK GENMASK(7, 6) 104 + 93 105 /* TB_ADDR_TX_RCVDETSC_CTRL */ 94 106 #define RXDET_IN_P3_32KHZ BIT(0) 107 + /* 108 + * UTMI_REG15 109 + * 110 + * Gate how many us for the txvalid signal until analog 111 + * HS/FS transmitters have powered up 112 + */ 113 + #define TXVALID_GATE_THRESHOLD_HS_MASK (BIT(4) | BIT(5)) 114 + /* 0us, txvalid is ready just after HS/FS transmitters have powered up */ 115 + #define TXVALID_GATE_THRESHOLD_HS_0US (BIT(4) | BIT(5)) 116 + 117 + #define SET_B_SESSION_VALID (BIT(6) | BIT(5)) 118 + #define CLR_B_SESSION_VALID (BIT(6)) 95 119 96 120 struct cdns_reg_pairs { 97 121 u16 val; ··· 136 106 struct clk *clk; 137 107 void __iomem *base; 138 108 struct cdns_salvo_data *data; 109 + enum usb2_disconn_threshold usb2_disconn; 139 110 }; 140 111 141 112 static const struct of_device_id cdns_salvo_phy_of_match[]; 142 - static u16 cdns_salvo_read(struct cdns_salvo_phy *salvo_phy, u32 reg) 113 + static const struct cdns_salvo_data cdns_nxp_salvo_data; 114 + 115 + static bool cdns_is_nxp_phy(struct cdns_salvo_phy *salvo_phy) 143 116 { 144 - return (u16)readl(salvo_phy->base + 117 + return salvo_phy->data == &cdns_nxp_salvo_data; 118 + } 119 + 120 + static u16 cdns_salvo_read(struct cdns_salvo_phy *salvo_phy, u32 offset, u32 reg) 121 + { 122 + return (u16)readl(salvo_phy->base + offset + 145 123 reg * (1 << salvo_phy->data->reg_offset_shift)); 146 124 } 147 125 148 - static void cdns_salvo_write(struct cdns_salvo_phy *salvo_phy, 126 + static void cdns_salvo_write(struct cdns_salvo_phy *salvo_phy, u32 offset, 149 127 u32 reg, u16 val) 150 128 { 151 - writel(val, salvo_phy->base + 129 + writel(val, salvo_phy->base + offset + 152 130 reg * (1 << salvo_phy->data->reg_offset_shift)); 153 131 } 154 132 ··· 257 219 for (i = 0; i < data->init_sequence_length; i++) { 258 220 const struct cdns_reg_pairs *reg_pair = data->init_sequence_val + i; 259 221 260 - cdns_salvo_write(salvo_phy, reg_pair->off, reg_pair->val); 222 + cdns_salvo_write(salvo_phy, USB3_PHY_OFFSET, reg_pair->off, reg_pair->val); 261 223 } 262 224 263 225 /* RXDET_IN_P3_32KHZ, Receiver detect slow clock enable */ 264 - value = cdns_salvo_read(salvo_phy, TB_ADDR_TX_RCVDETSC_CTRL); 226 + value = cdns_salvo_read(salvo_phy, USB3_PHY_OFFSET, TB_ADDR_TX_RCVDETSC_CTRL); 265 227 value |= RXDET_IN_P3_32KHZ; 266 - cdns_salvo_write(salvo_phy, TB_ADDR_TX_RCVDETSC_CTRL, 228 + cdns_salvo_write(salvo_phy, USB3_PHY_OFFSET, TB_ADDR_TX_RCVDETSC_CTRL, 267 229 RXDET_IN_P3_32KHZ); 230 + 231 + value = cdns_salvo_read(salvo_phy, USB2_PHY_OFFSET, UTMI_REG15); 232 + value &= ~TXVALID_GATE_THRESHOLD_HS_MASK; 233 + cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_REG15, 234 + value | TXVALID_GATE_THRESHOLD_HS_0US); 235 + 236 + cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG5, 0x5); 237 + 238 + value = cdns_salvo_read(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG0); 239 + value &= ~RX_USB2_DISCONN_MASK; 240 + value = FIELD_PREP(RX_USB2_DISCONN_MASK, salvo_phy->usb2_disconn); 241 + cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG0, value); 268 242 269 243 udelay(10); 270 244 ··· 301 251 return 0; 302 252 } 303 253 254 + static int cdns_salvo_set_mode(struct phy *phy, enum phy_mode mode, int submode) 255 + { 256 + struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy); 257 + 258 + if (!cdns_is_nxp_phy(salvo_phy)) 259 + return 0; 260 + 261 + if (mode == PHY_MODE_USB_DEVICE) 262 + cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_BC_REG4, 263 + SET_B_SESSION_VALID); 264 + else 265 + cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_BC_REG4, 266 + CLR_B_SESSION_VALID); 267 + 268 + return 0; 269 + } 270 + 304 271 static const struct phy_ops cdns_salvo_phy_ops = { 305 272 .init = cdns_salvo_phy_init, 306 273 .power_on = cdns_salvo_phy_power_on, 307 274 .power_off = cdns_salvo_phy_power_off, 308 275 .owner = THIS_MODULE, 276 + .set_mode = cdns_salvo_set_mode, 309 277 }; 310 278 311 279 static int cdns_salvo_phy_probe(struct platform_device *pdev) ··· 332 264 struct device *dev = &pdev->dev; 333 265 struct cdns_salvo_phy *salvo_phy; 334 266 struct cdns_salvo_data *data; 267 + u32 val; 335 268 336 269 data = (struct cdns_salvo_data *)of_device_get_match_data(dev); 337 270 salvo_phy = devm_kzalloc(dev, sizeof(*salvo_phy), GFP_KERNEL); ··· 343 274 salvo_phy->clk = devm_clk_get_optional(dev, "salvo_phy_clk"); 344 275 if (IS_ERR(salvo_phy->clk)) 345 276 return PTR_ERR(salvo_phy->clk); 277 + 278 + if (of_property_read_u32(dev->of_node, "cdns,usb2-disconnect-threshold-microvolt", &val)) 279 + val = 575; 280 + 281 + if (val < 610) 282 + salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_575; 283 + else if (val < 645) 284 + salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_610; 285 + else 286 + salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_645; 346 287 347 288 salvo_phy->base = devm_platform_ioremap_resource(pdev, 0); 348 289 if (IS_ERR(salvo_phy->base))
+526 -194
drivers/phy/cadence/phy-cadence-torrent.c
··· 38 38 #define POLL_TIMEOUT_US 5000 39 39 #define PLL_LOCK_TIMEOUT 100000 40 40 41 + #define DP_PLL0 BIT(0) 42 + #define DP_PLL1 BIT(1) 43 + 41 44 #define TORRENT_COMMON_CDB_OFFSET 0x0 42 45 43 46 #define TORRENT_TX_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \ ··· 69 66 */ 70 67 #define PHY_AUX_CTRL 0x04 71 68 #define PHY_RESET 0x20 72 - #define PMA_TX_ELEC_IDLE_MASK 0xF0U 73 69 #define PMA_TX_ELEC_IDLE_SHIFT 4 74 - #define PHY_L00_RESET_N_MASK 0x01U 75 70 #define PHY_PMA_XCVR_PLLCLK_EN 0x24 76 71 #define PHY_PMA_XCVR_PLLCLK_EN_ACK 0x28 77 72 #define PHY_PMA_XCVR_POWER_STATE_REQ 0x2c 78 - #define PHY_POWER_STATE_LN_0 0x0000 79 - #define PHY_POWER_STATE_LN_1 0x0008 80 - #define PHY_POWER_STATE_LN_2 0x0010 81 - #define PHY_POWER_STATE_LN_3 0x0018 73 + #define PHY_POWER_STATE_LN(ln) ((ln) * 8) 82 74 #define PMA_XCVR_POWER_STATE_REQ_LN_MASK 0x3FU 83 75 #define PHY_PMA_XCVR_POWER_STATE_ACK 0x30 84 76 #define PHY_PMA_CMN_READY 0x34 ··· 321 323 void __iomem *base; /* DPTX registers base */ 322 324 void __iomem *sd_base; /* SD0801 registers base */ 323 325 u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */ 326 + u32 dp_pll; 324 327 struct reset_control *phy_rst; 325 328 struct reset_control *apb_rst; 326 329 struct device *dev; ··· 904 905 /* Setting VCO for 10.8GHz */ 905 906 case 2700: 906 907 case 5400: 907 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028); 908 - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022); 909 - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022); 910 - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C); 908 + if (cdns_phy->dp_pll & DP_PLL0) 909 + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022); 910 + 911 + if (cdns_phy->dp_pll & DP_PLL1) { 912 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028); 913 + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022); 914 + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C); 915 + } 911 916 break; 912 917 /* Setting VCO for 9.72GHz */ 913 918 case 1620: 914 919 case 2430: 915 920 case 3240: 916 - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); 917 - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); 918 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); 919 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); 920 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); 921 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); 922 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); 923 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); 924 - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061); 925 - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061); 926 - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333); 927 - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333); 928 - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); 929 - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); 930 - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042); 931 - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042); 932 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); 933 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); 921 + if (cdns_phy->dp_pll & DP_PLL0) { 922 + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); 923 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); 924 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); 925 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); 926 + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061); 927 + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333); 928 + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); 929 + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042); 930 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); 931 + } 932 + if (cdns_phy->dp_pll & DP_PLL1) { 933 + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); 934 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); 935 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); 936 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); 937 + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061); 938 + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333); 939 + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); 940 + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042); 941 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); 942 + } 934 943 break; 935 944 /* Setting VCO for 8.64GHz */ 936 945 case 2160: 937 946 case 4320: 938 - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); 939 - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); 940 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); 941 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); 942 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); 943 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); 944 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); 945 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); 946 - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056); 947 - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056); 948 - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666); 949 - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666); 950 - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); 951 - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); 952 - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A); 953 - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A); 954 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); 955 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); 947 + if (cdns_phy->dp_pll & DP_PLL0) { 948 + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); 949 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); 950 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); 951 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); 952 + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056); 953 + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666); 954 + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); 955 + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A); 956 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); 957 + } 958 + if (cdns_phy->dp_pll & DP_PLL1) { 959 + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); 960 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); 961 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); 962 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); 963 + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056); 964 + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666); 965 + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); 966 + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A); 967 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); 968 + } 956 969 break; 957 970 /* Setting VCO for 8.1GHz */ 958 971 case 8100: 959 - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); 960 - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); 961 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); 962 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); 963 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); 964 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); 965 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); 966 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); 967 - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051); 968 - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051); 969 - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); 970 - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); 971 - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036); 972 - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036); 973 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); 974 - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); 972 + if (cdns_phy->dp_pll & DP_PLL0) { 973 + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); 974 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); 975 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); 976 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); 977 + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051); 978 + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); 979 + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036); 980 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); 981 + } 982 + if (cdns_phy->dp_pll & DP_PLL1) { 983 + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); 984 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); 985 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); 986 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); 987 + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051); 988 + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); 989 + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036); 990 + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); 991 + } 975 992 break; 976 993 } 994 + } 995 + 996 + /* Set PLL used for DP configuration */ 997 + static int cdns_torrent_dp_get_pll(struct cdns_torrent_phy *cdns_phy, 998 + enum cdns_torrent_phy_type phy_t2) 999 + { 1000 + switch (phy_t2) { 1001 + case TYPE_PCIE: 1002 + case TYPE_USB: 1003 + cdns_phy->dp_pll = DP_PLL1; 1004 + break; 1005 + case TYPE_SGMII: 1006 + case TYPE_QSGMII: 1007 + cdns_phy->dp_pll = DP_PLL0; 1008 + break; 1009 + case TYPE_NONE: 1010 + cdns_phy->dp_pll = DP_PLL0 | DP_PLL1; 1011 + break; 1012 + default: 1013 + dev_err(cdns_phy->dev, "Unsupported PHY configuration\n"); 1014 + return -EINVAL; 1015 + } 1016 + 1017 + return 0; 977 1018 } 978 1019 979 1020 /* 980 1021 * Enable or disable PLL for selected lanes. 981 1022 */ 982 1023 static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, 1024 + struct cdns_torrent_inst *inst, 983 1025 struct phy_configure_opts_dp *dp, 984 1026 bool enable) 985 1027 { 986 - u32 rd_val; 987 - u32 ret; 988 1028 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; 1029 + u32 rd_val, pll_ack_val; 1030 + int ret; 989 1031 990 1032 /* 991 1033 * Used to determine, which bits to check for or enable in ··· 1036 996 /* Used to enable or disable lanes. */ 1037 997 u32 pll_val; 1038 998 1039 - /* Select values of registers and mask, depending on enabled lane 1040 - * count. 1041 - */ 1042 - switch (dp->lanes) { 1043 - /* lane 0 */ 1044 - case (1): 1045 - pll_bits = 0x00000001; 1046 - break; 1047 - /* lanes 0-1 */ 1048 - case (2): 1049 - pll_bits = 0x00000003; 1050 - break; 1051 - /* lanes 0-3, all */ 1052 - default: 1053 - pll_bits = 0x0000000F; 1054 - break; 1055 - } 999 + /* Select values of registers and mask, depending on enabled lane count. */ 1000 + pll_val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); 1056 1001 1057 - if (enable) 1058 - pll_val = pll_bits; 1059 - else 1060 - pll_val = 0x00000000; 1002 + if (enable) { 1003 + pll_bits = ((1 << dp->lanes) - 1); 1004 + pll_val |= pll_bits; 1005 + pll_ack_val = pll_bits; 1006 + } else { 1007 + pll_bits = ((1 << inst->num_lanes) - 1); 1008 + pll_val &= (~pll_bits); 1009 + pll_ack_val = 0; 1010 + } 1061 1011 1062 1012 cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, pll_val); 1063 1013 ··· 1055 1025 ret = regmap_read_poll_timeout(regmap, 1056 1026 PHY_PMA_XCVR_PLLCLK_EN_ACK, 1057 1027 rd_val, 1058 - (rd_val & pll_bits) == pll_val, 1028 + (rd_val & pll_bits) == pll_ack_val, 1059 1029 0, POLL_TIMEOUT_US); 1060 1030 ndelay(100); 1061 1031 return ret; 1062 1032 } 1063 1033 1064 1034 static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, 1035 + struct cdns_torrent_inst *inst, 1065 1036 u32 num_lanes, 1066 1037 enum phy_powerstate powerstate) 1067 1038 { 1068 1039 /* Register value for power state for a single byte. */ 1069 - u32 value_part; 1070 - u32 value; 1071 - u32 mask; 1040 + u32 value_part, i; 1041 + u32 value = 0; 1042 + u32 mask = 0; 1072 1043 u32 read_val; 1073 - u32 ret; 1044 + int ret; 1074 1045 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; 1075 1046 1076 1047 switch (powerstate) { ··· 1087 1056 break; 1088 1057 } 1089 1058 1090 - /* Select values of registers and mask, depending on enabled 1091 - * lane count. 1092 - */ 1093 - switch (num_lanes) { 1094 - /* lane 0 */ 1095 - case (1): 1096 - value = value_part; 1097 - mask = 0x0000003FU; 1098 - break; 1099 - /* lanes 0-1 */ 1100 - case (2): 1101 - value = (value_part 1102 - | (value_part << 8)); 1103 - mask = 0x00003F3FU; 1104 - break; 1105 - /* lanes 0-3, all */ 1106 - default: 1107 - value = (value_part 1108 - | (value_part << 8) 1109 - | (value_part << 16) 1110 - | (value_part << 24)); 1111 - mask = 0x3F3F3F3FU; 1112 - break; 1059 + /* Select values of registers and mask, depending on enabled lane count. */ 1060 + 1061 + for (i = 0; i < num_lanes; i++) { 1062 + value |= (value_part << PHY_POWER_STATE_LN(i)); 1063 + mask |= (PMA_XCVR_POWER_STATE_REQ_LN_MASK << PHY_POWER_STATE_LN(i)); 1113 1064 } 1114 1065 1115 1066 /* Set power state A<n>. */ ··· 1106 1093 return ret; 1107 1094 } 1108 1095 1109 - static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) 1096 + static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, 1097 + struct cdns_torrent_inst *inst, u32 num_lanes) 1110 1098 { 1111 1099 unsigned int read_val; 1112 1100 int ret; ··· 1128 1114 1129 1115 ndelay(100); 1130 1116 1131 - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, 1117 + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes, 1132 1118 POWERSTATE_A2); 1133 1119 if (ret) 1134 1120 return ret; 1135 1121 1136 - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, 1122 + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes, 1137 1123 POWERSTATE_A0); 1138 1124 1139 1125 return ret; ··· 1157 1143 } 1158 1144 1159 1145 static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, 1146 + struct cdns_torrent_inst *inst, 1160 1147 u32 rate, u32 num_lanes) 1161 1148 { 1162 1149 unsigned int clk_sel_val = 0; ··· 1190 1175 break; 1191 1176 } 1192 1177 1193 - cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, 1194 - CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val); 1195 - cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, 1196 - CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val); 1178 + if (cdns_phy->dp_pll & DP_PLL0) 1179 + cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, 1180 + CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val); 1181 + 1182 + if (cdns_phy->dp_pll & DP_PLL1) 1183 + cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, 1184 + CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val); 1197 1185 1198 1186 /* PMA lane configuration to deal with multi-link operation */ 1199 1187 for (i = 0; i < num_lanes; i++) 1200 - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i], 1188 + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + i], 1201 1189 XCVR_DIAG_HSCLK_DIV, hsclk_div_val); 1202 1190 } 1203 1191 ··· 1209 1191 * set and PLL disable request was processed. 1210 1192 */ 1211 1193 static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy, 1194 + struct cdns_torrent_inst *inst, 1212 1195 struct phy_configure_opts_dp *dp) 1213 1196 { 1214 - u32 read_val, ret; 1197 + u32 read_val, field_val; 1198 + int ret; 1215 1199 1216 - /* Disable the cmn_pll0_en before re-programming the new data rate. */ 1217 - regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x0); 1200 + /* 1201 + * Disable the associated PLL (cmn_pll0_en or cmn_pll1_en) before 1202 + * re-programming the new data rate. 1203 + */ 1204 + ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val); 1205 + if (ret) 1206 + return ret; 1207 + field_val &= ~(cdns_phy->dp_pll); 1208 + regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val); 1218 1209 1219 1210 /* 1220 1211 * Wait for PLL ready de-assertion. 1221 1212 * For PLL0 - PHY_PMA_CMN_CTRL2[2] == 1 1213 + * For PLL1 - PHY_PMA_CMN_CTRL2[3] == 1 1222 1214 */ 1223 - ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, 1224 - read_val, 1225 - ((read_val >> 2) & 0x01) != 0, 1226 - 0, POLL_TIMEOUT_US); 1227 - if (ret) 1228 - return ret; 1215 + if (cdns_phy->dp_pll & DP_PLL0) { 1216 + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, 1217 + read_val, 1218 + ((read_val >> 2) & 0x01) != 0, 1219 + 0, POLL_TIMEOUT_US); 1220 + if (ret) 1221 + return ret; 1222 + } 1223 + 1224 + if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1) { 1225 + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, 1226 + read_val, 1227 + ((read_val >> 3) & 0x01) != 0, 1228 + 0, POLL_TIMEOUT_US); 1229 + if (ret) 1230 + return ret; 1231 + } 1229 1232 ndelay(200); 1230 1233 1231 1234 /* DP Rate Change - VCO Output settings. */ ··· 1260 1221 /* PMA common configuration 100MHz */ 1261 1222 cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(cdns_phy, dp->link_rate, dp->ssc); 1262 1223 1263 - cdns_torrent_dp_pma_cmn_rate(cdns_phy, dp->link_rate, dp->lanes); 1224 + cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, dp->link_rate, dp->lanes); 1264 1225 1265 - /* Enable the cmn_pll0_en. */ 1266 - regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x3); 1226 + /* Enable the associated PLL (cmn_pll0_en or cmn_pll1_en) */ 1227 + ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val); 1228 + if (ret) 1229 + return ret; 1230 + field_val |= cdns_phy->dp_pll; 1231 + regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val); 1267 1232 1268 1233 /* 1269 1234 * Wait for PLL ready assertion. 1270 1235 * For PLL0 - PHY_PMA_CMN_CTRL2[0] == 1 1236 + * For PLL1 - PHY_PMA_CMN_CTRL2[1] == 1 1271 1237 */ 1272 - ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, 1273 - read_val, 1274 - (read_val & 0x01) != 0, 1275 - 0, POLL_TIMEOUT_US); 1238 + if (cdns_phy->dp_pll & DP_PLL0) { 1239 + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, 1240 + read_val, 1241 + (read_val & 0x01) != 0, 1242 + 0, POLL_TIMEOUT_US); 1243 + if (ret) 1244 + return ret; 1245 + } 1246 + 1247 + if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1) 1248 + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, 1249 + read_val, 1250 + ((read_val >> 1) & 0x01) != 0, 1251 + 0, POLL_TIMEOUT_US); 1252 + 1276 1253 return ret; 1277 1254 } 1278 1255 ··· 1356 1301 1357 1302 /* Set power state A0 and PLL clock enable to 0 on enabled lanes. */ 1358 1303 static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy, 1304 + struct cdns_torrent_inst *inst, 1359 1305 u32 num_lanes) 1360 1306 { 1361 1307 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; ··· 1364 1308 PHY_PMA_XCVR_POWER_STATE_REQ); 1365 1309 u32 pll_clk_en = cdns_torrent_dp_read(regmap, 1366 1310 PHY_PMA_XCVR_PLLCLK_EN); 1311 + u32 i; 1367 1312 1368 - /* Lane 0 is always enabled. */ 1369 - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << 1370 - PHY_POWER_STATE_LN_0); 1371 - pll_clk_en &= ~0x01U; 1313 + for (i = 0; i < num_lanes; i++) { 1314 + pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK 1315 + << PHY_POWER_STATE_LN(inst->mlane + i)); 1372 1316 1373 - if (num_lanes > 1) { 1374 - /* lane 1 */ 1375 - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << 1376 - PHY_POWER_STATE_LN_1); 1377 - pll_clk_en &= ~(0x01U << 1); 1378 - } 1379 - 1380 - if (num_lanes > 2) { 1381 - /* lanes 2 and 3 */ 1382 - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << 1383 - PHY_POWER_STATE_LN_2); 1384 - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << 1385 - PHY_POWER_STATE_LN_3); 1386 - pll_clk_en &= ~(0x01U << 2); 1387 - pll_clk_en &= ~(0x01U << 3); 1317 + pll_clk_en &= ~(0x01U << (inst->mlane + i)); 1388 1318 } 1389 1319 1390 1320 cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, pwr_state); ··· 1379 1337 1380 1338 /* Configure lane count as required. */ 1381 1339 static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy, 1340 + struct cdns_torrent_inst *inst, 1382 1341 struct phy_configure_opts_dp *dp) 1383 1342 { 1384 - u32 value; 1385 - u32 ret; 1343 + u32 value, i; 1344 + int ret; 1386 1345 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; 1387 1346 u8 lane_mask = (1 << dp->lanes) - 1; 1347 + u8 pma_tx_elec_idle_mask = 0; 1348 + u32 clane = inst->mlane; 1349 + 1350 + lane_mask <<= clane; 1388 1351 1389 1352 value = cdns_torrent_dp_read(regmap, PHY_RESET); 1390 1353 /* clear pma_tx_elec_idle_ln_* bits. */ 1391 - value &= ~PMA_TX_ELEC_IDLE_MASK; 1354 + pma_tx_elec_idle_mask = ((1 << inst->num_lanes) - 1) << clane; 1355 + 1356 + pma_tx_elec_idle_mask <<= PMA_TX_ELEC_IDLE_SHIFT; 1357 + 1358 + value &= ~pma_tx_elec_idle_mask; 1359 + 1392 1360 /* Assert pma_tx_elec_idle_ln_* for disabled lanes. */ 1393 1361 value |= ((~lane_mask) << PMA_TX_ELEC_IDLE_SHIFT) & 1394 - PMA_TX_ELEC_IDLE_MASK; 1362 + pma_tx_elec_idle_mask; 1363 + 1395 1364 cdns_torrent_dp_write(regmap, PHY_RESET, value); 1396 1365 1397 - /* reset the link by asserting phy_l00_reset_n low */ 1366 + /* reset the link by asserting master lane phy_l0*_reset_n low */ 1398 1367 cdns_torrent_dp_write(regmap, PHY_RESET, 1399 - value & (~PHY_L00_RESET_N_MASK)); 1368 + value & (~(1 << clane))); 1400 1369 1401 1370 /* 1402 - * Assert lane reset on unused lanes and lane 0 so they remain in reset 1371 + * Assert lane reset on unused lanes and master lane so they remain in reset 1403 1372 * and powered down when re-enabling the link 1404 1373 */ 1405 - value = (value & 0x0000FFF0) | (0x0000000E & lane_mask); 1374 + for (i = 0; i < inst->num_lanes; i++) 1375 + value &= (~(1 << (clane + i))); 1376 + 1377 + for (i = 1; i < inst->num_lanes; i++) 1378 + value |= ((1 << (clane + i)) & lane_mask); 1379 + 1406 1380 cdns_torrent_dp_write(regmap, PHY_RESET, value); 1407 1381 1408 - cdns_torrent_dp_set_a0_pll(cdns_phy, dp->lanes); 1382 + cdns_torrent_dp_set_a0_pll(cdns_phy, inst, dp->lanes); 1409 1383 1410 1384 /* release phy_l0*_reset_n based on used laneCount */ 1411 - value = (value & 0x0000FFF0) | (0x0000000F & lane_mask); 1385 + for (i = 0; i < inst->num_lanes; i++) 1386 + value &= (~(1 << (clane + i))); 1387 + 1388 + for (i = 0; i < inst->num_lanes; i++) 1389 + value |= ((1 << (clane + i)) & lane_mask); 1390 + 1412 1391 cdns_torrent_dp_write(regmap, PHY_RESET, value); 1413 1392 1414 1393 /* Wait, until PHY gets ready after releasing PHY reset signal. */ ··· 1440 1377 ndelay(100); 1441 1378 1442 1379 /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */ 1443 - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001); 1380 + value = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); 1381 + value |= (1 << clane); 1382 + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, value); 1444 1383 1445 - ret = cdns_torrent_dp_run(cdns_phy, dp->lanes); 1384 + ret = cdns_torrent_dp_run(cdns_phy, inst, dp->lanes); 1446 1385 1447 1386 return ret; 1448 1387 } 1449 1388 1450 1389 /* Configure link rate as required. */ 1451 1390 static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy, 1391 + struct cdns_torrent_inst *inst, 1452 1392 struct phy_configure_opts_dp *dp) 1453 1393 { 1454 - u32 ret; 1394 + int ret; 1455 1395 1456 - ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes, 1396 + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes, 1457 1397 POWERSTATE_A3); 1458 1398 if (ret) 1459 1399 return ret; 1460 - ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, false); 1400 + ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, false); 1461 1401 if (ret) 1462 1402 return ret; 1463 1403 ndelay(200); 1464 1404 1465 - ret = cdns_torrent_dp_configure_rate(cdns_phy, dp); 1405 + ret = cdns_torrent_dp_configure_rate(cdns_phy, inst, dp); 1466 1406 if (ret) 1467 1407 return ret; 1468 1408 ndelay(200); 1469 1409 1470 - ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, true); 1410 + ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, true); 1471 1411 if (ret) 1472 1412 return ret; 1473 - ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes, 1413 + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes, 1474 1414 POWERSTATE_A2); 1475 1415 if (ret) 1476 1416 return ret; 1477 - ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes, 1417 + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes, 1478 1418 POWERSTATE_A0); 1479 1419 if (ret) 1480 1420 return ret; ··· 1488 1422 1489 1423 /* Configure voltage swing and pre-emphasis for all enabled lanes. */ 1490 1424 static void cdns_torrent_dp_set_voltages(struct cdns_torrent_phy *cdns_phy, 1425 + struct cdns_torrent_inst *inst, 1491 1426 struct phy_configure_opts_dp *dp) 1492 1427 { 1493 1428 u8 lane; 1494 1429 u16 val; 1495 1430 1496 1431 for (lane = 0; lane < dp->lanes; lane++) { 1497 - val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane], 1432 + val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], 1498 1433 TX_DIAG_ACYA); 1499 1434 /* 1500 1435 * Write 1 to register bit TX_DIAG_ACYA[0] to freeze the 1501 1436 * current state of the analog TX driver. 1502 1437 */ 1503 1438 val |= TX_DIAG_ACYA_HBDC_MASK; 1504 - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], 1439 + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], 1505 1440 TX_DIAG_ACYA, val); 1506 1441 1507 - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], 1442 + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], 1508 1443 TX_TXCC_CTRL, 0x08A4); 1509 1444 val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].diag_tx_drv; 1510 - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], 1445 + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], 1511 1446 DRV_DIAG_TX_DRV, val); 1512 1447 val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].mgnfs_mult; 1513 - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], 1448 + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], 1514 1449 TX_TXCC_MGNFS_MULT_000, 1515 1450 val); 1516 1451 val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].cpost_mult; 1517 - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], 1452 + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], 1518 1453 TX_TXCC_CPOST_MULT_00, 1519 1454 val); 1520 1455 1521 - val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane], 1456 + val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], 1522 1457 TX_DIAG_ACYA); 1523 1458 /* 1524 1459 * Write 0 to register bit TX_DIAG_ACYA[0] to allow the state of 1525 1460 * analog TX driver to reflect the new programmed one. 1526 1461 */ 1527 1462 val &= ~TX_DIAG_ACYA_HBDC_MASK; 1528 - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], 1463 + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], 1529 1464 TX_DIAG_ACYA, val); 1530 1465 } 1531 1466 }; ··· 1545 1478 } 1546 1479 1547 1480 if (opts->dp.set_lanes) { 1548 - ret = cdns_torrent_dp_set_lanes(cdns_phy, &opts->dp); 1481 + ret = cdns_torrent_dp_set_lanes(cdns_phy, inst, &opts->dp); 1549 1482 if (ret) { 1550 1483 dev_err(&phy->dev, "cdns_torrent_dp_set_lanes failed\n"); 1551 1484 return ret; ··· 1553 1486 } 1554 1487 1555 1488 if (opts->dp.set_rate) { 1556 - ret = cdns_torrent_dp_set_rate(cdns_phy, &opts->dp); 1489 + ret = cdns_torrent_dp_set_rate(cdns_phy, inst, &opts->dp); 1557 1490 if (ret) { 1558 1491 dev_err(&phy->dev, "cdns_torrent_dp_set_rate failed\n"); 1559 1492 return ret; ··· 1561 1494 } 1562 1495 1563 1496 if (opts->dp.set_voltages) 1564 - cdns_torrent_dp_set_voltages(cdns_phy, &opts->dp); 1497 + cdns_torrent_dp_set_voltages(cdns_phy, inst, &opts->dp); 1565 1498 1566 1499 return ret; 1567 1500 } ··· 1629 1562 { 1630 1563 struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; 1631 1564 unsigned char lane_bits; 1565 + u32 val; 1632 1566 1633 1567 cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */ 1634 1568 ··· 1637 1569 * Set lines power state to A0 1638 1570 * Set lines pll clk enable to 0 1639 1571 */ 1640 - cdns_torrent_dp_set_a0_pll(cdns_phy, inst->num_lanes); 1572 + cdns_torrent_dp_set_a0_pll(cdns_phy, inst, inst->num_lanes); 1641 1573 1642 1574 /* 1643 1575 * release phy_l0*_reset_n and pma_tx_elec_idle_ln_* based on 1644 1576 * used lanes 1645 1577 */ 1646 1578 lane_bits = (1 << inst->num_lanes) - 1; 1647 - cdns_torrent_dp_write(regmap, PHY_RESET, 1648 - ((0xF & ~lane_bits) << 4) | (0xF & lane_bits)); 1579 + 1580 + val = cdns_torrent_dp_read(regmap, PHY_RESET); 1581 + val |= (0xF & lane_bits); 1582 + val &= ~(lane_bits << 4); 1583 + cdns_torrent_dp_write(regmap, PHY_RESET, val); 1649 1584 1650 1585 /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */ 1651 - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001); 1586 + val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); 1587 + val |= 1; 1588 + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, val); 1652 1589 1653 1590 /* 1654 1591 * PHY PMA registers configuration functions ··· 1672 1599 cdns_phy->max_bit_rate, 1673 1600 false); 1674 1601 1675 - cdns_torrent_dp_pma_cmn_rate(cdns_phy, cdns_phy->max_bit_rate, 1602 + cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, cdns_phy->max_bit_rate, 1676 1603 inst->num_lanes); 1677 1604 1678 1605 /* take out of reset */ ··· 1685 1612 { 1686 1613 int ret; 1687 1614 1688 - cdns_torrent_phy_on(phy); 1615 + ret = cdns_torrent_phy_on(phy); 1616 + if (ret) 1617 + return ret; 1689 1618 1690 1619 ret = cdns_torrent_dp_wait_pma_cmn_ready(cdns_phy); 1691 1620 if (ret) 1692 1621 return ret; 1693 1622 1694 - ret = cdns_torrent_dp_run(cdns_phy, inst->num_lanes); 1623 + ret = cdns_torrent_dp_run(cdns_phy, inst, inst->num_lanes); 1695 1624 1696 1625 return ret; 1697 1626 } ··· 1702 1627 { 1703 1628 struct cdns_torrent_inst *inst = phy_get_drvdata(phy); 1704 1629 struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); 1630 + int ret; 1705 1631 1706 1632 switch (cdns_phy->ref_clk_rate) { 1707 1633 case CLK_19_2_MHZ: ··· 1711 1635 /* Valid Ref Clock Rate */ 1712 1636 break; 1713 1637 default: 1638 + dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n"); 1639 + return -EINVAL; 1640 + } 1641 + 1642 + ret = cdns_torrent_dp_get_pll(cdns_phy, TYPE_NONE); 1643 + if (ret) 1644 + return ret; 1645 + 1646 + cdns_torrent_dp_common_init(cdns_phy, inst); 1647 + 1648 + return cdns_torrent_dp_start(cdns_phy, inst, phy); 1649 + } 1650 + 1651 + static int cdns_torrent_dp_multilink_init(struct cdns_torrent_phy *cdns_phy, 1652 + struct cdns_torrent_inst *inst, 1653 + struct phy *phy) 1654 + { 1655 + if (cdns_phy->ref_clk_rate != CLK_100_MHZ) { 1714 1656 dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n"); 1715 1657 return -EINVAL; 1716 1658 } ··· 2250 2156 u32 num_regs; 2251 2157 int i, j; 2252 2158 2253 - if (cdns_phy->nsubnodes > 1) 2159 + if (cdns_phy->nsubnodes > 1) { 2160 + if (phy_type == TYPE_DP) 2161 + return cdns_torrent_dp_multilink_init(cdns_phy, inst, phy); 2254 2162 return 0; 2163 + } 2255 2164 2256 2165 /** 2257 2166 * Spread spectrum generation is not required or supported ··· 2494 2397 regmap_write(regmap, reg_pairs[j].off, 2495 2398 reg_pairs[j].val); 2496 2399 } 2400 + } 2401 + 2402 + if (phy_t1 == TYPE_DP) { 2403 + ret = cdns_torrent_dp_get_pll(cdns_phy, phy_t2); 2404 + if (ret) 2405 + return ret; 2497 2406 } 2498 2407 2499 2408 reset_control_deassert(cdns_phy->phys[node].lnk_rst); ··· 2896 2793 clk_disable_unprepare(cdns_phy->clk); 2897 2794 cdns_torrent_clk_cleanup(cdns_phy); 2898 2795 } 2796 + 2797 + /* USB and DP link configuration */ 2798 + static struct cdns_reg_pairs usb_dp_link_cmn_regs[] = { 2799 + {0x0002, PHY_PLL_CFG}, 2800 + {0x8600, CMN_PDIAG_PLL0_CLK_SEL_M0} 2801 + }; 2802 + 2803 + static struct cdns_reg_pairs usb_dp_xcvr_diag_ln_regs[] = { 2804 + {0x0000, XCVR_DIAG_HSCLK_SEL}, 2805 + {0x0001, XCVR_DIAG_HSCLK_DIV}, 2806 + {0x0041, XCVR_DIAG_PLLDRC_CTRL} 2807 + }; 2808 + 2809 + static struct cdns_reg_pairs dp_usb_xcvr_diag_ln_regs[] = { 2810 + {0x0001, XCVR_DIAG_HSCLK_SEL}, 2811 + {0x0009, XCVR_DIAG_PLLDRC_CTRL} 2812 + }; 2813 + 2814 + static struct cdns_torrent_vals usb_dp_link_cmn_vals = { 2815 + .reg_pairs = usb_dp_link_cmn_regs, 2816 + .num_regs = ARRAY_SIZE(usb_dp_link_cmn_regs), 2817 + }; 2818 + 2819 + static struct cdns_torrent_vals usb_dp_xcvr_diag_ln_vals = { 2820 + .reg_pairs = usb_dp_xcvr_diag_ln_regs, 2821 + .num_regs = ARRAY_SIZE(usb_dp_xcvr_diag_ln_regs), 2822 + }; 2823 + 2824 + static struct cdns_torrent_vals dp_usb_xcvr_diag_ln_vals = { 2825 + .reg_pairs = dp_usb_xcvr_diag_ln_regs, 2826 + .num_regs = ARRAY_SIZE(dp_usb_xcvr_diag_ln_regs), 2827 + }; 2828 + 2829 + /* PCIe and DP link configuration */ 2830 + static struct cdns_reg_pairs pcie_dp_link_cmn_regs[] = { 2831 + {0x0003, PHY_PLL_CFG}, 2832 + {0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0}, 2833 + {0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1} 2834 + }; 2835 + 2836 + static struct cdns_reg_pairs pcie_dp_xcvr_diag_ln_regs[] = { 2837 + {0x0000, XCVR_DIAG_HSCLK_SEL}, 2838 + {0x0001, XCVR_DIAG_HSCLK_DIV}, 2839 + {0x0012, XCVR_DIAG_PLLDRC_CTRL} 2840 + }; 2841 + 2842 + static struct cdns_reg_pairs dp_pcie_xcvr_diag_ln_regs[] = { 2843 + {0x0001, XCVR_DIAG_HSCLK_SEL}, 2844 + {0x0009, XCVR_DIAG_PLLDRC_CTRL} 2845 + }; 2846 + 2847 + static struct cdns_torrent_vals pcie_dp_link_cmn_vals = { 2848 + .reg_pairs = pcie_dp_link_cmn_regs, 2849 + .num_regs = ARRAY_SIZE(pcie_dp_link_cmn_regs), 2850 + }; 2851 + 2852 + static struct cdns_torrent_vals pcie_dp_xcvr_diag_ln_vals = { 2853 + .reg_pairs = pcie_dp_xcvr_diag_ln_regs, 2854 + .num_regs = ARRAY_SIZE(pcie_dp_xcvr_diag_ln_regs), 2855 + }; 2856 + 2857 + static struct cdns_torrent_vals dp_pcie_xcvr_diag_ln_vals = { 2858 + .reg_pairs = dp_pcie_xcvr_diag_ln_regs, 2859 + .num_regs = ARRAY_SIZE(dp_pcie_xcvr_diag_ln_regs), 2860 + }; 2861 + 2862 + /* DP Multilink, 100 MHz Ref clk, no SSC */ 2863 + static struct cdns_reg_pairs dp_100_no_ssc_cmn_regs[] = { 2864 + {0x007F, CMN_TXPUCAL_TUNE}, 2865 + {0x007F, CMN_TXPDCAL_TUNE} 2866 + }; 2867 + 2868 + static struct cdns_reg_pairs dp_100_no_ssc_tx_ln_regs[] = { 2869 + {0x00FB, TX_PSC_A0}, 2870 + {0x04AA, TX_PSC_A2}, 2871 + {0x04AA, TX_PSC_A3}, 2872 + {0x000F, XCVR_DIAG_BIDI_CTRL} 2873 + }; 2874 + 2875 + static struct cdns_reg_pairs dp_100_no_ssc_rx_ln_regs[] = { 2876 + {0x0000, RX_PSC_A0}, 2877 + {0x0000, RX_PSC_A2}, 2878 + {0x0000, RX_PSC_A3}, 2879 + {0x0000, RX_PSC_CAL}, 2880 + {0x0000, RX_REE_GCSM1_CTRL}, 2881 + {0x0000, RX_REE_GCSM2_CTRL}, 2882 + {0x0000, RX_REE_PERGCSM_CTRL} 2883 + }; 2884 + 2885 + static struct cdns_torrent_vals dp_100_no_ssc_cmn_vals = { 2886 + .reg_pairs = dp_100_no_ssc_cmn_regs, 2887 + .num_regs = ARRAY_SIZE(dp_100_no_ssc_cmn_regs), 2888 + }; 2889 + 2890 + static struct cdns_torrent_vals dp_100_no_ssc_tx_ln_vals = { 2891 + .reg_pairs = dp_100_no_ssc_tx_ln_regs, 2892 + .num_regs = ARRAY_SIZE(dp_100_no_ssc_tx_ln_regs), 2893 + }; 2894 + 2895 + static struct cdns_torrent_vals dp_100_no_ssc_rx_ln_vals = { 2896 + .reg_pairs = dp_100_no_ssc_rx_ln_regs, 2897 + .num_regs = ARRAY_SIZE(dp_100_no_ssc_rx_ln_regs), 2898 + }; 2899 2899 2900 2900 /* Single DisplayPort(DP) link configuration */ 2901 2901 static struct cdns_reg_pairs sl_dp_link_cmn_regs[] = { ··· 3942 3736 [TYPE_NONE] = { 3943 3737 [NO_SSC] = &sl_dp_link_cmn_vals, 3944 3738 }, 3739 + [TYPE_PCIE] = { 3740 + [NO_SSC] = &pcie_dp_link_cmn_vals, 3741 + }, 3742 + [TYPE_USB] = { 3743 + [NO_SSC] = &usb_dp_link_cmn_vals, 3744 + }, 3945 3745 }, 3946 3746 [TYPE_PCIE] = { 3947 3747 [TYPE_NONE] = { ··· 3969 3757 [NO_SSC] = &pcie_usb_link_cmn_vals, 3970 3758 [EXTERNAL_SSC] = &pcie_usb_link_cmn_vals, 3971 3759 [INTERNAL_SSC] = &pcie_usb_link_cmn_vals, 3760 + }, 3761 + [TYPE_DP] = { 3762 + [NO_SSC] = &pcie_dp_link_cmn_vals, 3972 3763 }, 3973 3764 }, 3974 3765 [TYPE_SGMII] = { ··· 4025 3810 [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, 4026 3811 [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, 4027 3812 }, 3813 + [TYPE_DP] = { 3814 + [NO_SSC] = &usb_dp_link_cmn_vals, 3815 + }, 4028 3816 }, 4029 3817 }, 4030 3818 .xcvr_diag_vals = { 4031 3819 [TYPE_DP] = { 4032 3820 [TYPE_NONE] = { 4033 3821 [NO_SSC] = &sl_dp_xcvr_diag_ln_vals, 3822 + }, 3823 + [TYPE_PCIE] = { 3824 + [NO_SSC] = &dp_pcie_xcvr_diag_ln_vals, 3825 + }, 3826 + [TYPE_USB] = { 3827 + [NO_SSC] = &dp_usb_xcvr_diag_ln_vals, 4034 3828 }, 4035 3829 }, 4036 3830 [TYPE_PCIE] = { ··· 4062 3838 [NO_SSC] = &pcie_usb_xcvr_diag_ln_vals, 4063 3839 [EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, 4064 3840 [INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, 3841 + }, 3842 + [TYPE_DP] = { 3843 + [NO_SSC] = &pcie_dp_xcvr_diag_ln_vals, 4065 3844 }, 4066 3845 }, 4067 3846 [TYPE_SGMII] = { ··· 4118 3891 [EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, 4119 3892 [INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, 4120 3893 }, 3894 + [TYPE_DP] = { 3895 + [NO_SSC] = &usb_dp_xcvr_diag_ln_vals, 3896 + }, 4121 3897 }, 4122 3898 }, 4123 3899 .pcs_cmn_vals = { ··· 4145 3915 [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, 4146 3916 [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, 4147 3917 }, 3918 + [TYPE_DP] = { 3919 + [NO_SSC] = &usb_phy_pcs_cmn_vals, 3920 + }, 4148 3921 }, 4149 3922 }, 4150 3923 .cmn_vals = { ··· 4168 3935 [CLK_100_MHZ] = { 4169 3936 [TYPE_DP] = { 4170 3937 [TYPE_NONE] = { 3938 + [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, 3939 + }, 3940 + [TYPE_PCIE] = { 3941 + [NO_SSC] = &dp_100_no_ssc_cmn_vals, 3942 + }, 3943 + [TYPE_USB] = { 4171 3944 [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, 4172 3945 }, 4173 3946 }, ··· 4197 3958 [NO_SSC] = &pcie_100_no_ssc_cmn_vals, 4198 3959 [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, 4199 3960 [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, 3961 + }, 3962 + [TYPE_DP] = { 3963 + [NO_SSC] = NULL, 4200 3964 }, 4201 3965 }, 4202 3966 [TYPE_SGMII] = { ··· 4253 4011 [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, 4254 4012 [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, 4255 4013 }, 4014 + [TYPE_DP] = { 4015 + [NO_SSC] = &usb_100_no_ssc_cmn_vals, 4016 + }, 4256 4017 }, 4257 4018 }, 4258 4019 }, ··· 4279 4034 [TYPE_NONE] = { 4280 4035 [NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals, 4281 4036 }, 4037 + [TYPE_PCIE] = { 4038 + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, 4039 + }, 4040 + [TYPE_USB] = { 4041 + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, 4042 + }, 4282 4043 }, 4283 4044 [TYPE_PCIE] = { 4284 4045 [TYPE_NONE] = { ··· 4306 4055 [NO_SSC] = NULL, 4307 4056 [EXTERNAL_SSC] = NULL, 4308 4057 [INTERNAL_SSC] = NULL, 4058 + }, 4059 + [TYPE_DP] = { 4060 + [NO_SSC] = NULL, 4309 4061 }, 4310 4062 }, 4311 4063 [TYPE_SGMII] = { ··· 4361 4107 [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, 4362 4108 [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, 4363 4109 [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, 4110 + }, 4111 + [TYPE_DP] = { 4112 + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, 4364 4113 }, 4365 4114 }, 4366 4115 }, ··· 4388 4131 [TYPE_NONE] = { 4389 4132 [NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals, 4390 4133 }, 4134 + [TYPE_PCIE] = { 4135 + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, 4136 + }, 4137 + [TYPE_USB] = { 4138 + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, 4139 + }, 4391 4140 }, 4392 4141 [TYPE_PCIE] = { 4393 4142 [TYPE_NONE] = { ··· 4415 4152 [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, 4416 4153 [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, 4417 4154 [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, 4155 + }, 4156 + [TYPE_DP] = { 4157 + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, 4418 4158 }, 4419 4159 }, 4420 4160 [TYPE_SGMII] = { ··· 4470 4204 [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, 4471 4205 [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, 4472 4206 [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, 4207 + }, 4208 + [TYPE_DP] = { 4209 + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, 4473 4210 }, 4474 4211 }, 4475 4212 }, ··· 4487 4218 [TYPE_NONE] = { 4488 4219 [NO_SSC] = &sl_dp_link_cmn_vals, 4489 4220 }, 4221 + [TYPE_PCIE] = { 4222 + [NO_SSC] = &pcie_dp_link_cmn_vals, 4223 + }, 4224 + [TYPE_USB] = { 4225 + [NO_SSC] = &usb_dp_link_cmn_vals, 4226 + }, 4490 4227 }, 4491 4228 [TYPE_PCIE] = { 4492 4229 [TYPE_NONE] = { ··· 4514 4239 [NO_SSC] = &pcie_usb_link_cmn_vals, 4515 4240 [EXTERNAL_SSC] = &pcie_usb_link_cmn_vals, 4516 4241 [INTERNAL_SSC] = &pcie_usb_link_cmn_vals, 4242 + }, 4243 + [TYPE_DP] = { 4244 + [NO_SSC] = &pcie_dp_link_cmn_vals, 4517 4245 }, 4518 4246 }, 4519 4247 [TYPE_SGMII] = { ··· 4570 4292 [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, 4571 4293 [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, 4572 4294 }, 4295 + [TYPE_DP] = { 4296 + [NO_SSC] = &usb_dp_link_cmn_vals, 4297 + }, 4573 4298 }, 4574 4299 }, 4575 4300 .xcvr_diag_vals = { 4576 4301 [TYPE_DP] = { 4577 4302 [TYPE_NONE] = { 4578 4303 [NO_SSC] = &sl_dp_xcvr_diag_ln_vals, 4304 + }, 4305 + [TYPE_PCIE] = { 4306 + [NO_SSC] = &dp_pcie_xcvr_diag_ln_vals, 4307 + }, 4308 + [TYPE_USB] = { 4309 + [NO_SSC] = &dp_usb_xcvr_diag_ln_vals, 4579 4310 }, 4580 4311 }, 4581 4312 [TYPE_PCIE] = { ··· 4607 4320 [NO_SSC] = &pcie_usb_xcvr_diag_ln_vals, 4608 4321 [EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, 4609 4322 [INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, 4323 + }, 4324 + [TYPE_DP] = { 4325 + [NO_SSC] = &pcie_dp_xcvr_diag_ln_vals, 4610 4326 }, 4611 4327 }, 4612 4328 [TYPE_SGMII] = { ··· 4663 4373 [EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, 4664 4374 [INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, 4665 4375 }, 4376 + [TYPE_DP] = { 4377 + [NO_SSC] = &usb_dp_xcvr_diag_ln_vals, 4378 + }, 4666 4379 }, 4667 4380 }, 4668 4381 .pcs_cmn_vals = { ··· 4690 4397 [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, 4691 4398 [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, 4692 4399 }, 4400 + [TYPE_DP] = { 4401 + [NO_SSC] = &usb_phy_pcs_cmn_vals, 4402 + }, 4693 4403 }, 4694 4404 }, 4695 4405 .cmn_vals = { ··· 4713 4417 [CLK_100_MHZ] = { 4714 4418 [TYPE_DP] = { 4715 4419 [TYPE_NONE] = { 4420 + [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, 4421 + }, 4422 + [TYPE_PCIE] = { 4423 + [NO_SSC] = &dp_100_no_ssc_cmn_vals, 4424 + }, 4425 + [TYPE_USB] = { 4716 4426 [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, 4717 4427 }, 4718 4428 }, ··· 4742 4440 [NO_SSC] = &pcie_100_no_ssc_cmn_vals, 4743 4441 [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, 4744 4442 [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, 4443 + }, 4444 + [TYPE_DP] = { 4445 + [NO_SSC] = NULL, 4745 4446 }, 4746 4447 }, 4747 4448 [TYPE_SGMII] = { ··· 4798 4493 [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, 4799 4494 [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, 4800 4495 }, 4496 + [TYPE_DP] = { 4497 + [NO_SSC] = &usb_100_no_ssc_cmn_vals, 4498 + }, 4801 4499 }, 4802 4500 }, 4803 4501 }, ··· 4824 4516 [TYPE_NONE] = { 4825 4517 [NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals, 4826 4518 }, 4519 + [TYPE_PCIE] = { 4520 + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, 4521 + }, 4522 + [TYPE_USB] = { 4523 + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, 4524 + }, 4827 4525 }, 4828 4526 [TYPE_PCIE] = { 4829 4527 [TYPE_NONE] = { ··· 4851 4537 [NO_SSC] = NULL, 4852 4538 [EXTERNAL_SSC] = NULL, 4853 4539 [INTERNAL_SSC] = NULL, 4540 + }, 4541 + [TYPE_DP] = { 4542 + [NO_SSC] = NULL, 4854 4543 }, 4855 4544 }, 4856 4545 [TYPE_SGMII] = { ··· 4906 4589 [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, 4907 4590 [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, 4908 4591 [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, 4592 + }, 4593 + [TYPE_DP] = { 4594 + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, 4909 4595 }, 4910 4596 }, 4911 4597 }, ··· 4933 4613 [TYPE_NONE] = { 4934 4614 [NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals, 4935 4615 }, 4616 + [TYPE_PCIE] = { 4617 + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, 4618 + }, 4619 + [TYPE_USB] = { 4620 + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, 4621 + }, 4936 4622 }, 4937 4623 [TYPE_PCIE] = { 4938 4624 [TYPE_NONE] = { ··· 4960 4634 [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, 4961 4635 [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, 4962 4636 [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, 4637 + }, 4638 + [TYPE_DP] = { 4639 + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, 4963 4640 }, 4964 4641 }, 4965 4642 [TYPE_SGMII] = { ··· 5015 4686 [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, 5016 4687 [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, 5017 4688 [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, 4689 + }, 4690 + [TYPE_DP] = { 4691 + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, 5018 4692 }, 5019 4693 }, 5020 4694 },
+1 -3
drivers/phy/freescale/phy-fsl-imx8m-pcie.c
··· 206 206 struct device *dev = &pdev->dev; 207 207 struct device_node *np = dev->of_node; 208 208 struct imx8_pcie_phy *imx8_phy; 209 - struct resource *res; 210 209 211 210 imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL); 212 211 if (!imx8_phy) ··· 258 259 "Failed to get PCIE PHY PERST control\n"); 259 260 } 260 261 261 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 262 - imx8_phy->base = devm_ioremap_resource(dev, res); 262 + imx8_phy->base = devm_platform_ioremap_resource(pdev, 0); 263 263 if (IS_ERR(imx8_phy->base)) 264 264 return PTR_ERR(imx8_phy->base); 265 265
+218
drivers/phy/freescale/phy-fsl-imx8mq-usb.c
··· 27 27 #define PHY_CTRL2_TXENABLEN0 BIT(8) 28 28 #define PHY_CTRL2_OTG_DISABLE BIT(9) 29 29 30 + #define PHY_CTRL3 0xc 31 + #define PHY_CTRL3_COMPDISTUNE_MASK GENMASK(2, 0) 32 + #define PHY_CTRL3_TXPREEMP_TUNE_MASK GENMASK(16, 15) 33 + #define PHY_CTRL3_TXRISE_TUNE_MASK GENMASK(21, 20) 34 + #define PHY_CTRL3_TXVREF_TUNE_MASK GENMASK(25, 22) 35 + #define PHY_CTRL3_TX_VBOOST_LEVEL_MASK GENMASK(31, 29) 36 + 37 + #define PHY_CTRL4 0x10 38 + #define PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(20, 15) 39 + 40 + #define PHY_CTRL5 0x14 41 + #define PHY_CTRL5_DMPWD_OVERRIDE_SEL BIT(23) 42 + #define PHY_CTRL5_DMPWD_OVERRIDE BIT(22) 43 + #define PHY_CTRL5_DPPWD_OVERRIDE_SEL BIT(21) 44 + #define PHY_CTRL5_DPPWD_OVERRIDE BIT(20) 45 + #define PHY_CTRL5_PCS_TX_SWING_FULL_MASK GENMASK(6, 0) 46 + 30 47 #define PHY_CTRL6 0x18 31 48 #define PHY_CTRL6_ALT_CLK_EN BIT(1) 32 49 #define PHY_CTRL6_ALT_CLK_SEL BIT(0) 50 + 51 + #define PHY_TUNE_DEFAULT 0xffffffff 33 52 34 53 struct imx8mq_usb_phy { 35 54 struct phy *phy; 36 55 struct clk *clk; 37 56 void __iomem *base; 38 57 struct regulator *vbus; 58 + u32 pcs_tx_swing_full; 59 + u32 pcs_tx_deemph_3p5db; 60 + u32 tx_vref_tune; 61 + u32 tx_rise_tune; 62 + u32 tx_preemp_amp_tune; 63 + u32 tx_vboost_level; 64 + u32 comp_dis_tune; 39 65 }; 66 + 67 + static u32 phy_tx_vref_tune_from_property(u32 percent) 68 + { 69 + percent = clamp(percent, 94U, 124U); 70 + 71 + return DIV_ROUND_CLOSEST(percent - 94U, 2); 72 + } 73 + 74 + static u32 phy_tx_rise_tune_from_property(u32 percent) 75 + { 76 + switch (percent) { 77 + case 0 ... 98: 78 + return 3; 79 + case 99: 80 + return 2; 81 + case 100 ... 101: 82 + return 1; 83 + default: 84 + return 0; 85 + } 86 + } 87 + 88 + static u32 phy_tx_preemp_amp_tune_from_property(u32 microamp) 89 + { 90 + microamp = min(microamp, 1800U); 91 + 92 + return microamp / 600; 93 + } 94 + 95 + static u32 phy_tx_vboost_level_from_property(u32 microvolt) 96 + { 97 + switch (microvolt) { 98 + case 0 ... 960: 99 + return 0; 100 + case 961 ... 1160: 101 + return 2; 102 + default: 103 + return 3; 104 + } 105 + } 106 + 107 + static u32 phy_pcs_tx_deemph_3p5db_from_property(u32 decibel) 108 + { 109 + return min(decibel, 36U); 110 + } 111 + 112 + static u32 phy_comp_dis_tune_from_property(u32 percent) 113 + { 114 + switch (percent) { 115 + case 0 ... 92: 116 + return 0; 117 + case 93 ... 95: 118 + return 1; 119 + case 96 ... 97: 120 + return 2; 121 + case 98 ... 102: 122 + return 3; 123 + case 103 ... 105: 124 + return 4; 125 + case 106 ... 109: 126 + return 5; 127 + case 110 ... 113: 128 + return 6; 129 + default: 130 + return 7; 131 + } 132 + } 133 + static u32 phy_pcs_tx_swing_full_from_property(u32 percent) 134 + { 135 + percent = min(percent, 100U); 136 + 137 + return (percent * 127) / 100; 138 + } 139 + 140 + static void imx8m_get_phy_tuning_data(struct imx8mq_usb_phy *imx_phy) 141 + { 142 + struct device *dev = imx_phy->phy->dev.parent; 143 + 144 + if (device_property_read_u32(dev, "fsl,phy-tx-vref-tune-percent", 145 + &imx_phy->tx_vref_tune)) 146 + imx_phy->tx_vref_tune = PHY_TUNE_DEFAULT; 147 + else 148 + imx_phy->tx_vref_tune = 149 + phy_tx_vref_tune_from_property(imx_phy->tx_vref_tune); 150 + 151 + if (device_property_read_u32(dev, "fsl,phy-tx-rise-tune-percent", 152 + &imx_phy->tx_rise_tune)) 153 + imx_phy->tx_rise_tune = PHY_TUNE_DEFAULT; 154 + else 155 + imx_phy->tx_rise_tune = 156 + phy_tx_rise_tune_from_property(imx_phy->tx_rise_tune); 157 + 158 + if (device_property_read_u32(dev, "fsl,phy-tx-preemp-amp-tune-microamp", 159 + &imx_phy->tx_preemp_amp_tune)) 160 + imx_phy->tx_preemp_amp_tune = PHY_TUNE_DEFAULT; 161 + else 162 + imx_phy->tx_preemp_amp_tune = 163 + phy_tx_preemp_amp_tune_from_property(imx_phy->tx_preemp_amp_tune); 164 + 165 + if (device_property_read_u32(dev, "fsl,phy-tx-vboost-level-microvolt", 166 + &imx_phy->tx_vboost_level)) 167 + imx_phy->tx_vboost_level = PHY_TUNE_DEFAULT; 168 + else 169 + imx_phy->tx_vboost_level = 170 + phy_tx_vboost_level_from_property(imx_phy->tx_vboost_level); 171 + 172 + if (device_property_read_u32(dev, "fsl,phy-comp-dis-tune-percent", 173 + &imx_phy->comp_dis_tune)) 174 + imx_phy->comp_dis_tune = PHY_TUNE_DEFAULT; 175 + else 176 + imx_phy->comp_dis_tune = 177 + phy_comp_dis_tune_from_property(imx_phy->comp_dis_tune); 178 + 179 + if (device_property_read_u32(dev, "fsl,pcs-tx-deemph-3p5db-attenuation-db", 180 + &imx_phy->pcs_tx_deemph_3p5db)) 181 + imx_phy->pcs_tx_deemph_3p5db = PHY_TUNE_DEFAULT; 182 + else 183 + imx_phy->pcs_tx_deemph_3p5db = 184 + phy_pcs_tx_deemph_3p5db_from_property(imx_phy->pcs_tx_deemph_3p5db); 185 + 186 + if (device_property_read_u32(dev, "fsl,phy-pcs-tx-swing-full-percent", 187 + &imx_phy->pcs_tx_swing_full)) 188 + imx_phy->pcs_tx_swing_full = PHY_TUNE_DEFAULT; 189 + else 190 + imx_phy->pcs_tx_swing_full = 191 + phy_pcs_tx_swing_full_from_property(imx_phy->pcs_tx_swing_full); 192 + } 193 + 194 + static void imx8m_phy_tune(struct imx8mq_usb_phy *imx_phy) 195 + { 196 + u32 value; 197 + 198 + /* PHY tuning */ 199 + if (imx_phy->pcs_tx_deemph_3p5db != PHY_TUNE_DEFAULT) { 200 + value = readl(imx_phy->base + PHY_CTRL4); 201 + value &= ~PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK; 202 + value |= FIELD_PREP(PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK, 203 + imx_phy->pcs_tx_deemph_3p5db); 204 + writel(value, imx_phy->base + PHY_CTRL4); 205 + } 206 + 207 + if (imx_phy->pcs_tx_swing_full != PHY_TUNE_DEFAULT) { 208 + value = readl(imx_phy->base + PHY_CTRL5); 209 + value |= FIELD_PREP(PHY_CTRL5_PCS_TX_SWING_FULL_MASK, 210 + imx_phy->pcs_tx_swing_full); 211 + writel(value, imx_phy->base + PHY_CTRL5); 212 + } 213 + 214 + if ((imx_phy->tx_vref_tune & imx_phy->tx_rise_tune & 215 + imx_phy->tx_preemp_amp_tune & imx_phy->comp_dis_tune & 216 + imx_phy->tx_vboost_level) == PHY_TUNE_DEFAULT) 217 + /* If all are the default values, no need update. */ 218 + return; 219 + 220 + value = readl(imx_phy->base + PHY_CTRL3); 221 + 222 + if (imx_phy->tx_vref_tune != PHY_TUNE_DEFAULT) { 223 + value &= ~PHY_CTRL3_TXVREF_TUNE_MASK; 224 + value |= FIELD_PREP(PHY_CTRL3_TXVREF_TUNE_MASK, 225 + imx_phy->tx_vref_tune); 226 + } 227 + 228 + if (imx_phy->tx_rise_tune != PHY_TUNE_DEFAULT) { 229 + value &= ~PHY_CTRL3_TXRISE_TUNE_MASK; 230 + value |= FIELD_PREP(PHY_CTRL3_TXRISE_TUNE_MASK, 231 + imx_phy->tx_rise_tune); 232 + } 233 + 234 + if (imx_phy->tx_preemp_amp_tune != PHY_TUNE_DEFAULT) { 235 + value &= ~PHY_CTRL3_TXPREEMP_TUNE_MASK; 236 + value |= FIELD_PREP(PHY_CTRL3_TXPREEMP_TUNE_MASK, 237 + imx_phy->tx_preemp_amp_tune); 238 + } 239 + 240 + if (imx_phy->comp_dis_tune != PHY_TUNE_DEFAULT) { 241 + value &= ~PHY_CTRL3_COMPDISTUNE_MASK; 242 + value |= FIELD_PREP(PHY_CTRL3_COMPDISTUNE_MASK, 243 + imx_phy->comp_dis_tune); 244 + } 245 + 246 + if (imx_phy->tx_vboost_level != PHY_TUNE_DEFAULT) { 247 + value &= ~PHY_CTRL3_TX_VBOOST_LEVEL_MASK; 248 + value |= FIELD_PREP(PHY_CTRL3_TX_VBOOST_LEVEL_MASK, 249 + imx_phy->tx_vboost_level); 250 + } 251 + 252 + writel(value, imx_phy->base + PHY_CTRL3); 253 + } 40 254 41 255 static int imx8mq_usb_phy_init(struct phy *phy) 42 256 { ··· 312 98 value = readl(imx_phy->base + PHY_CTRL1); 313 99 value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); 314 100 writel(value, imx_phy->base + PHY_CTRL1); 101 + 102 + imx8m_phy_tune(imx_phy); 315 103 316 104 return 0; 317 105 } ··· 397 181 return PTR_ERR(imx_phy->vbus); 398 182 399 183 phy_set_drvdata(imx_phy->phy, imx_phy); 184 + 185 + imx8m_get_phy_tuning_data(imx_phy); 400 186 401 187 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 402 188
+1 -1
drivers/phy/hisilicon/Kconfig
··· 54 54 55 55 config PHY_HISI_INNO_USB2 56 56 tristate "HiSilicon INNO USB2 PHY support" 57 - depends on (ARCH_HISI && ARM64) || COMPILE_TEST 57 + depends on ARCH_HISI || COMPILE_TEST 58 58 select GENERIC_PHY 59 59 select MFD_SYSCON 60 60 help
+45 -15
drivers/phy/hisilicon/phy-hisi-inno-usb2.c
··· 9 9 #include <linux/delay.h> 10 10 #include <linux/io.h> 11 11 #include <linux/module.h> 12 - #include <linux/platform_device.h> 12 + #include <linux/of_device.h> 13 13 #include <linux/phy/phy.h> 14 14 #include <linux/reset.h> 15 15 ··· 20 20 #define PHY_CLK_STABLE_TIME 2 /* unit:ms */ 21 21 #define UTMI_RST_COMPLETE_TIME 2 /* unit:ms */ 22 22 #define POR_RST_COMPLETE_TIME 300 /* unit:us */ 23 + 24 + #define PHY_TYPE_0 0 25 + #define PHY_TYPE_1 1 26 + 23 27 #define PHY_TEST_DATA GENMASK(7, 0) 24 - #define PHY_TEST_ADDR GENMASK(15, 8) 25 - #define PHY_TEST_PORT GENMASK(18, 16) 26 - #define PHY_TEST_WREN BIT(21) 27 - #define PHY_TEST_CLK BIT(22) /* rising edge active */ 28 - #define PHY_TEST_RST BIT(23) /* low active */ 28 + #define PHY_TEST_ADDR_OFFSET 8 29 + #define PHY0_TEST_ADDR GENMASK(15, 8) 30 + #define PHY0_TEST_PORT_OFFSET 16 31 + #define PHY0_TEST_PORT GENMASK(18, 16) 32 + #define PHY0_TEST_WREN BIT(21) 33 + #define PHY0_TEST_CLK BIT(22) /* rising edge active */ 34 + #define PHY0_TEST_RST BIT(23) /* low active */ 35 + #define PHY1_TEST_ADDR GENMASK(11, 8) 36 + #define PHY1_TEST_PORT_OFFSET 12 37 + #define PHY1_TEST_PORT BIT(12) 38 + #define PHY1_TEST_WREN BIT(13) 39 + #define PHY1_TEST_CLK BIT(14) /* rising edge active */ 40 + #define PHY1_TEST_RST BIT(15) /* low active */ 41 + 29 42 #define PHY_CLK_ENABLE BIT(2) 30 43 31 44 struct hisi_inno_phy_port { ··· 50 37 void __iomem *mmio; 51 38 struct clk *ref_clk; 52 39 struct reset_control *por_rst; 40 + unsigned int type; 53 41 struct hisi_inno_phy_port ports[INNO_PHY_PORT_NUM]; 54 42 }; 55 43 ··· 59 45 { 60 46 void __iomem *reg = priv->mmio; 61 47 u32 val; 48 + u32 value; 62 49 63 - val = (data & PHY_TEST_DATA) | 64 - ((addr << 8) & PHY_TEST_ADDR) | 65 - ((port << 16) & PHY_TEST_PORT) | 66 - PHY_TEST_WREN | PHY_TEST_RST; 50 + if (priv->type == PHY_TYPE_0) 51 + val = (data & PHY_TEST_DATA) | 52 + ((addr << PHY_TEST_ADDR_OFFSET) & PHY0_TEST_ADDR) | 53 + ((port << PHY0_TEST_PORT_OFFSET) & PHY0_TEST_PORT) | 54 + PHY0_TEST_WREN | PHY0_TEST_RST; 55 + else 56 + val = (data & PHY_TEST_DATA) | 57 + ((addr << PHY_TEST_ADDR_OFFSET) & PHY1_TEST_ADDR) | 58 + ((port << PHY1_TEST_PORT_OFFSET) & PHY1_TEST_PORT) | 59 + PHY1_TEST_WREN | PHY1_TEST_RST; 67 60 writel(val, reg); 68 61 69 - val |= PHY_TEST_CLK; 70 - writel(val, reg); 62 + value = val; 63 + if (priv->type == PHY_TYPE_0) 64 + value |= PHY0_TEST_CLK; 65 + else 66 + value |= PHY1_TEST_CLK; 67 + writel(value, reg); 71 68 72 - val &= ~PHY_TEST_CLK; 73 69 writel(val, reg); 74 70 } 75 71 ··· 159 135 if (IS_ERR(priv->por_rst)) 160 136 return PTR_ERR(priv->por_rst); 161 137 138 + priv->type = (uintptr_t) of_device_get_match_data(dev); 139 + 162 140 for_each_child_of_node(np, child) { 163 141 struct reset_control *rst; 164 142 struct phy *phy; ··· 196 170 } 197 171 198 172 static const struct of_device_id hisi_inno_phy_of_match[] = { 199 - { .compatible = "hisilicon,inno-usb2-phy", }, 200 - { .compatible = "hisilicon,hi3798cv200-usb2-phy", }, 173 + { .compatible = "hisilicon,inno-usb2-phy", 174 + .data = (void *) PHY_TYPE_0 }, 175 + { .compatible = "hisilicon,hi3798cv200-usb2-phy", 176 + .data = (void *) PHY_TYPE_0 }, 177 + { .compatible = "hisilicon,hi3798mv100-usb2-phy", 178 + .data = (void *) PHY_TYPE_1 }, 201 179 { }, 202 180 }; 203 181 MODULE_DEVICE_TABLE(of, hisi_inno_phy_of_match);
+356
drivers/phy/mediatek/phy-mtk-tphy.c
··· 7 7 8 8 #include <dt-bindings/phy/phy.h> 9 9 #include <linux/clk.h> 10 + #include <linux/debugfs.h> 10 11 #include <linux/delay.h> 11 12 #include <linux/iopoll.h> 12 13 #include <linux/mfd/syscon.h> ··· 265 264 266 265 #define TPHY_CLKS_CNT 2 267 266 267 + #define USER_BUF_LEN(count) min_t(size_t, 8, (count)) 268 + 268 269 enum mtk_phy_version { 269 270 MTK_PHY_V1 = 1, 270 271 MTK_PHY_V2, ··· 338 335 int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ 339 336 int src_coef; /* coefficient for slew rate calibrate */ 340 337 }; 338 + 339 + #if IS_ENABLED(CONFIG_DEBUG_FS) 340 + 341 + enum u2_phy_params { 342 + U2P_EYE_VRT = 0, 343 + U2P_EYE_TERM, 344 + U2P_EFUSE_EN, 345 + U2P_EFUSE_INTR, 346 + U2P_DISCTH, 347 + U2P_PRE_EMPHASIS, 348 + }; 349 + 350 + enum u3_phy_params { 351 + U3P_EFUSE_EN = 0, 352 + U3P_EFUSE_INTR, 353 + U3P_EFUSE_TX_IMP, 354 + U3P_EFUSE_RX_IMP, 355 + }; 356 + 357 + static const char *const u2_phy_files[] = { 358 + [U2P_EYE_VRT] = "vrt", 359 + [U2P_EYE_TERM] = "term", 360 + [U2P_EFUSE_EN] = "efuse", 361 + [U2P_EFUSE_INTR] = "intr", 362 + [U2P_DISCTH] = "discth", 363 + [U2P_PRE_EMPHASIS] = "preemph", 364 + }; 365 + 366 + static const char *const u3_phy_files[] = { 367 + [U3P_EFUSE_EN] = "efuse", 368 + [U3P_EFUSE_INTR] = "intr", 369 + [U3P_EFUSE_TX_IMP] = "tx-imp", 370 + [U3P_EFUSE_RX_IMP] = "rx-imp", 371 + }; 372 + 373 + static int u2_phy_params_show(struct seq_file *sf, void *unused) 374 + { 375 + struct mtk_phy_instance *inst = sf->private; 376 + const char *fname = file_dentry(sf->file)->d_iname; 377 + struct u2phy_banks *u2_banks = &inst->u2_banks; 378 + void __iomem *com = u2_banks->com; 379 + u32 max = 0; 380 + u32 tmp = 0; 381 + u32 val = 0; 382 + int ret; 383 + 384 + ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname); 385 + if (ret < 0) 386 + return ret; 387 + 388 + switch (ret) { 389 + case U2P_EYE_VRT: 390 + tmp = readl(com + U3P_USBPHYACR1); 391 + val = FIELD_GET(PA1_RG_VRT_SEL, tmp); 392 + max = FIELD_MAX(PA1_RG_VRT_SEL); 393 + break; 394 + 395 + case U2P_EYE_TERM: 396 + tmp = readl(com + U3P_USBPHYACR1); 397 + val = FIELD_GET(PA1_RG_TERM_SEL, tmp); 398 + max = FIELD_MAX(PA1_RG_TERM_SEL); 399 + break; 400 + 401 + case U2P_EFUSE_EN: 402 + if (u2_banks->misc) { 403 + tmp = readl(u2_banks->misc + U3P_MISC_REG1); 404 + max = 1; 405 + } 406 + 407 + val = !!(tmp & MR1_EFUSE_AUTO_LOAD_DIS); 408 + break; 409 + 410 + case U2P_EFUSE_INTR: 411 + tmp = readl(com + U3P_USBPHYACR1); 412 + val = FIELD_GET(PA1_RG_INTR_CAL, tmp); 413 + max = FIELD_MAX(PA1_RG_INTR_CAL); 414 + break; 415 + 416 + case U2P_DISCTH: 417 + tmp = readl(com + U3P_USBPHYACR6); 418 + val = FIELD_GET(PA6_RG_U2_DISCTH, tmp); 419 + max = FIELD_MAX(PA6_RG_U2_DISCTH); 420 + break; 421 + 422 + case U2P_PRE_EMPHASIS: 423 + tmp = readl(com + U3P_USBPHYACR6); 424 + val = FIELD_GET(PA6_RG_U2_PRE_EMP, tmp); 425 + max = FIELD_MAX(PA6_RG_U2_PRE_EMP); 426 + break; 427 + 428 + default: 429 + seq_printf(sf, "invalid, %d\n", ret); 430 + break; 431 + } 432 + 433 + seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max); 434 + 435 + return 0; 436 + } 437 + 438 + static int u2_phy_params_open(struct inode *inode, struct file *file) 439 + { 440 + return single_open(file, u2_phy_params_show, inode->i_private); 441 + } 442 + 443 + static ssize_t u2_phy_params_write(struct file *file, const char __user *ubuf, 444 + size_t count, loff_t *ppos) 445 + { 446 + const char *fname = file_dentry(file)->d_iname; 447 + struct seq_file *sf = file->private_data; 448 + struct mtk_phy_instance *inst = sf->private; 449 + struct u2phy_banks *u2_banks = &inst->u2_banks; 450 + void __iomem *com = u2_banks->com; 451 + ssize_t rc; 452 + u32 val; 453 + int ret; 454 + 455 + rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val); 456 + if (rc) 457 + return rc; 458 + 459 + ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname); 460 + if (ret < 0) 461 + return (ssize_t)ret; 462 + 463 + switch (ret) { 464 + case U2P_EYE_VRT: 465 + mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL, val); 466 + break; 467 + 468 + case U2P_EYE_TERM: 469 + mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_TERM_SEL, val); 470 + break; 471 + 472 + case U2P_EFUSE_EN: 473 + if (u2_banks->misc) 474 + mtk_phy_update_field(u2_banks->misc + U3P_MISC_REG1, 475 + MR1_EFUSE_AUTO_LOAD_DIS, !!val); 476 + break; 477 + 478 + case U2P_EFUSE_INTR: 479 + mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_INTR_CAL, val); 480 + break; 481 + 482 + case U2P_DISCTH: 483 + mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_DISCTH, val); 484 + break; 485 + 486 + case U2P_PRE_EMPHASIS: 487 + mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_PRE_EMP, val); 488 + break; 489 + 490 + default: 491 + break; 492 + } 493 + 494 + return count; 495 + } 496 + 497 + static const struct file_operations u2_phy_fops = { 498 + .open = u2_phy_params_open, 499 + .write = u2_phy_params_write, 500 + .read = seq_read, 501 + .llseek = seq_lseek, 502 + .release = single_release, 503 + }; 504 + 505 + static void u2_phy_dbgfs_files_create(struct mtk_phy_instance *inst) 506 + { 507 + u32 count = ARRAY_SIZE(u2_phy_files); 508 + int i; 509 + 510 + for (i = 0; i < count; i++) 511 + debugfs_create_file(u2_phy_files[i], 0644, inst->phy->debugfs, 512 + inst, &u2_phy_fops); 513 + } 514 + 515 + static int u3_phy_params_show(struct seq_file *sf, void *unused) 516 + { 517 + struct mtk_phy_instance *inst = sf->private; 518 + const char *fname = file_dentry(sf->file)->d_iname; 519 + struct u3phy_banks *u3_banks = &inst->u3_banks; 520 + u32 val = 0; 521 + u32 max = 0; 522 + u32 tmp; 523 + int ret; 524 + 525 + ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname); 526 + if (ret < 0) 527 + return ret; 528 + 529 + switch (ret) { 530 + case U3P_EFUSE_EN: 531 + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV); 532 + val = !!(tmp & P3D_RG_EFUSE_AUTO_LOAD_DIS); 533 + max = 1; 534 + break; 535 + 536 + case U3P_EFUSE_INTR: 537 + tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0); 538 + val = FIELD_GET(P3A_RG_IEXT_INTR, tmp); 539 + max = FIELD_MAX(P3A_RG_IEXT_INTR); 540 + break; 541 + 542 + case U3P_EFUSE_TX_IMP: 543 + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0); 544 + val = FIELD_GET(P3D_RG_TX_IMPEL, tmp); 545 + max = FIELD_MAX(P3D_RG_TX_IMPEL); 546 + break; 547 + 548 + case U3P_EFUSE_RX_IMP: 549 + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1); 550 + val = FIELD_GET(P3D_RG_RX_IMPEL, tmp); 551 + max = FIELD_MAX(P3D_RG_RX_IMPEL); 552 + break; 553 + 554 + default: 555 + seq_printf(sf, "invalid, %d\n", ret); 556 + break; 557 + } 558 + 559 + seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max); 560 + 561 + return 0; 562 + } 563 + 564 + static int u3_phy_params_open(struct inode *inode, struct file *file) 565 + { 566 + return single_open(file, u3_phy_params_show, inode->i_private); 567 + } 568 + 569 + static ssize_t u3_phy_params_write(struct file *file, const char __user *ubuf, 570 + size_t count, loff_t *ppos) 571 + { 572 + const char *fname = file_dentry(file)->d_iname; 573 + struct seq_file *sf = file->private_data; 574 + struct mtk_phy_instance *inst = sf->private; 575 + struct u3phy_banks *u3_banks = &inst->u3_banks; 576 + void __iomem *phyd = u3_banks->phyd; 577 + ssize_t rc; 578 + u32 val; 579 + int ret; 580 + 581 + rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val); 582 + if (rc) 583 + return rc; 584 + 585 + ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname); 586 + if (ret < 0) 587 + return (ssize_t)ret; 588 + 589 + switch (ret) { 590 + case U3P_EFUSE_EN: 591 + mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV, 592 + P3D_RG_EFUSE_AUTO_LOAD_DIS, !!val); 593 + break; 594 + 595 + case U3P_EFUSE_INTR: 596 + mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0, 597 + P3A_RG_IEXT_INTR, val); 598 + break; 599 + 600 + case U3P_EFUSE_TX_IMP: 601 + mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_TX_IMPEL, val); 602 + mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_FORCE_TX_IMPEL); 603 + break; 604 + 605 + case U3P_EFUSE_RX_IMP: 606 + mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_RX_IMPEL, val); 607 + mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_FORCE_RX_IMPEL); 608 + break; 609 + 610 + default: 611 + break; 612 + } 613 + 614 + return count; 615 + } 616 + 617 + static const struct file_operations u3_phy_fops = { 618 + .open = u3_phy_params_open, 619 + .write = u3_phy_params_write, 620 + .read = seq_read, 621 + .llseek = seq_lseek, 622 + .release = single_release, 623 + }; 624 + 625 + static void u3_phy_dbgfs_files_create(struct mtk_phy_instance *inst) 626 + { 627 + u32 count = ARRAY_SIZE(u3_phy_files); 628 + int i; 629 + 630 + for (i = 0; i < count; i++) 631 + debugfs_create_file(u3_phy_files[i], 0644, inst->phy->debugfs, 632 + inst, &u3_phy_fops); 633 + } 634 + 635 + static int phy_type_show(struct seq_file *sf, void *unused) 636 + { 637 + struct mtk_phy_instance *inst = sf->private; 638 + const char *type; 639 + 640 + switch (inst->type) { 641 + case PHY_TYPE_USB2: 642 + type = "USB2"; 643 + break; 644 + case PHY_TYPE_USB3: 645 + type = "USB3"; 646 + break; 647 + case PHY_TYPE_PCIE: 648 + type = "PCIe"; 649 + break; 650 + case PHY_TYPE_SGMII: 651 + type = "SGMII"; 652 + break; 653 + case PHY_TYPE_SATA: 654 + type = "SATA"; 655 + break; 656 + default: 657 + type = ""; 658 + } 659 + 660 + seq_printf(sf, "%s\n", type); 661 + 662 + return 0; 663 + } 664 + DEFINE_SHOW_ATTRIBUTE(phy_type); 665 + 666 + /* these files will be removed when phy is released by phy core */ 667 + static void phy_debugfs_init(struct mtk_phy_instance *inst) 668 + { 669 + debugfs_create_file("type", 0444, inst->phy->debugfs, inst, &phy_type_fops); 670 + 671 + switch (inst->type) { 672 + case PHY_TYPE_USB2: 673 + u2_phy_dbgfs_files_create(inst); 674 + break; 675 + case PHY_TYPE_USB3: 676 + case PHY_TYPE_PCIE: 677 + u3_phy_dbgfs_files_create(inst); 678 + break; 679 + default: 680 + break; 681 + } 682 + } 683 + 684 + #else 685 + 686 + static void phy_debugfs_init(struct mtk_phy_instance *inst) 687 + {} 688 + 689 + #endif 341 690 342 691 static void hs_slew_rate_calibrate(struct mtk_tphy *tphy, 343 692 struct mtk_phy_instance *instance) ··· 1495 1140 1496 1141 phy_parse_property(tphy, instance); 1497 1142 phy_type_set(instance); 1143 + phy_debugfs_init(instance); 1498 1144 1499 1145 return instance->phy; 1500 1146 }
+264 -162
drivers/phy/microchip/sparx5_serdes.c
··· 25 25 26 26 #define SPX5_SERDES_10G_START 13 27 27 #define SPX5_SERDES_25G_START 25 28 + #define SPX5_SERDES_6G10G_CNT SPX5_SERDES_25G_START 29 + 30 + /* Optimal power settings from GUC */ 31 + #define SPX5_SERDES_QUIET_MODE_VAL 0x01ef4e0c 28 32 29 33 enum sparx5_10g28cmu_mode { 30 34 SPX5_SD10G28_CMU_MAIN = 0, 31 35 SPX5_SD10G28_CMU_AUX1 = 1, 32 36 SPX5_SD10G28_CMU_AUX2 = 3, 33 37 SPX5_SD10G28_CMU_NONE = 4, 38 + SPX5_SD10G28_CMU_MAX, 34 39 }; 35 40 36 41 enum sparx5_sd25g28_mode_preset_type { ··· 927 922 *params = init; 928 923 } 929 924 925 + static int sparx5_cmu_apply_cfg(struct sparx5_serdes_private *priv, 926 + u32 cmu_idx, 927 + void __iomem *cmu_tgt, 928 + void __iomem *cmu_cfg_tgt, 929 + u32 spd10g) 930 + { 931 + void __iomem **regs = priv->regs; 932 + struct device *dev = priv->dev; 933 + int value; 934 + 935 + cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); 936 + cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); 937 + 938 + if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || 939 + cmu_idx == 10 || cmu_idx == 13) { 940 + spd10g = 0; 941 + } 942 + 943 + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(1), 944 + SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, 945 + cmu_cfg_tgt, 946 + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); 947 + 948 + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), 949 + SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, 950 + cmu_cfg_tgt, 951 + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); 952 + 953 + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(1), 954 + SD_CMU_CFG_SD_CMU_CFG_CMU_RST, 955 + cmu_cfg_tgt, 956 + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); 957 + 958 + sdx5_inst_rmw(SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT_SET(0x1) | 959 + SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT_SET(0x1) | 960 + SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT_SET(0x1) | 961 + SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT_SET(0x1) | 962 + SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(0x0), 963 + SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT | 964 + SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT | 965 + SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT | 966 + SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT | 967 + SD_CMU_CMU_45_R_EN_RATECHG_CTRL, 968 + cmu_tgt, 969 + SD_CMU_CMU_45(cmu_idx)); 970 + 971 + sdx5_inst_rmw(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(0), 972 + SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0, 973 + cmu_tgt, 974 + SD_CMU_CMU_47(cmu_idx)); 975 + 976 + sdx5_inst_rmw(SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(0), 977 + SD_CMU_CMU_1B_CFG_RESERVE_7_0, 978 + cmu_tgt, 979 + SD_CMU_CMU_1B(cmu_idx)); 980 + 981 + sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_JC_BYP_SET(0x1), 982 + SD_CMU_CMU_0D_CFG_JC_BYP, 983 + cmu_tgt, 984 + SD_CMU_CMU_0D(cmu_idx)); 985 + 986 + sdx5_inst_rmw(SD_CMU_CMU_1F_CFG_VTUNE_SEL_SET(1), 987 + SD_CMU_CMU_1F_CFG_VTUNE_SEL, 988 + cmu_tgt, 989 + SD_CMU_CMU_1F(cmu_idx)); 990 + 991 + sdx5_inst_rmw(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_SET(3), 992 + SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0, 993 + cmu_tgt, 994 + SD_CMU_CMU_00(cmu_idx)); 995 + 996 + sdx5_inst_rmw(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_SET(3), 997 + SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, 998 + cmu_tgt, 999 + SD_CMU_CMU_05(cmu_idx)); 1000 + 1001 + sdx5_inst_rmw(SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(1), 1002 + SD_CMU_CMU_30_R_PLL_DLOL_EN, 1003 + cmu_tgt, 1004 + SD_CMU_CMU_30(cmu_idx)); 1005 + 1006 + sdx5_inst_rmw(SD_CMU_CMU_09_CFG_SW_10G_SET(spd10g), 1007 + SD_CMU_CMU_09_CFG_SW_10G, 1008 + cmu_tgt, 1009 + SD_CMU_CMU_09(cmu_idx)); 1010 + 1011 + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(0), 1012 + SD_CMU_CFG_SD_CMU_CFG_CMU_RST, 1013 + cmu_cfg_tgt, 1014 + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); 1015 + 1016 + msleep(20); 1017 + 1018 + sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(0), 1019 + SD_CMU_CMU_44_R_PLL_RSTN, 1020 + cmu_tgt, 1021 + SD_CMU_CMU_44(cmu_idx)); 1022 + 1023 + sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(1), 1024 + SD_CMU_CMU_44_R_PLL_RSTN, 1025 + cmu_tgt, 1026 + SD_CMU_CMU_44(cmu_idx)); 1027 + 1028 + msleep(20); 1029 + 1030 + value = readl(sdx5_addr(regs, SD_CMU_CMU_E0(cmu_idx))); 1031 + value = SD_CMU_CMU_E0_PLL_LOL_UDL_GET(value); 1032 + 1033 + if (value) { 1034 + dev_err(dev, "CMU PLL Loss of Lock: 0x%x\n", value); 1035 + return -EINVAL; 1036 + } 1037 + sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD_SET(0), 1038 + SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD, 1039 + cmu_tgt, 1040 + SD_CMU_CMU_0D(cmu_idx)); 1041 + return 0; 1042 + } 1043 + 1044 + static int sparx5_cmu_cfg(struct sparx5_serdes_private *priv, u32 cmu_idx) 1045 + { 1046 + void __iomem *cmu_tgt, *cmu_cfg_tgt; 1047 + u32 spd10g = 1; 1048 + 1049 + if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || 1050 + cmu_idx == 10 || cmu_idx == 13) { 1051 + spd10g = 0; 1052 + } 1053 + 1054 + cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); 1055 + cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); 1056 + 1057 + return sparx5_cmu_apply_cfg(priv, cmu_idx, cmu_tgt, cmu_cfg_tgt, spd10g); 1058 + } 1059 + 1060 + /* Map of 6G/10G serdes mode and index to CMU index. */ 1061 + static const int 1062 + sparx5_serdes_cmu_map[SPX5_SD10G28_CMU_MAX][SPX5_SERDES_6G10G_CNT] = { 1063 + [SPX5_SD10G28_CMU_MAIN] = { 2, 2, 2, 2, 2, 1064 + 2, 2, 2, 5, 5, 1065 + 5, 5, 5, 5, 5, 1066 + 5, 8, 11, 11, 11, 1067 + 11, 11, 11, 11, 11 }, 1068 + [SPX5_SD10G28_CMU_AUX1] = { 0, 0, 3, 3, 3, 1069 + 3, 3, 3, 3, 3, 1070 + 6, 6, 6, 6, 6, 1071 + 6, 6, 9, 9, 12, 1072 + 12, 12, 12, 12, 12 }, 1073 + [SPX5_SD10G28_CMU_AUX2] = { 1, 1, 1, 1, 4, 1074 + 4, 4, 4, 4, 4, 1075 + 4, 4, 7, 7, 7, 1076 + 7, 7, 10, 10, 10, 1077 + 10, 13, 13, 13, 13 }, 1078 + [SPX5_SD10G28_CMU_NONE] = { 1, 1, 1, 1, 4, 1079 + 4, 4, 4, 4, 4, 1080 + 4, 4, 7, 7, 7, 1081 + 7, 7, 10, 10, 10, 1082 + 10, 13, 13, 13, 13 }, 1083 + }; 1084 + 1085 + /* Get the index of the CMU which provides the clock for the specified serdes 1086 + * mode and index. 1087 + */ 1088 + static int sparx5_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index) 1089 + { 1090 + return sparx5_serdes_cmu_map[mode][sd_index]; 1091 + } 1092 + 1093 + static void sparx5_serdes_cmu_power_off(struct sparx5_serdes_private *priv) 1094 + { 1095 + void __iomem *cmu_inst, *cmu_cfg_inst; 1096 + int i; 1097 + 1098 + /* Power down each CMU */ 1099 + for (i = 0; i < SPX5_CMU_MAX; i++) { 1100 + cmu_inst = sdx5_inst_get(priv, TARGET_SD_CMU, i); 1101 + cmu_cfg_inst = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, i); 1102 + 1103 + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), 1104 + SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, cmu_cfg_inst, 1105 + SD_CMU_CFG_SD_CMU_CFG(0)); 1106 + 1107 + sdx5_inst_rmw(SD_CMU_CMU_05_CFG_REFCK_TERM_EN_SET(0), 1108 + SD_CMU_CMU_05_CFG_REFCK_TERM_EN, cmu_inst, 1109 + SD_CMU_CMU_05(0)); 1110 + 1111 + sdx5_inst_rmw(SD_CMU_CMU_09_CFG_EN_TX_CK_DN_SET(0), 1112 + SD_CMU_CMU_09_CFG_EN_TX_CK_DN, cmu_inst, 1113 + SD_CMU_CMU_09(0)); 1114 + 1115 + sdx5_inst_rmw(SD_CMU_CMU_06_CFG_VCO_PD_SET(1), 1116 + SD_CMU_CMU_06_CFG_VCO_PD, cmu_inst, 1117 + SD_CMU_CMU_06(0)); 1118 + 1119 + sdx5_inst_rmw(SD_CMU_CMU_09_CFG_EN_TX_CK_UP_SET(0), 1120 + SD_CMU_CMU_09_CFG_EN_TX_CK_UP, cmu_inst, 1121 + SD_CMU_CMU_09(0)); 1122 + 1123 + sdx5_inst_rmw(SD_CMU_CMU_08_CFG_CK_TREE_PD_SET(1), 1124 + SD_CMU_CMU_08_CFG_CK_TREE_PD, cmu_inst, 1125 + SD_CMU_CMU_08(0)); 1126 + 1127 + sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_REFCK_PD_SET(1) | 1128 + SD_CMU_CMU_0D_CFG_PD_DIV64_SET(1) | 1129 + SD_CMU_CMU_0D_CFG_PD_DIV66_SET(1), 1130 + SD_CMU_CMU_0D_CFG_REFCK_PD | 1131 + SD_CMU_CMU_0D_CFG_PD_DIV64 | 1132 + SD_CMU_CMU_0D_CFG_PD_DIV66, cmu_inst, 1133 + SD_CMU_CMU_0D(0)); 1134 + 1135 + sdx5_inst_rmw(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_SET(1), 1136 + SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, cmu_inst, 1137 + SD_CMU_CMU_06(0)); 1138 + } 1139 + } 1140 + 930 1141 static void sparx5_sd25g28_reset(void __iomem *regs[], 931 1142 struct sparx5_sd25g28_params *params, 932 1143 u32 sd_index) ··· 1643 1422 u32 lane_index = macro->sidx; 1644 1423 u32 sd_index = macro->stpidx; 1645 1424 void __iomem *sd_inst; 1646 - u32 value; 1425 + u32 value, cmu_idx; 1426 + int err; 1427 + 1428 + /* Do not configure serdes if CMU is not to be configured too */ 1429 + if (params->skip_cmu_cfg) 1430 + return 0; 1431 + 1432 + cmu_idx = sparx5_serdes_cmu_get(params->cmu_sel, lane_index); 1433 + err = sparx5_cmu_cfg(priv, cmu_idx); 1434 + if (err) 1435 + return err; 1647 1436 1648 1437 if (params->is_6g) 1649 1438 sd_inst = sdx5_inst_get(priv, TARGET_SD6G_LANE, sd_index); ··· 2115 1884 .rxinvert = 1, 2116 1885 .txswing = 240, 2117 1886 .reg_rst = reset, 1887 + .skip_cmu_cfg = reset, 2118 1888 }; 2119 1889 int err; 2120 1890 ··· 2131 1899 static int sparx5_serdes_power_save(struct sparx5_serdes_macro *macro, u32 pwdn) 2132 1900 { 2133 1901 struct sparx5_serdes_private *priv = macro->priv; 2134 - void __iomem *sd_inst; 1902 + void __iomem *sd_inst, *sd_lane_inst; 2135 1903 2136 1904 if (macro->serdestype == SPX5_SDT_6G) 2137 1905 sd_inst = sdx5_inst_get(priv, TARGET_SD6G_LANE, macro->stpidx); ··· 2141 1909 sd_inst = sdx5_inst_get(priv, TARGET_SD25G_LANE, macro->stpidx); 2142 1910 2143 1911 if (macro->serdestype == SPX5_SDT_25G) { 1912 + sd_lane_inst = sdx5_inst_get(priv, TARGET_SD_LANE_25G, 1913 + macro->stpidx); 1914 + /* Take serdes out of reset */ 1915 + sdx5_inst_rmw(SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST_SET(0), 1916 + SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST, sd_lane_inst, 1917 + SD_LANE_25G_SD_LANE_CFG(0)); 1918 + 1919 + /* Configure optimal settings for quiet mode */ 1920 + sdx5_inst_rmw(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_SET(SPX5_SERDES_QUIET_MODE_VAL), 1921 + SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, 1922 + sd_lane_inst, SD_LANE_25G_QUIET_MODE_6G(0)); 1923 + 2144 1924 sdx5_inst_rmw(SD25G_LANE_LANE_04_LN_CFG_PD_DRIVER_SET(pwdn), 2145 1925 SD25G_LANE_LANE_04_LN_CFG_PD_DRIVER, 2146 1926 sd_inst, 2147 1927 SD25G_LANE_LANE_04(0)); 2148 1928 } else { 2149 1929 /* 6G and 10G */ 1930 + sd_lane_inst = sdx5_inst_get(priv, TARGET_SD_LANE, macro->sidx); 1931 + 1932 + /* Take serdes out of reset */ 1933 + sdx5_inst_rmw(SD_LANE_SD_LANE_CFG_EXT_CFG_RST_SET(0), 1934 + SD_LANE_SD_LANE_CFG_EXT_CFG_RST, sd_lane_inst, 1935 + SD_LANE_SD_LANE_CFG(0)); 1936 + 1937 + /* Configure optimal settings for quiet mode */ 1938 + sdx5_inst_rmw(SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(SPX5_SERDES_QUIET_MODE_VAL), 1939 + SD_LANE_QUIET_MODE_6G_QUIET_MODE, sd_lane_inst, 1940 + SD_LANE_QUIET_MODE_6G(0)); 1941 + 2150 1942 sdx5_inst_rmw(SD10G_LANE_LANE_06_CFG_PD_DRIVER_SET(pwdn), 2151 1943 SD10G_LANE_LANE_06_CFG_PD_DRIVER, 2152 1944 sd_inst, ··· 2193 1937 SD_LANE_MISC(macro->sidx)); 2194 1938 } 2195 1939 return 0; 2196 - } 2197 - 2198 - static int sparx5_cmu_apply_cfg(struct sparx5_serdes_private *priv, 2199 - u32 cmu_idx, 2200 - void __iomem *cmu_tgt, 2201 - void __iomem *cmu_cfg_tgt, 2202 - u32 spd10g) 2203 - { 2204 - void __iomem **regs = priv->regs; 2205 - struct device *dev = priv->dev; 2206 - int value; 2207 - 2208 - cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); 2209 - cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); 2210 - 2211 - if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || 2212 - cmu_idx == 10 || cmu_idx == 13) { 2213 - spd10g = 0; 2214 - } 2215 - 2216 - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(1), 2217 - SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, 2218 - cmu_cfg_tgt, 2219 - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); 2220 - 2221 - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), 2222 - SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, 2223 - cmu_cfg_tgt, 2224 - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); 2225 - 2226 - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(1), 2227 - SD_CMU_CFG_SD_CMU_CFG_CMU_RST, 2228 - cmu_cfg_tgt, 2229 - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); 2230 - 2231 - sdx5_inst_rmw(SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT_SET(0x1) | 2232 - SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT_SET(0x1) | 2233 - SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT_SET(0x1) | 2234 - SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT_SET(0x1) | 2235 - SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(0x0), 2236 - SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT | 2237 - SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT | 2238 - SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT | 2239 - SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT | 2240 - SD_CMU_CMU_45_R_EN_RATECHG_CTRL, 2241 - cmu_tgt, 2242 - SD_CMU_CMU_45(cmu_idx)); 2243 - 2244 - sdx5_inst_rmw(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(0), 2245 - SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0, 2246 - cmu_tgt, 2247 - SD_CMU_CMU_47(cmu_idx)); 2248 - 2249 - sdx5_inst_rmw(SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(0), 2250 - SD_CMU_CMU_1B_CFG_RESERVE_7_0, 2251 - cmu_tgt, 2252 - SD_CMU_CMU_1B(cmu_idx)); 2253 - 2254 - sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_JC_BYP_SET(0x1), 2255 - SD_CMU_CMU_0D_CFG_JC_BYP, 2256 - cmu_tgt, 2257 - SD_CMU_CMU_0D(cmu_idx)); 2258 - 2259 - sdx5_inst_rmw(SD_CMU_CMU_1F_CFG_VTUNE_SEL_SET(1), 2260 - SD_CMU_CMU_1F_CFG_VTUNE_SEL, 2261 - cmu_tgt, 2262 - SD_CMU_CMU_1F(cmu_idx)); 2263 - 2264 - sdx5_inst_rmw(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_SET(3), 2265 - SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0, 2266 - cmu_tgt, 2267 - SD_CMU_CMU_00(cmu_idx)); 2268 - 2269 - sdx5_inst_rmw(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_SET(3), 2270 - SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, 2271 - cmu_tgt, 2272 - SD_CMU_CMU_05(cmu_idx)); 2273 - 2274 - sdx5_inst_rmw(SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(1), 2275 - SD_CMU_CMU_30_R_PLL_DLOL_EN, 2276 - cmu_tgt, 2277 - SD_CMU_CMU_30(cmu_idx)); 2278 - 2279 - sdx5_inst_rmw(SD_CMU_CMU_09_CFG_SW_10G_SET(spd10g), 2280 - SD_CMU_CMU_09_CFG_SW_10G, 2281 - cmu_tgt, 2282 - SD_CMU_CMU_09(cmu_idx)); 2283 - 2284 - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(0), 2285 - SD_CMU_CFG_SD_CMU_CFG_CMU_RST, 2286 - cmu_cfg_tgt, 2287 - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); 2288 - 2289 - msleep(20); 2290 - 2291 - sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(0), 2292 - SD_CMU_CMU_44_R_PLL_RSTN, 2293 - cmu_tgt, 2294 - SD_CMU_CMU_44(cmu_idx)); 2295 - 2296 - sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(1), 2297 - SD_CMU_CMU_44_R_PLL_RSTN, 2298 - cmu_tgt, 2299 - SD_CMU_CMU_44(cmu_idx)); 2300 - 2301 - msleep(20); 2302 - 2303 - value = readl(sdx5_addr(regs, SD_CMU_CMU_E0(cmu_idx))); 2304 - value = SD_CMU_CMU_E0_PLL_LOL_UDL_GET(value); 2305 - 2306 - if (value) { 2307 - dev_err(dev, "CMU PLL Loss of Lock: 0x%x\n", value); 2308 - return -EINVAL; 2309 - } 2310 - sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD_SET(0), 2311 - SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD, 2312 - cmu_tgt, 2313 - SD_CMU_CMU_0D(cmu_idx)); 2314 - return 0; 2315 - } 2316 - 2317 - static int sparx5_cmu_cfg(struct sparx5_serdes_private *priv, u32 cmu_idx) 2318 - { 2319 - void __iomem *cmu_tgt, *cmu_cfg_tgt; 2320 - u32 spd10g = 1; 2321 - 2322 - if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || 2323 - cmu_idx == 10 || cmu_idx == 13) { 2324 - spd10g = 0; 2325 - } 2326 - 2327 - cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); 2328 - cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); 2329 - 2330 - return sparx5_cmu_apply_cfg(priv, cmu_idx, cmu_tgt, cmu_cfg_tgt, spd10g); 2331 - } 2332 - 2333 - static int sparx5_serdes_cmu_enable(struct sparx5_serdes_private *priv) 2334 - { 2335 - int idx, err = 0; 2336 - 2337 - if (!priv->cmu_enabled) { 2338 - for (idx = 0; idx < SPX5_CMU_MAX; idx++) { 2339 - err = sparx5_cmu_cfg(priv, idx); 2340 - if (err) { 2341 - dev_err(priv->dev, "CMU %u, error: %d\n", idx, err); 2342 - goto leave; 2343 - } 2344 - } 2345 - priv->cmu_enabled = true; 2346 - } 2347 - leave: 2348 - return err; 2349 1940 } 2350 1941 2351 1942 static int sparx5_serdes_get_serdesmode(phy_interface_t portmode, int speed) ··· 2222 2119 struct device *dev = macro->priv->dev; 2223 2120 int serdesmode; 2224 2121 int err; 2225 - 2226 - err = sparx5_serdes_cmu_enable(macro->priv); 2227 - if (err) 2228 - return err; 2229 2122 2230 2123 serdesmode = sparx5_serdes_get_serdesmode(macro->portmode, macro->speed); 2231 2124 if (serdesmode < 0) { ··· 2314 2215 struct sparx5_serdes_macro *macro = phy_get_drvdata(phy); 2315 2216 int err; 2316 2217 2317 - err = sparx5_serdes_cmu_enable(macro->priv); 2318 - if (err) 2319 - return err; 2320 2218 if (macro->serdestype == SPX5_SDT_25G) 2321 2219 err = sparx5_sd25g28_config(macro, true); 2322 2220 else ··· 2403 2307 } 2404 2308 2405 2309 phy_set_drvdata(*phy, macro); 2310 + 2311 + /* Power off serdes by default */ 2312 + sparx5_serdes_power_off(*phy); 2406 2313 2407 2314 return 0; 2408 2315 } ··· 2589 2490 if (err) 2590 2491 return err; 2591 2492 } 2493 + 2494 + /* Power down all CMUs by default */ 2495 + sparx5_serdes_cmu_power_off(priv); 2592 2496 2593 2497 provider = devm_of_phy_provider_register(priv->dev, sparx5_serdes_xlate); 2594 2498
-1
drivers/phy/microchip/sparx5_serdes.h
··· 30 30 struct device *dev; 31 31 void __iomem *regs[NUM_TARGETS]; 32 32 struct phy *phys[SPX5_SERDES_MAX]; 33 - bool cmu_enabled; 34 33 unsigned long coreclock; 35 34 }; 36 35
+106
drivers/phy/microchip/sparx5_serdes_regs.h
··· 2149 2149 #define SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_GET(x)\ 2150 2150 FIELD_GET(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, x) 2151 2151 2152 + /* SD10G_CMU_TARGET:CMU_GRP_1:CMU_06 */ 2153 + #define SD_CMU_CMU_06(t) \ 2154 + __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 4, 0, 1, 4) 2155 + 2156 + #define SD_CMU_CMU_06_CFG_DISLOS BIT(0) 2157 + #define SD_CMU_CMU_06_CFG_DISLOS_SET(x)\ 2158 + FIELD_PREP(SD_CMU_CMU_06_CFG_DISLOS, x) 2159 + #define SD_CMU_CMU_06_CFG_DISLOS_GET(x)\ 2160 + FIELD_GET(SD_CMU_CMU_06_CFG_DISLOS, x) 2161 + 2162 + #define SD_CMU_CMU_06_CFG_DISLOL BIT(1) 2163 + #define SD_CMU_CMU_06_CFG_DISLOL_SET(x)\ 2164 + FIELD_PREP(SD_CMU_CMU_06_CFG_DISLOL, x) 2165 + #define SD_CMU_CMU_06_CFG_DISLOL_GET(x)\ 2166 + FIELD_GET(SD_CMU_CMU_06_CFG_DISLOL, x) 2167 + 2168 + #define SD_CMU_CMU_06_CFG_DCLOL BIT(2) 2169 + #define SD_CMU_CMU_06_CFG_DCLOL_SET(x)\ 2170 + FIELD_PREP(SD_CMU_CMU_06_CFG_DCLOL, x) 2171 + #define SD_CMU_CMU_06_CFG_DCLOL_GET(x)\ 2172 + FIELD_GET(SD_CMU_CMU_06_CFG_DCLOL, x) 2173 + 2174 + #define SD_CMU_CMU_06_CFG_FORCE_RX_FILT BIT(3) 2175 + #define SD_CMU_CMU_06_CFG_FORCE_RX_FILT_SET(x)\ 2176 + FIELD_PREP(SD_CMU_CMU_06_CFG_FORCE_RX_FILT, x) 2177 + #define SD_CMU_CMU_06_CFG_FORCE_RX_FILT_GET(x)\ 2178 + FIELD_GET(SD_CMU_CMU_06_CFG_FORCE_RX_FILT, x) 2179 + 2180 + #define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD BIT(4) 2181 + #define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_SET(x)\ 2182 + FIELD_PREP(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, x) 2183 + #define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_GET(x)\ 2184 + FIELD_GET(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, x) 2185 + 2186 + #define SD_CMU_CMU_06_CFG_VCO_PD BIT(5) 2187 + #define SD_CMU_CMU_06_CFG_VCO_PD_SET(x)\ 2188 + FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_PD, x) 2189 + #define SD_CMU_CMU_06_CFG_VCO_PD_GET(x)\ 2190 + FIELD_GET(SD_CMU_CMU_06_CFG_VCO_PD, x) 2191 + 2192 + #define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN BIT(6) 2193 + #define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN_SET(x)\ 2194 + FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_CAL_RESETN, x) 2195 + #define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN_GET(x)\ 2196 + FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_RESETN, x) 2197 + 2198 + #define SD_CMU_CMU_06_CFG_VCO_CAL_BYP BIT(7) 2199 + #define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_SET(x)\ 2200 + FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x) 2201 + #define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_GET(x)\ 2202 + FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x) 2203 + 2204 + /* SD10G_CMU_TARGET:CMU_GRP_1:CMU_08 */ 2205 + #define SD_CMU_CMU_08(t) \ 2206 + __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 12, 0, 1, 4) 2207 + 2208 + #define SD_CMU_CMU_08_CFG_VFILT2PAD BIT(0) 2209 + #define SD_CMU_CMU_08_CFG_VFILT2PAD_SET(x)\ 2210 + FIELD_PREP(SD_CMU_CMU_08_CFG_VFILT2PAD, x) 2211 + #define SD_CMU_CMU_08_CFG_VFILT2PAD_GET(x)\ 2212 + FIELD_GET(SD_CMU_CMU_08_CFG_VFILT2PAD, x) 2213 + 2214 + #define SD_CMU_CMU_08_CFG_EN_DUMMY BIT(1) 2215 + #define SD_CMU_CMU_08_CFG_EN_DUMMY_SET(x)\ 2216 + FIELD_PREP(SD_CMU_CMU_08_CFG_EN_DUMMY, x) 2217 + #define SD_CMU_CMU_08_CFG_EN_DUMMY_GET(x)\ 2218 + FIELD_GET(SD_CMU_CMU_08_CFG_EN_DUMMY, x) 2219 + 2220 + #define SD_CMU_CMU_08_CFG_CK_TREE_PD BIT(2) 2221 + #define SD_CMU_CMU_08_CFG_CK_TREE_PD_SET(x)\ 2222 + FIELD_PREP(SD_CMU_CMU_08_CFG_CK_TREE_PD, x) 2223 + #define SD_CMU_CMU_08_CFG_CK_TREE_PD_GET(x)\ 2224 + FIELD_GET(SD_CMU_CMU_08_CFG_CK_TREE_PD, x) 2225 + 2226 + #define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN BIT(3) 2227 + #define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_SET(x)\ 2228 + FIELD_PREP(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN, x) 2229 + #define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_GET(x)\ 2230 + FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN, x) 2231 + 2232 + #define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN BIT(4) 2233 + #define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_SET(x)\ 2234 + FIELD_PREP(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x) 2235 + #define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_GET(x)\ 2236 + FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x) 2237 + 2152 2238 /* SD10G_CMU_TARGET:CMU_GRP_1:CMU_09 */ 2153 2239 #define SD_CMU_CMU_09(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 16, 0, 1, 4) 2154 2240 ··· 2529 2443 #define SD_LANE_SD_LANE_STAT_DBG_OBS_GET(x)\ 2530 2444 FIELD_GET(SD_LANE_SD_LANE_STAT_DBG_OBS, x) 2531 2445 2446 + /* SD_LANE_TARGET:SD_PWR_CFG:QUIET_MODE_6G */ 2447 + #define SD_LANE_QUIET_MODE_6G(t) \ 2448 + __REG(TARGET_SD_LANE, t, 25, 24, 0, 1, 8, 4, 0, 1, 4) 2449 + 2450 + #define SD_LANE_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0) 2451 + #define SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(x)\ 2452 + FIELD_PREP(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x) 2453 + #define SD_LANE_QUIET_MODE_6G_QUIET_MODE_GET(x)\ 2454 + FIELD_GET(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x) 2455 + 2532 2456 /* SD_LANE_TARGET:CFG_STAT_FX100:MISC */ 2533 2457 #define SD_LANE_MISC(t) __REG(TARGET_SD_LANE, t, 25, 56, 0, 1, 56, 0, 0, 1, 4) 2534 2458 ··· 2787 2691 FIELD_PREP(SD_LANE_25G_SD_LANE_STAT_DBG_OBS, x) 2788 2692 #define SD_LANE_25G_SD_LANE_STAT_DBG_OBS_GET(x)\ 2789 2693 FIELD_GET(SD_LANE_25G_SD_LANE_STAT_DBG_OBS, x) 2694 + 2695 + /* SD25G_CFG_TARGET:SD_PWR_CFG:QUIET_MODE_6G */ 2696 + #define SD_LANE_25G_QUIET_MODE_6G(t) \ 2697 + __REG(TARGET_SD_LANE_25G, t, 8, 28, 0, 1, 8, 4, 0, 1, 4) 2698 + 2699 + #define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0) 2700 + #define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_SET(x)\ 2701 + FIELD_PREP(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, x) 2702 + #define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_GET(x)\ 2703 + FIELD_GET(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, x) 2790 2704 2791 2705 #endif /* _SPARX5_SERDES_REGS_H_ */
+14
drivers/phy/phy-core.c
··· 11 11 #include <linux/export.h> 12 12 #include <linux/module.h> 13 13 #include <linux/err.h> 14 + #include <linux/debugfs.h> 14 15 #include <linux/device.h> 15 16 #include <linux/slab.h> 16 17 #include <linux/of.h> ··· 21 20 #include <linux/regulator/consumer.h> 22 21 23 22 static struct class *phy_class; 23 + static struct dentry *phy_debugfs_root; 24 24 static DEFINE_MUTEX(phy_provider_mutex); 25 25 static LIST_HEAD(phy_provider_list); 26 26 static LIST_HEAD(phys); ··· 998 996 pm_runtime_no_callbacks(&phy->dev); 999 997 } 1000 998 999 + phy->debugfs = debugfs_create_dir(dev_name(&phy->dev), phy_debugfs_root); 1000 + 1001 1001 return phy; 1002 1002 1003 1003 put_dev: ··· 1230 1226 1231 1227 phy = to_phy(dev); 1232 1228 dev_vdbg(dev, "releasing '%s'\n", dev_name(dev)); 1229 + debugfs_remove_recursive(phy->debugfs); 1233 1230 regulator_put(phy->pwr); 1234 1231 ida_simple_remove(&phy_ida, phy->id); 1235 1232 kfree(phy); ··· 1247 1242 1248 1243 phy_class->dev_release = phy_release; 1249 1244 1245 + phy_debugfs_root = debugfs_create_dir("phy", NULL); 1246 + 1250 1247 return 0; 1251 1248 } 1252 1249 device_initcall(phy_core_init); 1250 + 1251 + static void __exit phy_core_exit(void) 1252 + { 1253 + debugfs_remove_recursive(phy_debugfs_root); 1254 + class_destroy(phy_class); 1255 + } 1256 + module_exit(phy_core_exit);
+12
drivers/phy/qualcomm/Kconfig
··· 59 59 config PHY_QCOM_QMP_COMBO 60 60 tristate "Qualcomm QMP Combo PHY Driver" 61 61 default PHY_QCOM_QMP 62 + depends on TYPEC || TYPEC=n 63 + depends on DRM || DRM=n 62 64 select GENERIC_PHY 63 65 select MFD_SYSCON 66 + select DRM_PANEL_BRIDGE if DRM 64 67 help 65 68 Enable this to support the QMP Combo PHY transceiver that is used 66 69 with USB3 and DisplayPort controllers on Qualcomm chips. ··· 188 185 This option enables support for the Synopsis PHYs present inside the 189 186 Qualcomm USB3.0 DWC3 controller on ipq806x SoC. This driver supports 190 187 both HS and SS PHY controllers. 188 + 189 + config PHY_QCOM_SGMII_ETH 190 + tristate "Qualcomm DWMAC SGMII SerDes/PHY driver" 191 + depends on OF && (ARCH_QCOM || COMPILE_TEST) 192 + depends on HAS_IOMEM 193 + select GENERIC_PHY 194 + help 195 + Enable this to support the internal SerDes/SGMII PHY on various 196 + Qualcomm chipsets.
+2 -1
drivers/phy/qualcomm/Makefile
··· 20 20 obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o 21 21 obj-$(CONFIG_PHY_QCOM_USB_SS) += phy-qcom-usb-ss.o 22 22 obj-$(CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2)+= phy-qcom-snps-femto-v2.o 23 - obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o 23 + obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o 24 + obj-$(CONFIG_PHY_QCOM_SGMII_ETH) += phy-qcom-sgmii-eth.o
+210 -53
drivers/phy/qualcomm/phy-qcom-qmp-combo.c
··· 19 19 #include <linux/regulator/consumer.h> 20 20 #include <linux/reset.h> 21 21 #include <linux/slab.h> 22 + #include <linux/usb/typec.h> 23 + #include <linux/usb/typec_mux.h> 24 + 25 + #include <drm/drm_bridge.h> 22 26 23 27 #include <dt-bindings/phy/phy-qcom-qmp.h> 24 28 ··· 66 62 67 63 /* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ 68 64 #define CLAMP_EN BIT(0) /* enables i/o clamp_n */ 65 + 66 + /* QPHY_V3_DP_COM_TYPEC_CTRL register bits */ 67 + #define SW_PORTSELECT_VAL BIT(0) 68 + #define SW_PORTSELECT_MUX BIT(1) 69 69 70 70 #define PHY_INIT_COMPLETE_TIMEOUT 10000 71 71 ··· 1323 1315 1324 1316 struct phy *usb_phy; 1325 1317 enum phy_mode mode; 1318 + unsigned int usb_init_count; 1326 1319 1327 1320 struct phy *dp_phy; 1328 1321 unsigned int dp_aux_cfg; 1329 1322 struct phy_configure_opts_dp dp_opts; 1323 + unsigned int dp_init_count; 1330 1324 1331 1325 struct clk_fixed_rate pipe_clk_fixed; 1332 1326 struct clk_hw dp_link_hw; 1333 1327 struct clk_hw dp_pixel_hw; 1328 + 1329 + struct drm_bridge bridge; 1330 + 1331 + struct typec_switch_dev *sw; 1332 + enum typec_orientation orientation; 1334 1333 }; 1335 1334 1336 1335 static void qmp_v3_dp_aux_init(struct qmp_combo *qmp); ··· 1969 1954 1970 1955 static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp) 1971 1956 { 1957 + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); 1958 + const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; 1972 1959 u32 val; 1973 - bool reverse = false; 1974 1960 1975 1961 val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | 1976 1962 DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; 1977 1963 1978 - /* 1979 - * TODO: Assume orientation is CC1 for now and two lanes, need to 1980 - * use type-c connector to understand orientation and lanes. 1981 - * 1982 - * Otherwise val changes to be like below if this code understood 1983 - * the orientation of the type-c cable. 1984 - * 1985 - * if (lane_cnt == 4 || orientation == ORIENTATION_CC2) 1986 - * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; 1987 - * if (lane_cnt == 4 || orientation == ORIENTATION_CC1) 1988 - * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; 1989 - * if (orientation == ORIENTATION_CC2) 1990 - * writel(0x4c, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_MODE); 1991 - */ 1992 - val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; 1964 + if (dp_opts->lanes == 4 || reverse) 1965 + val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; 1966 + if (dp_opts->lanes == 4 || !reverse) 1967 + val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; 1968 + 1993 1969 writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); 1994 1970 1995 - writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE); 1971 + if (reverse) 1972 + writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE); 1973 + else 1974 + writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE); 1996 1975 1997 1976 return reverse; 1998 1977 } ··· 2151 2142 static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp, 2152 2143 unsigned int com_resetm_ctrl_reg, 2153 2144 unsigned int com_c_ready_status_reg, 2145 + unsigned int com_cmn_status_reg, 2154 2146 unsigned int dp_phy_status_reg) 2155 2147 { 2156 2148 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; ··· 2208 2198 10000)) 2209 2199 return -ETIMEDOUT; 2210 2200 2211 - if (readl_poll_timeout(qmp->dp_serdes + QSERDES_V4_COM_CMN_STATUS, 2201 + if (readl_poll_timeout(qmp->dp_serdes + com_cmn_status_reg, 2212 2202 status, 2213 2203 ((status & BIT(0)) > 0), 2214 2204 500, 2215 2205 10000)) 2216 2206 return -ETIMEDOUT; 2217 2207 2218 - if (readl_poll_timeout(qmp->dp_serdes + QSERDES_V4_COM_CMN_STATUS, 2208 + if (readl_poll_timeout(qmp->dp_serdes + com_cmn_status_reg, 2219 2209 status, 2220 2210 ((status & BIT(1)) > 0), 2221 2211 500, ··· 2243 2233 2244 2234 static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp) 2245 2235 { 2236 + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); 2246 2237 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; 2247 2238 u32 bias0_en, drvr0_en, bias1_en, drvr1_en; 2248 - bool reverse = false; 2249 2239 u32 status; 2250 2240 int ret; 2251 2241 2252 2242 ret = qmp_v456_configure_dp_phy(qmp, QSERDES_V4_COM_RESETSM_CNTRL, 2253 2243 QSERDES_V4_COM_C_READY_STATUS, 2244 + QSERDES_V4_COM_CMN_STATUS, 2254 2245 QSERDES_V4_DP_PHY_STATUS); 2255 2246 if (ret < 0) 2256 2247 return ret; ··· 2308 2297 2309 2298 static int qmp_v5_configure_dp_phy(struct qmp_combo *qmp) 2310 2299 { 2300 + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); 2311 2301 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; 2312 2302 u32 bias0_en, drvr0_en, bias1_en, drvr1_en; 2313 - bool reverse = false; 2314 2303 u32 status; 2315 2304 int ret; 2316 2305 2317 2306 ret = qmp_v456_configure_dp_phy(qmp, QSERDES_V4_COM_RESETSM_CNTRL, 2318 2307 QSERDES_V4_COM_C_READY_STATUS, 2308 + QSERDES_V4_COM_CMN_STATUS, 2319 2309 QSERDES_V4_DP_PHY_STATUS); 2320 2310 if (ret < 0) 2321 2311 return ret; ··· 2368 2356 2369 2357 static int qmp_v6_configure_dp_phy(struct qmp_combo *qmp) 2370 2358 { 2359 + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); 2371 2360 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; 2372 2361 u32 bias0_en, drvr0_en, bias1_en, drvr1_en; 2373 - bool reverse = false; 2374 2362 u32 status; 2375 2363 int ret; 2376 2364 2377 2365 ret = qmp_v456_configure_dp_phy(qmp, QSERDES_V6_COM_RESETSM_CNTRL, 2378 2366 QSERDES_V6_COM_C_READY_STATUS, 2367 + QSERDES_V6_COM_CMN_STATUS, 2379 2368 QSERDES_V6_DP_PHY_STATUS); 2380 2369 if (ret < 0) 2381 2370 return ret; ··· 2450 2437 struct qmp_combo *qmp = phy_get_drvdata(phy); 2451 2438 const struct qmp_phy_cfg *cfg = qmp->cfg; 2452 2439 2440 + mutex_lock(&qmp->phy_mutex); 2441 + 2453 2442 memcpy(&qmp->dp_opts, dp_opts, sizeof(*dp_opts)); 2454 2443 if (qmp->dp_opts.set_voltages) { 2455 2444 cfg->configure_dp_tx(qmp); 2456 2445 qmp->dp_opts.set_voltages = 0; 2457 2446 } 2447 + 2448 + mutex_unlock(&qmp->phy_mutex); 2458 2449 2459 2450 return 0; 2460 2451 } ··· 2467 2450 { 2468 2451 struct qmp_combo *qmp = phy_get_drvdata(phy); 2469 2452 const struct qmp_phy_cfg *cfg = qmp->cfg; 2453 + int ret = 0; 2454 + 2455 + mutex_lock(&qmp->phy_mutex); 2470 2456 2471 2457 if (cfg->calibrate_dp_phy) 2472 - return cfg->calibrate_dp_phy(qmp); 2458 + ret = cfg->calibrate_dp_phy(qmp); 2473 2459 2474 - return 0; 2460 + mutex_unlock(&qmp->phy_mutex); 2461 + 2462 + return ret; 2475 2463 } 2476 2464 2477 - static int qmp_combo_com_init(struct qmp_combo *qmp) 2465 + static int qmp_combo_com_init(struct qmp_combo *qmp, bool force) 2478 2466 { 2479 2467 const struct qmp_phy_cfg *cfg = qmp->cfg; 2480 2468 void __iomem *com = qmp->com; 2481 2469 int ret; 2470 + u32 val; 2482 2471 2483 - mutex_lock(&qmp->phy_mutex); 2484 - if (qmp->init_count++) { 2485 - mutex_unlock(&qmp->phy_mutex); 2472 + if (!force && qmp->init_count++) 2486 2473 return 0; 2487 - } 2488 2474 2489 2475 ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); 2490 2476 if (ret) { ··· 2518 2498 SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | 2519 2499 SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); 2520 2500 2521 - /* Default type-c orientation, i.e CC1 */ 2522 - qphy_setbits(com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); 2523 - 2524 - qphy_setbits(com, QPHY_V3_DP_COM_PHY_MODE_CTRL, USB3_MODE | DP_MODE); 2501 + /* Use software based port select and switch on typec orientation */ 2502 + val = SW_PORTSELECT_MUX; 2503 + if (qmp->orientation == TYPEC_ORIENTATION_REVERSE) 2504 + val |= SW_PORTSELECT_VAL; 2505 + writel(val, com + QPHY_V3_DP_COM_TYPEC_CTRL); 2506 + writel(USB3_MODE | DP_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL); 2525 2507 2526 2508 /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ 2527 2509 qphy_clrbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ··· 2536 2514 qphy_setbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], 2537 2515 SW_PWRDN); 2538 2516 2539 - mutex_unlock(&qmp->phy_mutex); 2540 - 2541 2517 return 0; 2542 2518 2543 2519 err_assert_reset: ··· 2544 2524 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); 2545 2525 err_decrement_count: 2546 2526 qmp->init_count--; 2547 - mutex_unlock(&qmp->phy_mutex); 2548 2527 2549 2528 return ret; 2550 2529 } 2551 2530 2552 - static int qmp_combo_com_exit(struct qmp_combo *qmp) 2531 + static int qmp_combo_com_exit(struct qmp_combo *qmp, bool force) 2553 2532 { 2554 2533 const struct qmp_phy_cfg *cfg = qmp->cfg; 2555 2534 2556 - mutex_lock(&qmp->phy_mutex); 2557 - if (--qmp->init_count) { 2558 - mutex_unlock(&qmp->phy_mutex); 2535 + if (!force && --qmp->init_count) 2559 2536 return 0; 2560 - } 2561 2537 2562 2538 reset_control_bulk_assert(cfg->num_resets, qmp->resets); 2563 2539 2564 2540 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); 2565 2541 2566 2542 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); 2567 - 2568 - mutex_unlock(&qmp->phy_mutex); 2569 2543 2570 2544 return 0; 2571 2545 } ··· 2570 2556 const struct qmp_phy_cfg *cfg = qmp->cfg; 2571 2557 int ret; 2572 2558 2573 - ret = qmp_combo_com_init(qmp); 2559 + mutex_lock(&qmp->phy_mutex); 2560 + 2561 + ret = qmp_combo_com_init(qmp, false); 2574 2562 if (ret) 2575 - return ret; 2563 + goto out_unlock; 2576 2564 2577 2565 cfg->dp_aux_init(qmp); 2578 2566 2579 - return 0; 2567 + qmp->dp_init_count++; 2568 + 2569 + out_unlock: 2570 + mutex_unlock(&qmp->phy_mutex); 2571 + return ret; 2580 2572 } 2581 2573 2582 2574 static int qmp_combo_dp_exit(struct phy *phy) 2583 2575 { 2584 2576 struct qmp_combo *qmp = phy_get_drvdata(phy); 2585 2577 2586 - qmp_combo_com_exit(qmp); 2578 + mutex_lock(&qmp->phy_mutex); 2579 + 2580 + qmp_combo_com_exit(qmp, false); 2581 + 2582 + qmp->dp_init_count--; 2583 + 2584 + mutex_unlock(&qmp->phy_mutex); 2587 2585 2588 2586 return 0; 2589 2587 } ··· 2606 2580 const struct qmp_phy_cfg *cfg = qmp->cfg; 2607 2581 void __iomem *tx = qmp->dp_tx; 2608 2582 void __iomem *tx2 = qmp->dp_tx2; 2583 + 2584 + mutex_lock(&qmp->phy_mutex); 2609 2585 2610 2586 qmp_combo_dp_serdes_init(qmp); 2611 2587 ··· 2620 2592 /* Configure link rate, swing, etc. */ 2621 2593 cfg->configure_dp_phy(qmp); 2622 2594 2595 + mutex_unlock(&qmp->phy_mutex); 2596 + 2623 2597 return 0; 2624 2598 } 2625 2599 ··· 2629 2599 { 2630 2600 struct qmp_combo *qmp = phy_get_drvdata(phy); 2631 2601 2602 + mutex_lock(&qmp->phy_mutex); 2603 + 2632 2604 /* Assert DP PHY power down */ 2633 2605 writel(DP_PHY_PD_CTL_PSR_PWRDN, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); 2606 + 2607 + mutex_unlock(&qmp->phy_mutex); 2634 2608 2635 2609 return 0; 2636 2610 } ··· 2721 2687 struct qmp_combo *qmp = phy_get_drvdata(phy); 2722 2688 int ret; 2723 2689 2724 - ret = qmp_combo_com_init(qmp); 2690 + mutex_lock(&qmp->phy_mutex); 2691 + ret = qmp_combo_com_init(qmp, false); 2725 2692 if (ret) 2726 - return ret; 2693 + goto out_unlock; 2727 2694 2728 2695 ret = qmp_combo_usb_power_on(phy); 2729 - if (ret) 2730 - qmp_combo_com_exit(qmp); 2696 + if (ret) { 2697 + qmp_combo_com_exit(qmp, false); 2698 + goto out_unlock; 2699 + } 2731 2700 2701 + qmp->usb_init_count++; 2702 + 2703 + out_unlock: 2704 + mutex_unlock(&qmp->phy_mutex); 2732 2705 return ret; 2733 2706 } 2734 2707 ··· 2744 2703 struct qmp_combo *qmp = phy_get_drvdata(phy); 2745 2704 int ret; 2746 2705 2706 + mutex_lock(&qmp->phy_mutex); 2747 2707 ret = qmp_combo_usb_power_off(phy); 2748 2708 if (ret) 2749 - return ret; 2709 + goto out_unlock; 2750 2710 2751 - return qmp_combo_com_exit(qmp); 2711 + ret = qmp_combo_com_exit(qmp, false); 2712 + if (ret) 2713 + goto out_unlock; 2714 + 2715 + qmp->usb_init_count--; 2716 + 2717 + out_unlock: 2718 + mutex_unlock(&qmp->phy_mutex); 2719 + return ret; 2752 2720 } 2753 2721 2754 2722 static int qmp_combo_usb_set_mode(struct phy *phy, enum phy_mode mode, int submode) ··· 3223 3173 return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); 3224 3174 } 3225 3175 3176 + #if IS_ENABLED(CONFIG_TYPEC) 3177 + static int qmp_combo_typec_switch_set(struct typec_switch_dev *sw, 3178 + enum typec_orientation orientation) 3179 + { 3180 + struct qmp_combo *qmp = typec_switch_get_drvdata(sw); 3181 + const struct qmp_phy_cfg *cfg = qmp->cfg; 3182 + 3183 + if (orientation == qmp->orientation || orientation == TYPEC_ORIENTATION_NONE) 3184 + return 0; 3185 + 3186 + mutex_lock(&qmp->phy_mutex); 3187 + qmp->orientation = orientation; 3188 + 3189 + if (qmp->init_count) { 3190 + if (qmp->usb_init_count) 3191 + qmp_combo_usb_power_off(qmp->usb_phy); 3192 + qmp_combo_com_exit(qmp, true); 3193 + 3194 + qmp_combo_com_init(qmp, true); 3195 + if (qmp->usb_init_count) 3196 + qmp_combo_usb_power_on(qmp->usb_phy); 3197 + if (qmp->dp_init_count) 3198 + cfg->dp_aux_init(qmp); 3199 + } 3200 + mutex_unlock(&qmp->phy_mutex); 3201 + 3202 + return 0; 3203 + } 3204 + 3205 + static void qmp_combo_typec_unregister(void *data) 3206 + { 3207 + struct qmp_combo *qmp = data; 3208 + 3209 + typec_switch_unregister(qmp->sw); 3210 + } 3211 + 3212 + static int qmp_combo_typec_switch_register(struct qmp_combo *qmp) 3213 + { 3214 + struct typec_switch_desc sw_desc = {}; 3215 + struct device *dev = qmp->dev; 3216 + 3217 + sw_desc.drvdata = qmp; 3218 + sw_desc.fwnode = dev->fwnode; 3219 + sw_desc.set = qmp_combo_typec_switch_set; 3220 + qmp->sw = typec_switch_register(dev, &sw_desc); 3221 + if (IS_ERR(qmp->sw)) { 3222 + dev_err(dev, "Unable to register typec switch: %pe\n", qmp->sw); 3223 + return PTR_ERR(qmp->sw); 3224 + } 3225 + 3226 + return devm_add_action_or_reset(dev, qmp_combo_typec_unregister, qmp); 3227 + } 3228 + #else 3229 + static int qmp_combo_typec_switch_register(struct qmp_combo *qmp) 3230 + { 3231 + return 0; 3232 + } 3233 + #endif 3234 + 3235 + #if IS_ENABLED(CONFIG_DRM) 3236 + static int qmp_combo_bridge_attach(struct drm_bridge *bridge, 3237 + enum drm_bridge_attach_flags flags) 3238 + { 3239 + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); 3240 + struct drm_bridge *next_bridge; 3241 + 3242 + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) 3243 + return -EINVAL; 3244 + 3245 + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); 3246 + if (IS_ERR(next_bridge)) { 3247 + dev_err(qmp->dev, "failed to acquire drm_bridge: %pe\n", next_bridge); 3248 + return PTR_ERR(next_bridge); 3249 + } 3250 + 3251 + return drm_bridge_attach(bridge->encoder, next_bridge, bridge, 3252 + DRM_BRIDGE_ATTACH_NO_CONNECTOR); 3253 + } 3254 + 3255 + static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { 3256 + .attach = qmp_combo_bridge_attach, 3257 + }; 3258 + 3259 + static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) 3260 + { 3261 + qmp->bridge.funcs = &qmp_combo_bridge_funcs; 3262 + qmp->bridge.of_node = qmp->dev->of_node; 3263 + 3264 + return devm_drm_bridge_add(qmp->dev, &qmp->bridge); 3265 + } 3266 + #else 3267 + static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) 3268 + { 3269 + return 0; 3270 + } 3271 + #endif 3272 + 3226 3273 static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np) 3227 3274 { 3228 3275 struct device *dev = qmp->dev; ··· 3500 3353 3501 3354 qmp->dev = dev; 3502 3355 3356 + qmp->orientation = TYPEC_ORIENTATION_NORMAL; 3357 + 3503 3358 qmp->cfg = of_device_get_match_data(dev); 3504 3359 if (!qmp->cfg) 3505 3360 return -EINVAL; ··· 3517 3368 return ret; 3518 3369 3519 3370 ret = qmp_combo_vreg_init(qmp); 3371 + if (ret) 3372 + return ret; 3373 + 3374 + ret = qmp_combo_typec_switch_register(qmp); 3375 + if (ret) 3376 + return ret; 3377 + 3378 + ret = qmp_combo_dp_register_bridge(qmp); 3520 3379 if (ret) 3521 3380 return ret; 3522 3381
+182
drivers/phy/qualcomm/phy-qcom-qmp-usb.c
··· 139 139 [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V5_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR, 140 140 }; 141 141 142 + static const struct qmp_phy_init_tbl ipq9574_usb3_serdes_tbl[] = { 143 + QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), 144 + QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), 145 + QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), 146 + QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), 147 + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), 148 + QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), 149 + QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), 150 + QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), 151 + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), 152 + QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), 153 + /* PLL and Loop filter settings */ 154 + QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x68), 155 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0xab), 156 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0xaa), 157 + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x02), 158 + QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x09), 159 + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), 160 + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), 161 + QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0xa0), 162 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xaa), 163 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x29), 164 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), 165 + QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), 166 + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), 167 + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), 168 + QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), 169 + /* SSC settings */ 170 + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), 171 + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x7d), 172 + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), 173 + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), 174 + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), 175 + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x0a), 176 + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x05), 177 + }; 178 + 179 + static const struct qmp_phy_init_tbl ipq9574_usb3_tx_tbl[] = { 180 + QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), 181 + QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), 182 + QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), 183 + }; 184 + 185 + static const struct qmp_phy_init_tbl ipq9574_usb3_rx_tbl[] = { 186 + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06), 187 + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), 188 + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6c), 189 + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), 190 + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), 191 + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), 192 + QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), 193 + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), 194 + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), 195 + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0c), 196 + }; 197 + 198 + static const struct qmp_phy_init_tbl ipq9574_usb3_pcs_tbl[] = { 199 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), 200 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0e), 201 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), 202 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), 203 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), 204 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), 205 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), 206 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), 207 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), 208 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), 209 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), 210 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), 211 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), 212 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), 213 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), 214 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), 215 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), 216 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), 217 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), 218 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), 219 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), 220 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), 221 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), 222 + }; 223 + 142 224 static const struct qmp_phy_init_tbl ipq8074_usb3_serdes_tbl[] = { 143 225 QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), 144 226 QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ··· 1490 1408 QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), 1491 1409 }; 1492 1410 1411 + static const struct qmp_phy_init_tbl sa8775p_usb3_uniphy_pcs_tbl[] = { 1412 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG1, 0xc4), 1413 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG2, 0x89), 1414 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG3, 0x20), 1415 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG6, 0x13), 1416 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), 1417 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), 1418 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0xaa), 1419 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCS_TX_RX_CONFIG, 0x0c), 1420 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), 1421 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), 1422 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_POWER_STATE_CONFIG1, 0x6f), 1423 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_CDR_RESET_TIME, 0x0a), 1424 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0x88), 1425 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x13), 1426 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG1, 0x4b), 1427 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG5, 0x10), 1428 + QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), 1429 + }; 1430 + 1493 1431 struct qmp_usb_offsets { 1494 1432 u16 serdes; 1495 1433 u16 pcs; 1434 + u16 pcs_misc; 1496 1435 u16 pcs_usb; 1497 1436 u16 tx; 1498 1437 u16 rx; 1438 + /* for PHYs with >= 2 lanes */ 1439 + u16 tx2; 1440 + u16 rx2; 1499 1441 }; 1500 1442 1501 1443 /* struct qmp_phy_cfg - per-PHY initialization config */ ··· 1664 1558 "vdda-phy", "vdda-pll", 1665 1559 }; 1666 1560 1561 + static const struct qmp_usb_offsets qmp_usb_offsets_ipq9574 = { 1562 + .serdes = 0, 1563 + .pcs = 0x800, 1564 + .pcs_usb = 0x800, 1565 + .tx = 0x200, 1566 + .rx = 0x400, 1567 + }; 1568 + 1569 + static const struct qmp_usb_offsets qmp_usb_offsets_v3 = { 1570 + .serdes = 0, 1571 + .pcs = 0xc00, 1572 + .pcs_misc = 0xa00, 1573 + .tx = 0x200, 1574 + .rx = 0x400, 1575 + .tx2 = 0x600, 1576 + .rx2 = 0x800, 1577 + }; 1578 + 1667 1579 static const struct qmp_usb_offsets qmp_usb_offsets_v5 = { 1668 1580 .serdes = 0, 1669 1581 .pcs = 0x0200, ··· 1705 1581 .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), 1706 1582 .reset_list = msm8996_usb3phy_reset_l, 1707 1583 .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), 1584 + .vreg_list = qmp_phy_vreg_l, 1585 + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 1586 + .regs = qmp_v3_usb3phy_regs_layout, 1587 + }; 1588 + 1589 + static const struct qmp_phy_cfg ipq9574_usb3phy_cfg = { 1590 + .lanes = 1, 1591 + 1592 + .offsets = &qmp_usb_offsets_ipq9574, 1593 + 1594 + .serdes_tbl = ipq9574_usb3_serdes_tbl, 1595 + .serdes_tbl_num = ARRAY_SIZE(ipq9574_usb3_serdes_tbl), 1596 + .tx_tbl = ipq9574_usb3_tx_tbl, 1597 + .tx_tbl_num = ARRAY_SIZE(ipq9574_usb3_tx_tbl), 1598 + .rx_tbl = ipq9574_usb3_rx_tbl, 1599 + .rx_tbl_num = ARRAY_SIZE(ipq9574_usb3_rx_tbl), 1600 + .pcs_tbl = ipq9574_usb3_pcs_tbl, 1601 + .pcs_tbl_num = ARRAY_SIZE(ipq9574_usb3_pcs_tbl), 1602 + .clk_list = msm8996_phy_clk_l, 1603 + .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), 1604 + .reset_list = qcm2290_usb3phy_reset_l, 1605 + .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), 1708 1606 .vreg_list = qmp_phy_vreg_l, 1709 1607 .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 1710 1608 .regs = qmp_v3_usb3phy_regs_layout, ··· 1773 1627 1774 1628 .has_pwrdn_delay = true, 1775 1629 .has_phy_dp_com_ctrl = true, 1630 + }; 1631 + 1632 + static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = { 1633 + .lanes = 1, 1634 + 1635 + .offsets = &qmp_usb_offsets_v5, 1636 + 1637 + .serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl, 1638 + .serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_serdes_tbl), 1639 + .tx_tbl = sc8280xp_usb3_uniphy_tx_tbl, 1640 + .tx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_tx_tbl), 1641 + .rx_tbl = sc8280xp_usb3_uniphy_rx_tbl, 1642 + .rx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_rx_tbl), 1643 + .pcs_tbl = sa8775p_usb3_uniphy_pcs_tbl, 1644 + .pcs_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_tbl), 1645 + .clk_list = qmp_v4_phy_clk_l, 1646 + .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), 1647 + .reset_list = qcm2290_usb3phy_reset_l, 1648 + .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), 1649 + .vreg_list = qmp_phy_vreg_l, 1650 + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 1651 + .regs = qmp_v5_usb3phy_regs_layout, 1776 1652 }; 1777 1653 1778 1654 static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { ··· 2089 1921 2090 1922 static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { 2091 1923 .lanes = 2, 1924 + 1925 + .offsets = &qmp_usb_offsets_v3, 2092 1926 2093 1927 .serdes_tbl = qcm2290_usb3_serdes_tbl, 2094 1928 .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), ··· 2663 2493 2664 2494 qmp->serdes = base + offs->serdes; 2665 2495 qmp->pcs = base + offs->pcs; 2496 + qmp->pcs_misc = base + offs->pcs_misc; 2666 2497 qmp->pcs_usb = base + offs->pcs_usb; 2667 2498 qmp->tx = base + offs->tx; 2668 2499 qmp->rx = base + offs->rx; 2500 + 2501 + if (cfg->lanes >= 2) { 2502 + qmp->tx2 = base + offs->tx2; 2503 + qmp->rx2 = base + offs->rx2; 2504 + } 2669 2505 2670 2506 qmp->pipe_clk = devm_clk_get(dev, "pipe"); 2671 2507 if (IS_ERR(qmp->pipe_clk)) { ··· 2765 2589 .compatible = "qcom,ipq8074-qmp-usb3-phy", 2766 2590 .data = &ipq8074_usb3phy_cfg, 2767 2591 }, { 2592 + .compatible = "qcom,ipq9574-qmp-usb3-phy", 2593 + .data = &ipq9574_usb3phy_cfg, 2594 + }, { 2768 2595 .compatible = "qcom,msm8996-qmp-usb3-phy", 2769 2596 .data = &msm8996_usb3phy_cfg, 2770 2597 }, { ··· 2776 2597 }, { 2777 2598 .compatible = "qcom,qcm2290-qmp-usb3-phy", 2778 2599 .data = &qcm2290_usb3phy_cfg, 2600 + }, { 2601 + .compatible = "qcom,sa8775p-qmp-usb3-uni-phy", 2602 + .data = &sa8775p_usb3_uniphy_cfg, 2779 2603 }, { 2780 2604 .compatible = "qcom,sc7180-qmp-usb3-phy", 2781 2605 .data = &sc7180_usb3phy_cfg,
+3
drivers/phy/qualcomm/phy-qcom-qusb2.c
··· 912 912 .compatible = "qcom,ipq8074-qusb2-phy", 913 913 .data = &msm8996_phy_cfg, 914 914 }, { 915 + .compatible = "qcom,ipq9574-qusb2-phy", 916 + .data = &ipq6018_phy_cfg, 917 + }, { 915 918 .compatible = "qcom,msm8953-qusb2-phy", 916 919 .data = &msm8996_phy_cfg, 917 920 }, {
+451
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2023, Linaro Limited 4 + */ 5 + 6 + #include <linux/clk.h> 7 + #include <linux/ethtool.h> 8 + #include <linux/module.h> 9 + #include <linux/of.h> 10 + #include <linux/phy/phy.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/regmap.h> 13 + 14 + #define QSERDES_QMP_PLL 0x0 15 + #define QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0 (QSERDES_QMP_PLL + 0x1ac) 16 + #define QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0 (QSERDES_QMP_PLL + 0x1b0) 17 + #define QSERDES_COM_BIN_VCOCAL_HSCLK_SEL (QSERDES_QMP_PLL + 0x1bc) 18 + #define QSERDES_COM_CORE_CLK_EN (QSERDES_QMP_PLL + 0x174) 19 + #define QSERDES_COM_CORECLK_DIV_MODE0 (QSERDES_QMP_PLL + 0x168) 20 + #define QSERDES_COM_CP_CTRL_MODE0 (QSERDES_QMP_PLL + 0x74) 21 + #define QSERDES_COM_DEC_START_MODE0 (QSERDES_QMP_PLL + 0xbc) 22 + #define QSERDES_COM_DIV_FRAC_START1_MODE0 (QSERDES_QMP_PLL + 0xcc) 23 + #define QSERDES_COM_DIV_FRAC_START2_MODE0 (QSERDES_QMP_PLL + 0xd0) 24 + #define QSERDES_COM_DIV_FRAC_START3_MODE0 (QSERDES_QMP_PLL + 0xd4) 25 + #define QSERDES_COM_HSCLK_HS_SWITCH_SEL (QSERDES_QMP_PLL + 0x15c) 26 + #define QSERDES_COM_HSCLK_SEL (QSERDES_QMP_PLL + 0x158) 27 + #define QSERDES_COM_LOCK_CMP1_MODE0 (QSERDES_QMP_PLL + 0xac) 28 + #define QSERDES_COM_LOCK_CMP2_MODE0 (QSERDES_QMP_PLL + 0xb0) 29 + #define QSERDES_COM_PLL_CCTRL_MODE0 (QSERDES_QMP_PLL + 0x84) 30 + #define QSERDES_COM_PLL_IVCO (QSERDES_QMP_PLL + 0x58) 31 + #define QSERDES_COM_PLL_RCTRL_MODE0 (QSERDES_QMP_PLL + 0x7c) 32 + #define QSERDES_COM_SYSCLK_EN_SEL (QSERDES_QMP_PLL + 0x94) 33 + #define QSERDES_COM_VCO_TUNE1_MODE0 (QSERDES_QMP_PLL + 0x110) 34 + #define QSERDES_COM_VCO_TUNE2_MODE0 (QSERDES_QMP_PLL + 0x114) 35 + #define QSERDES_COM_VCO_TUNE_INITVAL2 (QSERDES_QMP_PLL + 0x124) 36 + #define QSERDES_COM_C_READY_STATUS (QSERDES_QMP_PLL + 0x178) 37 + #define QSERDES_COM_CMN_STATUS (QSERDES_QMP_PLL + 0x140) 38 + 39 + #define QSERDES_RX 0x600 40 + #define QSERDES_RX_UCDR_FO_GAIN (QSERDES_RX + 0x8) 41 + #define QSERDES_RX_UCDR_SO_GAIN (QSERDES_RX + 0x14) 42 + #define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN (QSERDES_RX + 0x30) 43 + #define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE (QSERDES_RX + 0x34) 44 + #define QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW (QSERDES_RX + 0x3c) 45 + #define QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH (QSERDES_RX + 0x40) 46 + #define QSERDES_RX_UCDR_PI_CONTROLS (QSERDES_RX + 0x44) 47 + #define QSERDES_RX_UCDR_PI_CTRL2 (QSERDES_RX + 0x48) 48 + #define QSERDES_RX_RX_TERM_BW (QSERDES_RX + 0x80) 49 + #define QSERDES_RX_VGA_CAL_CNTRL2 (QSERDES_RX + 0xd8) 50 + #define QSERDES_RX_GM_CAL (QSERDES_RX + 0xdc) 51 + #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1 (QSERDES_RX + 0xe8) 52 + #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 (QSERDES_RX + 0xec) 53 + #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 (QSERDES_RX + 0xf0) 54 + #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 (QSERDES_RX + 0xf4) 55 + #define QSERDES_RX_RX_IDAC_TSETTLE_LOW (QSERDES_RX + 0xf8) 56 + #define QSERDES_RX_RX_IDAC_TSETTLE_HIGH (QSERDES_RX + 0xfc) 57 + #define QSERDES_RX_RX_IDAC_MEASURE_TIME (QSERDES_RX + 0x100) 58 + #define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 (QSERDES_RX + 0x110) 59 + #define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 (QSERDES_RX + 0x114) 60 + #define QSERDES_RX_SIGDET_CNTRL (QSERDES_RX + 0x11c) 61 + #define QSERDES_RX_SIGDET_DEGLITCH_CNTRL (QSERDES_RX + 0x124) 62 + #define QSERDES_RX_RX_BAND (QSERDES_RX + 0x128) 63 + #define QSERDES_RX_RX_MODE_00_LOW (QSERDES_RX + 0x15c) 64 + #define QSERDES_RX_RX_MODE_00_HIGH (QSERDES_RX + 0x160) 65 + #define QSERDES_RX_RX_MODE_00_HIGH2 (QSERDES_RX + 0x164) 66 + #define QSERDES_RX_RX_MODE_00_HIGH3 (QSERDES_RX + 0x168) 67 + #define QSERDES_RX_RX_MODE_00_HIGH4 (QSERDES_RX + 0x16c) 68 + #define QSERDES_RX_RX_MODE_01_LOW (QSERDES_RX + 0x170) 69 + #define QSERDES_RX_RX_MODE_01_HIGH (QSERDES_RX + 0x174) 70 + #define QSERDES_RX_RX_MODE_01_HIGH2 (QSERDES_RX + 0x178) 71 + #define QSERDES_RX_RX_MODE_01_HIGH3 (QSERDES_RX + 0x17c) 72 + #define QSERDES_RX_RX_MODE_01_HIGH4 (QSERDES_RX + 0x180) 73 + #define QSERDES_RX_RX_MODE_10_LOW (QSERDES_RX + 0x184) 74 + #define QSERDES_RX_RX_MODE_10_HIGH (QSERDES_RX + 0x188) 75 + #define QSERDES_RX_RX_MODE_10_HIGH2 (QSERDES_RX + 0x18c) 76 + #define QSERDES_RX_RX_MODE_10_HIGH3 (QSERDES_RX + 0x190) 77 + #define QSERDES_RX_RX_MODE_10_HIGH4 (QSERDES_RX + 0x194) 78 + #define QSERDES_RX_DCC_CTRL1 (QSERDES_RX + 0x1a8) 79 + 80 + #define QSERDES_TX 0x400 81 + #define QSERDES_TX_TX_BAND (QSERDES_TX + 0x24) 82 + #define QSERDES_TX_SLEW_CNTL (QSERDES_TX + 0x28) 83 + #define QSERDES_TX_RES_CODE_LANE_OFFSET_TX (QSERDES_TX + 0x3c) 84 + #define QSERDES_TX_RES_CODE_LANE_OFFSET_RX (QSERDES_TX + 0x40) 85 + #define QSERDES_TX_LANE_MODE_1 (QSERDES_TX + 0x84) 86 + #define QSERDES_TX_LANE_MODE_3 (QSERDES_TX + 0x8c) 87 + #define QSERDES_TX_RCV_DETECT_LVL_2 (QSERDES_TX + 0xa4) 88 + #define QSERDES_TX_TRAN_DRVR_EMP_EN (QSERDES_TX + 0xc0) 89 + 90 + #define QSERDES_PCS 0xC00 91 + #define QSERDES_PCS_PHY_START (QSERDES_PCS + 0x0) 92 + #define QSERDES_PCS_POWER_DOWN_CONTROL (QSERDES_PCS + 0x4) 93 + #define QSERDES_PCS_SW_RESET (QSERDES_PCS + 0x8) 94 + #define QSERDES_PCS_LINE_RESET_TIME (QSERDES_PCS + 0xc) 95 + #define QSERDES_PCS_TX_LARGE_AMP_DRV_LVL (QSERDES_PCS + 0x20) 96 + #define QSERDES_PCS_TX_SMALL_AMP_DRV_LVL (QSERDES_PCS + 0x28) 97 + #define QSERDES_PCS_TX_MID_TERM_CTRL1 (QSERDES_PCS + 0xd8) 98 + #define QSERDES_PCS_TX_MID_TERM_CTRL2 (QSERDES_PCS + 0xdc) 99 + #define QSERDES_PCS_SGMII_MISC_CTRL8 (QSERDES_PCS + 0x118) 100 + #define QSERDES_PCS_PCS_READY_STATUS (QSERDES_PCS + 0x94) 101 + 102 + #define QSERDES_COM_C_READY BIT(0) 103 + #define QSERDES_PCS_READY BIT(0) 104 + #define QSERDES_PCS_SGMIIPHY_READY BIT(7) 105 + #define QSERDES_COM_C_PLL_LOCKED BIT(1) 106 + 107 + struct qcom_dwmac_sgmii_phy_data { 108 + struct regmap *regmap; 109 + struct clk *refclk; 110 + int speed; 111 + }; 112 + 113 + static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap) 114 + { 115 + regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01); 116 + regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01); 117 + 118 + regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F); 119 + regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06); 120 + regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); 121 + regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36); 122 + regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A); 123 + regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x0A); 124 + regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x1A); 125 + regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x82); 126 + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55); 127 + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55); 128 + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03); 129 + regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0x24); 130 + 131 + regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02); 132 + regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00); 133 + regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x04); 134 + regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00); 135 + regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x0A); 136 + regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00); 137 + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9); 138 + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E); 139 + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11); 140 + 141 + regmap_write(regmap, QSERDES_TX_TX_BAND, 0x05); 142 + regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A); 143 + regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09); 144 + regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x09); 145 + regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05); 146 + regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00); 147 + regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12); 148 + regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C); 149 + 150 + regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A); 151 + regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06); 152 + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A); 153 + regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F); 154 + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00); 155 + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01); 156 + regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81); 157 + regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80); 158 + regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x04); 159 + regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08); 160 + regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F); 161 + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04); 162 + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00); 163 + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A); 164 + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A); 165 + regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80); 166 + regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01); 167 + regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20); 168 + regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17); 169 + regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00); 170 + regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F); 171 + regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E); 172 + regmap_write(regmap, QSERDES_RX_RX_BAND, 0x05); 173 + regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0xE0); 174 + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8); 175 + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8); 176 + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x09); 177 + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB1); 178 + regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0); 179 + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8); 180 + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8); 181 + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09); 182 + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1); 183 + regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0); 184 + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8); 185 + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8); 186 + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B); 187 + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7); 188 + regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C); 189 + 190 + regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C); 191 + regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F); 192 + regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03); 193 + regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83); 194 + regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08); 195 + regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x0C); 196 + regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00); 197 + 198 + regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01); 199 + } 200 + 201 + static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap) 202 + { 203 + regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01); 204 + regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01); 205 + 206 + regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F); 207 + regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06); 208 + regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); 209 + regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36); 210 + regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A); 211 + regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x1A); 212 + regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x41); 213 + regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x7A); 214 + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); 215 + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x20); 216 + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x01); 217 + regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0xA1); 218 + 219 + regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02); 220 + regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00); 221 + regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x03); 222 + regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00); 223 + regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x05); 224 + regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00); 225 + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD); 226 + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C); 227 + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11); 228 + 229 + regmap_write(regmap, QSERDES_TX_TX_BAND, 0x04); 230 + regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A); 231 + regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09); 232 + regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x02); 233 + regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05); 234 + regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00); 235 + regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12); 236 + regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C); 237 + 238 + regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A); 239 + regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06); 240 + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A); 241 + regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F); 242 + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00); 243 + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01); 244 + regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81); 245 + regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80); 246 + regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x00); 247 + regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08); 248 + regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F); 249 + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04); 250 + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00); 251 + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A); 252 + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A); 253 + regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80); 254 + regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01); 255 + regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20); 256 + regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17); 257 + regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00); 258 + regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F); 259 + regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E); 260 + regmap_write(regmap, QSERDES_RX_RX_BAND, 0x18); 261 + regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0x18); 262 + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8); 263 + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8); 264 + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x0C); 265 + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB8); 266 + regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0); 267 + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8); 268 + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8); 269 + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09); 270 + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1); 271 + regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0); 272 + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8); 273 + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8); 274 + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B); 275 + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7); 276 + regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C); 277 + 278 + regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C); 279 + regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F); 280 + regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03); 281 + regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83); 282 + regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08); 283 + regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x8C); 284 + regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00); 285 + 286 + regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01); 287 + } 288 + 289 + static inline int 290 + qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg, 291 + unsigned int bit) 292 + { 293 + unsigned int val; 294 + 295 + return regmap_read_poll_timeout(regmap, reg, val, 296 + val & bit, 1500, 750000); 297 + } 298 + 299 + static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy) 300 + { 301 + struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); 302 + struct device *dev = phy->dev.parent; 303 + 304 + switch (data->speed) { 305 + case SPEED_10: 306 + case SPEED_100: 307 + case SPEED_1000: 308 + qcom_dwmac_sgmii_phy_init_1g(data->regmap); 309 + break; 310 + case SPEED_2500: 311 + qcom_dwmac_sgmii_phy_init_2p5g(data->regmap); 312 + break; 313 + } 314 + 315 + if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, 316 + QSERDES_COM_C_READY_STATUS, 317 + QSERDES_COM_C_READY)) { 318 + dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out"); 319 + return -ETIMEDOUT; 320 + } 321 + 322 + if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, 323 + QSERDES_PCS_PCS_READY_STATUS, 324 + QSERDES_PCS_READY)) { 325 + dev_err(dev, "PCS_READY timed-out"); 326 + return -ETIMEDOUT; 327 + } 328 + 329 + if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, 330 + QSERDES_PCS_PCS_READY_STATUS, 331 + QSERDES_PCS_SGMIIPHY_READY)) { 332 + dev_err(dev, "SGMIIPHY_READY timed-out"); 333 + return -ETIMEDOUT; 334 + } 335 + 336 + if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, 337 + QSERDES_COM_CMN_STATUS, 338 + QSERDES_COM_C_PLL_LOCKED)) { 339 + dev_err(dev, "PLL Lock Status timed-out"); 340 + return -ETIMEDOUT; 341 + } 342 + 343 + return 0; 344 + } 345 + 346 + static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy) 347 + { 348 + struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); 349 + 350 + return clk_prepare_enable(data->refclk); 351 + } 352 + 353 + static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy) 354 + { 355 + struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); 356 + 357 + regmap_write(data->regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08); 358 + regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x01); 359 + udelay(100); 360 + regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x00); 361 + regmap_write(data->regmap, QSERDES_PCS_PHY_START, 0x01); 362 + 363 + clk_disable_unprepare(data->refclk); 364 + 365 + return 0; 366 + } 367 + 368 + static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed) 369 + { 370 + struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); 371 + 372 + if (speed != data->speed) 373 + data->speed = speed; 374 + 375 + return qcom_dwmac_sgmii_phy_calibrate(phy); 376 + } 377 + 378 + static const struct phy_ops qcom_dwmac_sgmii_phy_ops = { 379 + .power_on = qcom_dwmac_sgmii_phy_power_on, 380 + .power_off = qcom_dwmac_sgmii_phy_power_off, 381 + .set_speed = qcom_dwmac_sgmii_phy_set_speed, 382 + .calibrate = qcom_dwmac_sgmii_phy_calibrate, 383 + .owner = THIS_MODULE, 384 + }; 385 + 386 + static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = { 387 + .reg_bits = 32, 388 + .val_bits = 32, 389 + .reg_stride = 4, 390 + .use_relaxed_mmio = true, 391 + .disable_locking = true, 392 + }; 393 + 394 + static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev) 395 + { 396 + struct qcom_dwmac_sgmii_phy_data *data; 397 + struct device *dev = &pdev->dev; 398 + struct phy_provider *provider; 399 + void __iomem *base; 400 + struct phy *phy; 401 + 402 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 403 + if (!data) 404 + return -ENOMEM; 405 + 406 + data->speed = SPEED_10; 407 + 408 + base = devm_platform_ioremap_resource(pdev, 0); 409 + if (IS_ERR(base)) 410 + return PTR_ERR(base); 411 + 412 + data->regmap = devm_regmap_init_mmio(dev, base, 413 + &qcom_dwmac_sgmii_phy_regmap_cfg); 414 + if (IS_ERR(data->regmap)) 415 + return PTR_ERR(data->regmap); 416 + 417 + phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops); 418 + if (IS_ERR(phy)) 419 + return PTR_ERR(phy); 420 + 421 + data->refclk = devm_clk_get(dev, "sgmi_ref"); 422 + if (IS_ERR(data->refclk)) 423 + return PTR_ERR(data->refclk); 424 + 425 + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 426 + if (IS_ERR(provider)) 427 + return PTR_ERR(provider); 428 + 429 + phy_set_drvdata(phy, data); 430 + 431 + return 0; 432 + } 433 + 434 + static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = { 435 + { .compatible = "qcom,sa8775p-dwmac-sgmii-phy" }, 436 + { }, 437 + }; 438 + MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match); 439 + 440 + static struct platform_driver qcom_dwmac_sgmii_phy_driver = { 441 + .probe = qcom_dwmac_sgmii_phy_probe, 442 + .driver = { 443 + .name = "qcom-dwmac-sgmii-phy", 444 + .of_match_table = qcom_dwmac_sgmii_phy_of_match, 445 + } 446 + }; 447 + 448 + module_platform_driver(qcom_dwmac_sgmii_phy_driver); 449 + 450 + MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver"); 451 + MODULE_LICENSE("GPL");
+1 -1
drivers/phy/samsung/Kconfig
··· 59 59 config PHY_EXYNOS4X12_USB2 60 60 bool 61 61 depends on PHY_SAMSUNG_USB2 62 - default SOC_EXYNOS3250 || SOC_EXYNOS4412 62 + default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412 63 63 64 64 config PHY_EXYNOS5250_USB2 65 65 bool
+4
drivers/phy/tegra/xusb.c
··· 568 568 usb_role_switch_unregister(port->usb_role_sw); 569 569 cancel_work_sync(&port->usb_phy_work); 570 570 usb_remove_phy(&port->usb_phy); 571 + port->usb_phy.dev->driver = NULL; 571 572 } 572 573 573 574 if (port->ops->remove) ··· 676 675 port->dev.driver = devm_kzalloc(&port->dev, 677 676 sizeof(struct device_driver), 678 677 GFP_KERNEL); 678 + if (!port->dev.driver) 679 + return -ENOMEM; 680 + 679 681 port->dev.driver->owner = THIS_MODULE; 680 682 681 683 port->usb_role_sw = usb_role_switch_register(&port->dev,
+32 -2
drivers/phy/ti/phy-gmii-sel.c
··· 23 23 #define AM33XX_GMII_SEL_MODE_RGMII 2 24 24 25 25 /* J72xx SoC specific definitions for the CONTROL port */ 26 + #define J72XX_GMII_SEL_MODE_SGMII 3 26 27 #define J72XX_GMII_SEL_MODE_QSGMII 4 28 + #define J72XX_GMII_SEL_MODE_USXGMII 5 27 29 #define J72XX_GMII_SEL_MODE_QSGMII_SUB 6 28 30 29 31 #define PHY_GMII_PORT(n) BIT((n) - 1) ··· 106 104 gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII; 107 105 else 108 106 gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII_SUB; 107 + break; 108 + 109 + case PHY_INTERFACE_MODE_SGMII: 110 + if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_SGMII))) 111 + goto unsupported; 112 + else 113 + gmii_sel_mode = J72XX_GMII_SEL_MODE_SGMII; 114 + break; 115 + 116 + case PHY_INTERFACE_MODE_USXGMII: 117 + if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_USXGMII))) 118 + goto unsupported; 119 + else 120 + gmii_sel_mode = J72XX_GMII_SEL_MODE_USXGMII; 109 121 break; 110 122 111 123 default: ··· 229 213 struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = { 230 214 .use_of_data = true, 231 215 .regfields = phy_gmii_sel_fields_am654, 232 - .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII), 216 + .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII), 233 217 .num_ports = 4, 234 218 .num_qsgmii_main_ports = 1, 235 219 }; ··· 238 222 struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = { 239 223 .use_of_data = true, 240 224 .regfields = phy_gmii_sel_fields_am654, 241 - .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII), 225 + .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII), 226 + .num_ports = 8, 227 + .num_qsgmii_main_ports = 2, 228 + }; 229 + 230 + static const 231 + struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j784s4 = { 232 + .use_of_data = true, 233 + .regfields = phy_gmii_sel_fields_am654, 234 + .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | 235 + BIT(PHY_INTERFACE_MODE_USXGMII), 242 236 .num_ports = 8, 243 237 .num_qsgmii_main_ports = 2, 244 238 }; ··· 281 255 { 282 256 .compatible = "ti,j721e-cpsw9g-phy-gmii-sel", 283 257 .data = &phy_gmii_sel_cpsw9g_soc_j721e, 258 + }, 259 + { 260 + .compatible = "ti,j784s4-cpsw9g-phy-gmii-sel", 261 + .data = &phy_gmii_sel_cpsw9g_soc_j784s4, 284 262 }, 285 263 {} 286 264 };
+2
include/linux/phy/phy.h
··· 148 148 * @power_count: used to protect when the PHY is used by multiple consumers 149 149 * @attrs: used to specify PHY specific attributes 150 150 * @pwr: power regulator associated with the phy 151 + * @debugfs: debugfs directory 151 152 */ 152 153 struct phy { 153 154 struct device dev; ··· 159 158 int power_count; 160 159 struct phy_attrs attrs; 161 160 struct regulator *pwr; 161 + struct dentry *debugfs; 162 162 }; 163 163 164 164 /**