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

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

Pull generic phy updates from Vinod Koul:
"New HW Support:
- Support for Embedded DisplayPort and DisplayPort submodes and
driver support on Qualcomm X1E80100 edp driver
- Qualcomm QMP UFS PHY for SM8475, QMP USB phy for QDU1000/QRU1000
and eusb2-repeater for SMB2360
- Samsung HDMI PHY for i.MX8MP, gs101 UFS phy
- Mediatek XFI T-PHY support for mt7988
- Rockchip usbdp combo phy driver

Updates:
- Qualcomm x4 lane EP support for sa8775p, v4 ad v6 support for
X1E80100, SM8650 tables for UFS Gear 4 & 5 and correct voltage
swing tables
- Freescale imx8m-pci pcie link-up updates
- Rockchip rx-common-refclk-mode support
- More platform remove callback returning void conversions"

* tag 'phy-for-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (43 commits)
dt-bindings: phy: qcom,usb-snps-femto-v2: use correct fallback for sc8180x
dt-bindings: phy: qcom,sc8280xp-qmp-ufs-phy: fix msm899[68] power-domains
dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: fix x1e80100-gen3x2 schema
phy: qcpm-qmp-usb: Add support for QDU1000/QRU1000
dt-bindings: phy: qcom,qmp-usb: Add QDU1000 USB3 PHY
dt-bindings: phy: qcom,usb-snps-femto-v2: Add bindings for QDU1000
phy: qcom-qmp-pcie: add x4 lane EP support for sa8775p
phy: samsung-ufs: ufs: exit on first reported error
phy: samsung-ufs: ufs: remove superfluous mfd/syscon.h header
phy: rockchip: fix CONFIG_TYPEC dependency
phy: rockchip: usbdp: fix uninitialized variable
phy: rockchip-snps-pcie3: add support for rockchip,rx-common-refclk-mode
dt-bindings: phy: rockchip,pcie3-phy: add rockchip,rx-common-refclk-mode
phy: rockchip: add usbdp combo phy driver
dt-bindings: phy: add rockchip usbdp combo phy document
phy: add driver for MediaTek XFI T-PHY
dt-bindings: phy: mediatek,mt7988-xfi-tphy: add new bindings
phy: freescale: fsl-samsung-hdmi: Convert to platform remove callback returning void
phy: qcom: qmp-ufs: update SM8650 tables for Gear 4 & 5
MAINTAINERS: Add phy-gs101-ufs file to Tensor GS101.
...

+4101 -131
+62
Documentation/devicetree/bindings/phy/fsl,imx8mp-hdmi-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/fsl,imx8mp-hdmi-phy.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Freescale i.MX8MP HDMI PHY 8 + 9 + maintainers: 10 + - Lucas Stach <l.stach@pengutronix.de> 11 + 12 + properties: 13 + compatible: 14 + enum: 15 + - fsl,imx8mp-hdmi-phy 16 + 17 + reg: 18 + maxItems: 1 19 + 20 + "#clock-cells": 21 + const: 0 22 + 23 + clocks: 24 + maxItems: 2 25 + 26 + clock-names: 27 + items: 28 + - const: apb 29 + - const: ref 30 + 31 + "#phy-cells": 32 + const: 0 33 + 34 + power-domains: 35 + maxItems: 1 36 + 37 + required: 38 + - compatible 39 + - reg 40 + - "#clock-cells" 41 + - clocks 42 + - clock-names 43 + - "#phy-cells" 44 + - power-domains 45 + 46 + additionalProperties: false 47 + 48 + examples: 49 + - | 50 + #include <dt-bindings/clock/imx8mp-clock.h> 51 + #include <dt-bindings/power/imx8mp-power.h> 52 + 53 + phy@32fdff00 { 54 + compatible = "fsl,imx8mp-hdmi-phy"; 55 + reg = <0x32fdff00 0x100>; 56 + clocks = <&clk IMX8MP_CLK_HDMI_APB>, 57 + <&clk IMX8MP_CLK_HDMI_24M>; 58 + clock-names = "apb", "ref"; 59 + power-domains = <&hdmi_blk_ctrl IMX8MP_HDMIBLK_PD_HDMI_TX_PHY>; 60 + #clock-cells = <0>; 61 + #phy-cells = <0>; 62 + };
+80
Documentation/devicetree/bindings/phy/mediatek,mt7988-xfi-tphy.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/mediatek,mt7988-xfi-tphy.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: MediaTek MT7988 XFI T-PHY 8 + 9 + maintainers: 10 + - Daniel Golle <daniel@makrotopia.org> 11 + 12 + description: 13 + The MediaTek XFI SerDes T-PHY provides the physical SerDes lanes 14 + used by the (10G/5G) USXGMII PCS and (1G/2.5G) LynxI PCS found in 15 + MediaTek's 10G-capabale MT7988 SoC. 16 + In MediaTek's SDK sources, this unit is referred to as "pextp". 17 + 18 + properties: 19 + compatible: 20 + const: mediatek,mt7988-xfi-tphy 21 + 22 + reg: 23 + maxItems: 1 24 + 25 + clocks: 26 + items: 27 + - description: XFI PHY clock 28 + - description: XFI register clock 29 + 30 + clock-names: 31 + items: 32 + - const: xfipll 33 + - const: topxtal 34 + 35 + resets: 36 + items: 37 + - description: Reset controller corresponding to the phy instance. 38 + 39 + mediatek,usxgmii-performance-errata: 40 + $ref: /schemas/types.yaml#/definitions/flag 41 + description: 42 + One instance of the T-PHY on MT7988 suffers from a performance 43 + problem in 10GBase-R mode which needs a work-around in the driver. 44 + This flag enables a work-around ajusting an analog phy setting and 45 + is required for XFI Port0 of the MT7988 SoC to be in compliance with 46 + the SFP specification. 47 + 48 + "#phy-cells": 49 + const: 0 50 + 51 + required: 52 + - compatible 53 + - reg 54 + - clocks 55 + - clock-names 56 + - resets 57 + - "#phy-cells" 58 + 59 + additionalProperties: false 60 + 61 + examples: 62 + - | 63 + #include <dt-bindings/clock/mediatek,mt7988-clk.h> 64 + soc { 65 + #address-cells = <2>; 66 + #size-cells = <2>; 67 + 68 + phy@11f20000 { 69 + compatible = "mediatek,mt7988-xfi-tphy"; 70 + reg = <0 0x11f20000 0 0x10000>; 71 + clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>, 72 + <&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>; 73 + clock-names = "xfipll", "topxtal"; 74 + resets = <&watchdog 14>; 75 + mediatek,usxgmii-performance-errata; 76 + #phy-cells = <0>; 77 + }; 78 + }; 79 + 80 + ...
+148
Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.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/phy-rockchip-usbdp.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Rockchip USBDP Combo PHY with Samsung IP block 8 + 9 + maintainers: 10 + - Frank Wang <frank.wang@rock-chips.com> 11 + - Zhang Yubing <yubing.zhang@rock-chips.com> 12 + 13 + properties: 14 + compatible: 15 + enum: 16 + - rockchip,rk3588-usbdp-phy 17 + 18 + reg: 19 + maxItems: 1 20 + 21 + "#phy-cells": 22 + description: | 23 + Cell allows setting the type of the PHY. Possible values are: 24 + - PHY_TYPE_USB3 25 + - PHY_TYPE_DP 26 + const: 1 27 + 28 + clocks: 29 + maxItems: 4 30 + 31 + clock-names: 32 + items: 33 + - const: refclk 34 + - const: immortal 35 + - const: pclk 36 + - const: utmi 37 + 38 + resets: 39 + maxItems: 5 40 + 41 + reset-names: 42 + items: 43 + - const: init 44 + - const: cmn 45 + - const: lane 46 + - const: pcs_apb 47 + - const: pma_apb 48 + 49 + rockchip,dp-lane-mux: 50 + $ref: /schemas/types.yaml#/definitions/uint32-array 51 + minItems: 2 52 + maxItems: 4 53 + items: 54 + maximum: 3 55 + description: 56 + An array of physical Type-C lanes indexes. Position of an entry 57 + determines the DisplayPort (DP) lane index, while the value of an entry 58 + indicates physical Type-C lane. The supported DP lanes number are 2 or 4. 59 + e.g. for 2 lanes DP lanes map, we could have "rockchip,dp-lane-mux = <2, 60 + 3>;", assuming DP lane0 on Type-C phy lane2, DP lane1 on Type-C phy 61 + lane3. For 4 lanes DP lanes map, we could have "rockchip,dp-lane-mux = 62 + <0, 1, 2, 3>;", assuming DP lane0 on Type-C phy lane0, DP lane1 on Type-C 63 + phy lane1, DP lane2 on Type-C phy lane2, DP lane3 on Type-C phy lane3. If 64 + DP lanes are mapped by DisplayPort Alt mode, this property is not needed. 65 + 66 + rockchip,u2phy-grf: 67 + $ref: /schemas/types.yaml#/definitions/phandle 68 + description: 69 + Phandle to the syscon managing the 'usb2 phy general register files'. 70 + 71 + rockchip,usb-grf: 72 + $ref: /schemas/types.yaml#/definitions/phandle 73 + description: 74 + Phandle to the syscon managing the 'usb general register files'. 75 + 76 + rockchip,usbdpphy-grf: 77 + $ref: /schemas/types.yaml#/definitions/phandle 78 + description: 79 + Phandle to the syscon managing the 'usbdp phy general register files'. 80 + 81 + rockchip,vo-grf: 82 + $ref: /schemas/types.yaml#/definitions/phandle 83 + description: 84 + Phandle to the syscon managing the 'video output general register files'. 85 + When select the DP lane mapping will request its phandle. 86 + 87 + sbu1-dc-gpios: 88 + description: 89 + GPIO connected to the SBU1 line of the USB-C connector via a big resistor 90 + (~100K) to apply a DC offset for signalling the connector orientation. 91 + maxItems: 1 92 + 93 + sbu2-dc-gpios: 94 + description: 95 + GPIO connected to the SBU2 line of the USB-C connector via a big resistor 96 + (~100K) to apply a DC offset for signalling the connector orientation. 97 + maxItems: 1 98 + 99 + orientation-switch: 100 + description: Flag the port as possible handler of orientation switching 101 + type: boolean 102 + 103 + mode-switch: 104 + description: Flag the port as possible handler of altmode switching 105 + type: boolean 106 + 107 + port: 108 + $ref: /schemas/graph.yaml#/properties/port 109 + description: 110 + A port node to link the PHY to a TypeC controller for the purpose of 111 + handling orientation switching. 112 + 113 + required: 114 + - compatible 115 + - reg 116 + - clocks 117 + - clock-names 118 + - resets 119 + - reset-names 120 + - "#phy-cells" 121 + 122 + additionalProperties: false 123 + 124 + examples: 125 + - | 126 + #include <dt-bindings/clock/rockchip,rk3588-cru.h> 127 + #include <dt-bindings/reset/rockchip,rk3588-cru.h> 128 + 129 + usbdp_phy0: phy@fed80000 { 130 + compatible = "rockchip,rk3588-usbdp-phy"; 131 + reg = <0xfed80000 0x10000>; 132 + #phy-cells = <1>; 133 + clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>, 134 + <&cru CLK_USBDP_PHY0_IMMORTAL>, 135 + <&cru PCLK_USBDPPHY0>, 136 + <&u2phy0>; 137 + clock-names = "refclk", "immortal", "pclk", "utmi"; 138 + resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>, 139 + <&cru SRST_USBDP_COMBO_PHY0_CMN>, 140 + <&cru SRST_USBDP_COMBO_PHY0_LANE>, 141 + <&cru SRST_USBDP_COMBO_PHY0_PCS>, 142 + <&cru SRST_P_USBDPPHY0>; 143 + reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb"; 144 + rockchip,u2phy-grf = <&usb2phy0_grf>; 145 + rockchip,usb-grf = <&usb_grf>; 146 + rockchip,usbdpphy-grf = <&usbdpphy0_grf>; 147 + rockchip,vo-grf = <&vo0_grf>; 148 + };
+1
Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml
··· 21 21 - qcom,sc8180x-edp-phy 22 22 - qcom,sc8280xp-dp-phy 23 23 - qcom,sc8280xp-edp-phy 24 + - qcom,x1e80100-dp-phy 24 25 25 26 reg: 26 27 items:
+24 -4
Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
··· 88 88 - description: offset of PCIe 4-lane configuration register 89 89 - description: offset of configuration bit for this PHY 90 90 91 - "#clock-cells": 92 - const: 0 91 + "#clock-cells": true 93 92 94 93 clock-output-names: 95 - maxItems: 1 94 + minItems: 1 95 + maxItems: 2 96 96 97 97 "#phy-cells": 98 98 const: 0 ··· 198 198 enum: 199 199 - qcom,sm8550-qmp-gen4x2-pcie-phy 200 200 - qcom,sm8650-qmp-gen4x2-pcie-phy 201 - - qcom,x1e80100-qmp-gen3x2-pcie-phy 202 201 - qcom,x1e80100-qmp-gen4x2-pcie-phy 203 202 then: 204 203 properties: ··· 211 212 maxItems: 1 212 213 reset-names: 213 214 maxItems: 1 215 + 216 + - if: 217 + properties: 218 + compatible: 219 + contains: 220 + enum: 221 + - qcom,sm8450-qmp-gen4x2-pcie-phy 222 + - qcom,sm8550-qmp-gen4x2-pcie-phy 223 + - qcom,sm8650-qmp-gen4x2-pcie-phy 224 + then: 225 + properties: 226 + clock-output-names: 227 + minItems: 2 228 + "#clock-cells": 229 + const: 1 230 + else: 231 + properties: 232 + clock-output-names: 233 + maxItems: 1 234 + "#clock-cells": 235 + const: 0 214 236 215 237 examples: 216 238 - |
+18 -1
Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
··· 32 32 - qcom,sm8250-qmp-ufs-phy 33 33 - qcom,sm8350-qmp-ufs-phy 34 34 - qcom,sm8450-qmp-ufs-phy 35 + - qcom,sm8475-qmp-ufs-phy 35 36 - qcom,sm8550-qmp-ufs-phy 36 37 - qcom,sm8650-qmp-ufs-phy 37 38 ··· 72 71 - reg 73 72 - clocks 74 73 - clock-names 75 - - power-domains 76 74 - resets 77 75 - reset-names 78 76 - vdda-phy-supply ··· 86 86 enum: 87 87 - qcom,msm8998-qmp-ufs-phy 88 88 - qcom,sa8775p-qmp-ufs-phy 89 + - qcom,sc7180-qmp-ufs-phy 89 90 - qcom,sc7280-qmp-ufs-phy 90 91 - qcom,sc8180x-qmp-ufs-phy 91 92 - qcom,sc8280xp-qmp-ufs-phy ··· 99 98 - qcom,sm8250-qmp-ufs-phy 100 99 - qcom,sm8350-qmp-ufs-phy 101 100 - qcom,sm8450-qmp-ufs-phy 101 + - qcom,sm8475-qmp-ufs-phy 102 102 - qcom,sm8550-qmp-ufs-phy 103 103 - qcom,sm8650-qmp-ufs-phy 104 104 then: ··· 128 126 items: 129 127 - const: ref 130 128 - const: qref 129 + 130 + - if: 131 + properties: 132 + compatible: 133 + contains: 134 + enum: 135 + - qcom,msm8996-qmp-ufs-phy 136 + - qcom,msm8998-qmp-ufs-phy 137 + then: 138 + properties: 139 + power-domains: 140 + false 141 + else: 142 + required: 143 + - power-domains 131 144 132 145 additionalProperties: false 133 146
+2
Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml
··· 20 20 - qcom,ipq8074-qmp-usb3-phy 21 21 - qcom,ipq9574-qmp-usb3-phy 22 22 - qcom,msm8996-qmp-usb3-phy 23 + - com,qdu1000-qmp-usb3-uni-phy 23 24 - qcom,sa8775p-qmp-usb3-uni-phy 24 25 - qcom,sc8280xp-qmp-usb3-uni-phy 25 26 - qcom,sdm845-qmp-usb3-uni-phy ··· 110 109 compatible: 111 110 contains: 112 111 enum: 112 + - qcom,qdu1000-qmp-usb3-uni-phy 113 113 - qcom,sa8775p-qmp-usb3-uni-phy 114 114 - qcom,sc8280xp-qmp-usb3-uni-phy 115 115 - qcom,sm8150-qmp-usb3-uni-phy
+3 -1
Documentation/devicetree/bindings/phy/qcom,snps-eusb2-repeater.yaml
··· 20 20 - enum: 21 21 - qcom,pm7550ba-eusb2-repeater 22 22 - const: qcom,pm8550b-eusb2-repeater 23 - - const: qcom,pm8550b-eusb2-repeater 23 + - enum: 24 + - qcom,pm8550b-eusb2-repeater 25 + - qcom,smb2360-eusb2-repeater 24 26 25 27 reg: 26 28 maxItems: 1
+2 -3
Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml
··· 15 15 properties: 16 16 compatible: 17 17 oneOf: 18 - - enum: 19 - - qcom,sc8180x-usb-hs-phy 20 - - qcom,usb-snps-femto-v2-phy 21 18 - items: 22 19 - enum: 23 20 - qcom,sa8775p-usb-hs-phy ··· 22 25 - const: qcom,usb-snps-hs-5nm-phy 23 26 - items: 24 27 - enum: 28 + - qcom,qdu1000-usb-hs-phy 25 29 - qcom,sc7280-usb-hs-phy 30 + - qcom,sc8180x-usb-hs-phy 26 31 - qcom,sdx55-usb-hs-phy 27 32 - qcom,sdx65-usb-hs-phy 28 33 - qcom,sm6375-usb-hs-phy
+10
Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
··· 54 54 $ref: /schemas/types.yaml#/definitions/phandle 55 55 description: phandle to the syscon managing the pipe "general register files" 56 56 57 + rockchip,rx-common-refclk-mode: 58 + description: which lanes (by position) should be configured to run in 59 + RX common reference clock mode. 0 means disabled, 1 means enabled. 60 + $ref: /schemas/types.yaml#/definitions/uint32-array 61 + minItems: 1 62 + maxItems: 16 63 + items: 64 + minimum: 0 65 + maximum: 1 66 + 57 67 required: 58 68 - compatible 59 69 - reg
+1
Documentation/devicetree/bindings/phy/samsung,ufs-phy.yaml
··· 15 15 16 16 compatible: 17 17 enum: 18 + - google,gs101-ufs-phy 18 19 - samsung,exynos7-ufs-phy 19 20 - samsung,exynosautov9-ufs-phy 20 21 - tesla,fsd-ufs-phy
+2
MAINTAINERS
··· 9312 9312 F: Documentation/devicetree/bindings/clock/google,gs101-clock.yaml 9313 9313 F: arch/arm64/boot/dts/exynos/google/ 9314 9314 F: drivers/clk/samsung/clk-gs101.c 9315 + F: drivers/phy/samsung/phy-gs101-ufs.c 9315 9316 F: include/dt-bindings/clock/google,gs101.h 9316 9317 K: [gG]oogle.?[tT]ensor 9317 9318 ··· 13988 13987 S: Maintained 13989 13988 F: drivers/net/phy/mediatek-ge-soc.c 13990 13989 F: drivers/net/phy/mediatek-ge.c 13990 + F: drivers/phy/mediatek/phy-mtk-xfi-tphy.c 13991 13991 13992 13992 MEDIATEK I2C CONTROLLER DRIVER 13993 13993 M: Qii Wang <qii.wang@mediatek.com>
+6
drivers/phy/freescale/Kconfig
··· 35 35 Enable this to add support for the PCIE PHY as found on 36 36 i.MX8M family of SOCs. 37 37 38 + config PHY_FSL_SAMSUNG_HDMI_PHY 39 + tristate "Samsung HDMI PHY support" 40 + depends on OF && HAS_IOMEM && COMMON_CLK 41 + help 42 + Enable this to add support for the Samsung HDMI PHY in i.MX8MP. 43 + 38 44 endif 39 45 40 46 config PHY_FSL_LYNX_28G
+1
drivers/phy/freescale/Makefile
··· 4 4 obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o 5 5 obj-$(CONFIG_PHY_FSL_IMX8M_PCIE) += phy-fsl-imx8m-pcie.o 6 6 obj-$(CONFIG_PHY_FSL_LYNX_28G) += phy-fsl-lynx-28g.o 7 + obj-$(CONFIG_PHY_FSL_SAMSUNG_HDMI_PHY) += phy-fsl-samsung-hdmi.o
+718
drivers/phy/freescale/phy-fsl-samsung-hdmi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright 2020 NXP 4 + * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de> 5 + */ 6 + 7 + #include <linux/bitfield.h> 8 + #include <linux/bits.h> 9 + #include <linux/clk.h> 10 + #include <linux/clk-provider.h> 11 + #include <linux/delay.h> 12 + #include <linux/iopoll.h> 13 + #include <linux/module.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/pm_runtime.h> 16 + 17 + #define PHY_REG_00 0x00 18 + #define PHY_REG_01 0x04 19 + #define PHY_REG_02 0x08 20 + #define PHY_REG_08 0x20 21 + #define PHY_REG_09 0x24 22 + #define PHY_REG_10 0x28 23 + #define PHY_REG_11 0x2c 24 + 25 + #define PHY_REG_12 0x30 26 + #define REG12_CK_DIV_MASK GENMASK(5, 4) 27 + 28 + #define PHY_REG_13 0x34 29 + #define REG13_TG_CODE_LOW_MASK GENMASK(7, 0) 30 + 31 + #define PHY_REG_14 0x38 32 + #define REG14_TOL_MASK GENMASK(7, 4) 33 + #define REG14_RP_CODE_MASK GENMASK(3, 1) 34 + #define REG14_TG_CODE_HIGH_MASK GENMASK(0, 0) 35 + 36 + #define PHY_REG_15 0x3c 37 + #define PHY_REG_16 0x40 38 + #define PHY_REG_17 0x44 39 + #define PHY_REG_18 0x48 40 + #define PHY_REG_19 0x4c 41 + #define PHY_REG_20 0x50 42 + 43 + #define PHY_REG_21 0x54 44 + #define REG21_SEL_TX_CK_INV BIT(7) 45 + #define REG21_PMS_S_MASK GENMASK(3, 0) 46 + 47 + #define PHY_REG_22 0x58 48 + #define PHY_REG_23 0x5c 49 + #define PHY_REG_24 0x60 50 + #define PHY_REG_25 0x64 51 + #define PHY_REG_26 0x68 52 + #define PHY_REG_27 0x6c 53 + #define PHY_REG_28 0x70 54 + #define PHY_REG_29 0x74 55 + #define PHY_REG_30 0x78 56 + #define PHY_REG_31 0x7c 57 + #define PHY_REG_32 0x80 58 + 59 + /* 60 + * REG33 does not match the ref manual. According to Sandor Yu from NXP, 61 + * "There is a doc issue on the i.MX8MP latest RM" 62 + * REG33 is being used per guidance from Sandor 63 + */ 64 + 65 + #define PHY_REG_33 0x84 66 + #define REG33_MODE_SET_DONE BIT(7) 67 + #define REG33_FIX_DA BIT(1) 68 + 69 + #define PHY_REG_34 0x88 70 + #define REG34_PHY_READY BIT(7) 71 + #define REG34_PLL_LOCK BIT(6) 72 + #define REG34_PHY_CLK_READY BIT(5) 73 + 74 + #define PHY_REG_35 0x8c 75 + #define PHY_REG_36 0x90 76 + #define PHY_REG_37 0x94 77 + #define PHY_REG_38 0x98 78 + #define PHY_REG_39 0x9c 79 + #define PHY_REG_40 0xa0 80 + #define PHY_REG_41 0xa4 81 + #define PHY_REG_42 0xa8 82 + #define PHY_REG_43 0xac 83 + #define PHY_REG_44 0xb0 84 + #define PHY_REG_45 0xb4 85 + #define PHY_REG_46 0xb8 86 + #define PHY_REG_47 0xbc 87 + 88 + #define PHY_PLL_DIV_REGS_NUM 6 89 + 90 + struct phy_config { 91 + u32 pixclk; 92 + u8 pll_div_regs[PHY_PLL_DIV_REGS_NUM]; 93 + }; 94 + 95 + static const struct phy_config phy_pll_cfg[] = { 96 + { 97 + .pixclk = 22250000, 98 + .pll_div_regs = { 0x4b, 0xf1, 0x89, 0x88, 0x80, 0x40 }, 99 + }, { 100 + .pixclk = 23750000, 101 + .pll_div_regs = { 0x50, 0xf1, 0x86, 0x85, 0x80, 0x40 }, 102 + }, { 103 + .pixclk = 24000000, 104 + .pll_div_regs = { 0x50, 0xf0, 0x00, 0x00, 0x80, 0x00 }, 105 + }, { 106 + .pixclk = 24024000, 107 + .pll_div_regs = { 0x50, 0xf1, 0x99, 0x02, 0x80, 0x40 }, 108 + }, { 109 + .pixclk = 25175000, 110 + .pll_div_regs = { 0x54, 0xfc, 0xcc, 0x91, 0x80, 0x40 }, 111 + }, { 112 + .pixclk = 25200000, 113 + .pll_div_regs = { 0x54, 0xf0, 0x00, 0x00, 0x80, 0x00 }, 114 + }, { 115 + .pixclk = 26750000, 116 + .pll_div_regs = { 0x5a, 0xf2, 0x89, 0x88, 0x80, 0x40 }, 117 + }, { 118 + .pixclk = 27000000, 119 + .pll_div_regs = { 0x5a, 0xf0, 0x00, 0x00, 0x80, 0x00 }, 120 + }, { 121 + .pixclk = 27027000, 122 + .pll_div_regs = { 0x5a, 0xf2, 0xfd, 0x0c, 0x80, 0x40 }, 123 + }, { 124 + .pixclk = 29500000, 125 + .pll_div_regs = { 0x62, 0xf4, 0x95, 0x08, 0x80, 0x40 }, 126 + }, { 127 + .pixclk = 30750000, 128 + .pll_div_regs = { 0x66, 0xf4, 0x82, 0x01, 0x88, 0x45 }, 129 + }, { 130 + .pixclk = 30888000, 131 + .pll_div_regs = { 0x66, 0xf4, 0x99, 0x18, 0x88, 0x45 }, 132 + }, { 133 + .pixclk = 33750000, 134 + .pll_div_regs = { 0x70, 0xf4, 0x82, 0x01, 0x80, 0x40 }, 135 + }, { 136 + .pixclk = 35000000, 137 + .pll_div_regs = { 0x58, 0xb8, 0x8b, 0x88, 0x80, 0x40 }, 138 + }, { 139 + .pixclk = 36000000, 140 + .pll_div_regs = { 0x5a, 0xb0, 0x00, 0x00, 0x80, 0x00 }, 141 + }, { 142 + .pixclk = 36036000, 143 + .pll_div_regs = { 0x5a, 0xb2, 0xfd, 0x0c, 0x80, 0x40 }, 144 + }, { 145 + .pixclk = 40000000, 146 + .pll_div_regs = { 0x64, 0xb0, 0x00, 0x00, 0x80, 0x00 }, 147 + }, { 148 + .pixclk = 43200000, 149 + .pll_div_regs = { 0x5a, 0x90, 0x00, 0x00, 0x80, 0x00 }, 150 + }, { 151 + .pixclk = 43243200, 152 + .pll_div_regs = { 0x5a, 0x92, 0xfd, 0x0c, 0x80, 0x40 }, 153 + }, { 154 + .pixclk = 44500000, 155 + .pll_div_regs = { 0x5c, 0x92, 0x98, 0x11, 0x84, 0x41 }, 156 + }, { 157 + .pixclk = 47000000, 158 + .pll_div_regs = { 0x62, 0x94, 0x95, 0x82, 0x80, 0x40 }, 159 + }, { 160 + .pixclk = 47500000, 161 + .pll_div_regs = { 0x63, 0x96, 0xa1, 0x82, 0x80, 0x40 }, 162 + }, { 163 + .pixclk = 50349650, 164 + .pll_div_regs = { 0x54, 0x7c, 0xc3, 0x8f, 0x80, 0x40 }, 165 + }, { 166 + .pixclk = 50400000, 167 + .pll_div_regs = { 0x54, 0x70, 0x00, 0x00, 0x80, 0x00 }, 168 + }, { 169 + .pixclk = 53250000, 170 + .pll_div_regs = { 0x58, 0x72, 0x84, 0x03, 0x82, 0x41 }, 171 + }, { 172 + .pixclk = 53500000, 173 + .pll_div_regs = { 0x5a, 0x72, 0x89, 0x88, 0x80, 0x40 }, 174 + }, { 175 + .pixclk = 54000000, 176 + .pll_div_regs = { 0x5a, 0x70, 0x00, 0x00, 0x80, 0x00 }, 177 + }, { 178 + .pixclk = 54054000, 179 + .pll_div_regs = { 0x5a, 0x72, 0xfd, 0x0c, 0x80, 0x40 }, 180 + }, { 181 + .pixclk = 59000000, 182 + .pll_div_regs = { 0x62, 0x74, 0x95, 0x08, 0x80, 0x40 }, 183 + }, { 184 + .pixclk = 59340659, 185 + .pll_div_regs = { 0x62, 0x74, 0xdb, 0x52, 0x88, 0x47 }, 186 + }, { 187 + .pixclk = 59400000, 188 + .pll_div_regs = { 0x63, 0x70, 0x00, 0x00, 0x80, 0x00 }, 189 + }, { 190 + .pixclk = 61500000, 191 + .pll_div_regs = { 0x66, 0x74, 0x82, 0x01, 0x88, 0x45 }, 192 + }, { 193 + .pixclk = 63500000, 194 + .pll_div_regs = { 0x69, 0x74, 0x89, 0x08, 0x80, 0x40 }, 195 + }, { 196 + .pixclk = 67500000, 197 + .pll_div_regs = { 0x54, 0x52, 0x87, 0x03, 0x80, 0x40 }, 198 + }, { 199 + .pixclk = 70000000, 200 + .pll_div_regs = { 0x58, 0x58, 0x8b, 0x88, 0x80, 0x40 }, 201 + }, { 202 + .pixclk = 72000000, 203 + .pll_div_regs = { 0x5a, 0x50, 0x00, 0x00, 0x80, 0x00 }, 204 + }, { 205 + .pixclk = 72072000, 206 + .pll_div_regs = { 0x5a, 0x52, 0xfd, 0x0c, 0x80, 0x40 }, 207 + }, { 208 + .pixclk = 74176000, 209 + .pll_div_regs = { 0x5d, 0x58, 0xdb, 0xA2, 0x88, 0x41 }, 210 + }, { 211 + .pixclk = 74250000, 212 + .pll_div_regs = { 0x5c, 0x52, 0x90, 0x0d, 0x84, 0x41 }, 213 + }, { 214 + .pixclk = 78500000, 215 + .pll_div_regs = { 0x62, 0x54, 0x87, 0x01, 0x80, 0x40 }, 216 + }, { 217 + .pixclk = 80000000, 218 + .pll_div_regs = { 0x64, 0x50, 0x00, 0x00, 0x80, 0x00 }, 219 + }, { 220 + .pixclk = 82000000, 221 + .pll_div_regs = { 0x66, 0x54, 0x82, 0x01, 0x88, 0x45 }, 222 + }, { 223 + .pixclk = 82500000, 224 + .pll_div_regs = { 0x67, 0x54, 0x88, 0x01, 0x90, 0x49 }, 225 + }, { 226 + .pixclk = 89000000, 227 + .pll_div_regs = { 0x70, 0x54, 0x84, 0x83, 0x80, 0x40 }, 228 + }, { 229 + .pixclk = 90000000, 230 + .pll_div_regs = { 0x70, 0x54, 0x82, 0x01, 0x80, 0x40 }, 231 + }, { 232 + .pixclk = 94000000, 233 + .pll_div_regs = { 0x4e, 0x32, 0xa7, 0x10, 0x80, 0x40 }, 234 + }, { 235 + .pixclk = 95000000, 236 + .pll_div_regs = { 0x50, 0x31, 0x86, 0x85, 0x80, 0x40 }, 237 + }, { 238 + .pixclk = 98901099, 239 + .pll_div_regs = { 0x52, 0x3a, 0xdb, 0x4c, 0x88, 0x47 }, 240 + }, { 241 + .pixclk = 99000000, 242 + .pll_div_regs = { 0x52, 0x32, 0x82, 0x01, 0x88, 0x47 }, 243 + }, { 244 + .pixclk = 100699300, 245 + .pll_div_regs = { 0x54, 0x3c, 0xc3, 0x8f, 0x80, 0x40 }, 246 + }, { 247 + .pixclk = 100800000, 248 + .pll_div_regs = { 0x54, 0x30, 0x00, 0x00, 0x80, 0x00 }, 249 + }, { 250 + .pixclk = 102500000, 251 + .pll_div_regs = { 0x55, 0x32, 0x8c, 0x05, 0x90, 0x4b }, 252 + }, { 253 + .pixclk = 104750000, 254 + .pll_div_regs = { 0x57, 0x32, 0x98, 0x07, 0x90, 0x49 }, 255 + }, { 256 + .pixclk = 106500000, 257 + .pll_div_regs = { 0x58, 0x32, 0x84, 0x03, 0x82, 0x41 }, 258 + }, { 259 + .pixclk = 107000000, 260 + .pll_div_regs = { 0x5a, 0x32, 0x89, 0x88, 0x80, 0x40 }, 261 + }, { 262 + .pixclk = 108000000, 263 + .pll_div_regs = { 0x5a, 0x30, 0x00, 0x00, 0x80, 0x00 }, 264 + }, { 265 + .pixclk = 108108000, 266 + .pll_div_regs = { 0x5a, 0x32, 0xfd, 0x0c, 0x80, 0x40 }, 267 + }, { 268 + .pixclk = 118000000, 269 + .pll_div_regs = { 0x62, 0x34, 0x95, 0x08, 0x80, 0x40 }, 270 + }, { 271 + .pixclk = 118800000, 272 + .pll_div_regs = { 0x63, 0x30, 0x00, 0x00, 0x80, 0x00 }, 273 + }, { 274 + .pixclk = 123000000, 275 + .pll_div_regs = { 0x66, 0x34, 0x82, 0x01, 0x88, 0x45 }, 276 + }, { 277 + .pixclk = 127000000, 278 + .pll_div_regs = { 0x69, 0x34, 0x89, 0x08, 0x80, 0x40 }, 279 + }, { 280 + .pixclk = 135000000, 281 + .pll_div_regs = { 0x70, 0x34, 0x82, 0x01, 0x80, 0x40 }, 282 + }, { 283 + .pixclk = 135580000, 284 + .pll_div_regs = { 0x71, 0x39, 0xe9, 0x82, 0x9c, 0x5b }, 285 + }, { 286 + .pixclk = 137520000, 287 + .pll_div_regs = { 0x72, 0x38, 0x99, 0x10, 0x85, 0x41 }, 288 + }, { 289 + .pixclk = 138750000, 290 + .pll_div_regs = { 0x73, 0x35, 0x88, 0x05, 0x90, 0x4d }, 291 + }, { 292 + .pixclk = 140000000, 293 + .pll_div_regs = { 0x75, 0x36, 0xa7, 0x90, 0x80, 0x40 }, 294 + }, { 295 + .pixclk = 144000000, 296 + .pll_div_regs = { 0x78, 0x30, 0x00, 0x00, 0x80, 0x00 }, 297 + }, { 298 + .pixclk = 148352000, 299 + .pll_div_regs = { 0x7b, 0x35, 0xdb, 0x39, 0x90, 0x45 }, 300 + }, { 301 + .pixclk = 148500000, 302 + .pll_div_regs = { 0x7b, 0x35, 0x84, 0x03, 0x90, 0x45 }, 303 + }, { 304 + .pixclk = 154000000, 305 + .pll_div_regs = { 0x40, 0x18, 0x83, 0x01, 0x00, 0x40 }, 306 + }, { 307 + .pixclk = 157000000, 308 + .pll_div_regs = { 0x41, 0x11, 0xa7, 0x14, 0x80, 0x40 }, 309 + }, { 310 + .pixclk = 160000000, 311 + .pll_div_regs = { 0x42, 0x12, 0xa1, 0x20, 0x80, 0x40 }, 312 + }, { 313 + .pixclk = 162000000, 314 + .pll_div_regs = { 0x43, 0x18, 0x8b, 0x08, 0x96, 0x55 }, 315 + }, { 316 + .pixclk = 164000000, 317 + .pll_div_regs = { 0x45, 0x11, 0x83, 0x82, 0x90, 0x4b }, 318 + }, { 319 + .pixclk = 165000000, 320 + .pll_div_regs = { 0x45, 0x11, 0x84, 0x81, 0x90, 0x4b }, 321 + }, { 322 + .pixclk = 180000000, 323 + .pll_div_regs = { 0x4b, 0x10, 0x00, 0x00, 0x80, 0x00 }, 324 + }, { 325 + .pixclk = 185625000, 326 + .pll_div_regs = { 0x4e, 0x12, 0x9a, 0x95, 0x80, 0x40 }, 327 + }, { 328 + .pixclk = 188000000, 329 + .pll_div_regs = { 0x4e, 0x12, 0xa7, 0x10, 0x80, 0x40 }, 330 + }, { 331 + .pixclk = 198000000, 332 + .pll_div_regs = { 0x52, 0x12, 0x82, 0x01, 0x88, 0x47 }, 333 + }, { 334 + .pixclk = 205000000, 335 + .pll_div_regs = { 0x55, 0x12, 0x8c, 0x05, 0x90, 0x4b }, 336 + }, { 337 + .pixclk = 209500000, 338 + .pll_div_regs = { 0x57, 0x12, 0x98, 0x07, 0x90, 0x49 }, 339 + }, { 340 + .pixclk = 213000000, 341 + .pll_div_regs = { 0x58, 0x12, 0x84, 0x03, 0x82, 0x41 }, 342 + }, { 343 + .pixclk = 216000000, 344 + .pll_div_regs = { 0x5a, 0x10, 0x00, 0x00, 0x80, 0x00 }, 345 + }, { 346 + .pixclk = 216216000, 347 + .pll_div_regs = { 0x5a, 0x12, 0xfd, 0x0c, 0x80, 0x40 }, 348 + }, { 349 + .pixclk = 237600000, 350 + .pll_div_regs = { 0x63, 0x10, 0x00, 0x00, 0x80, 0x00 }, 351 + }, { 352 + .pixclk = 254000000, 353 + .pll_div_regs = { 0x69, 0x14, 0x89, 0x08, 0x80, 0x40 }, 354 + }, { 355 + .pixclk = 277500000, 356 + .pll_div_regs = { 0x73, 0x15, 0x88, 0x05, 0x90, 0x4d }, 357 + }, { 358 + .pixclk = 288000000, 359 + .pll_div_regs = { 0x78, 0x10, 0x00, 0x00, 0x80, 0x00 }, 360 + }, { 361 + .pixclk = 297000000, 362 + .pll_div_regs = { 0x7b, 0x15, 0x84, 0x03, 0x90, 0x45 }, 363 + }, 364 + }; 365 + 366 + struct reg_settings { 367 + u8 reg; 368 + u8 val; 369 + }; 370 + 371 + static const struct reg_settings common_phy_cfg[] = { 372 + { PHY_REG_00, 0x00 }, { PHY_REG_01, 0xd1 }, 373 + { PHY_REG_08, 0x4f }, { PHY_REG_09, 0x30 }, 374 + { PHY_REG_10, 0x33 }, { PHY_REG_11, 0x65 }, 375 + /* REG12 pixclk specific */ 376 + /* REG13 pixclk specific */ 377 + /* REG14 pixclk specific */ 378 + { PHY_REG_15, 0x80 }, { PHY_REG_16, 0x6c }, 379 + { PHY_REG_17, 0xf2 }, { PHY_REG_18, 0x67 }, 380 + { PHY_REG_19, 0x00 }, { PHY_REG_20, 0x10 }, 381 + /* REG21 pixclk specific */ 382 + { PHY_REG_22, 0x30 }, { PHY_REG_23, 0x32 }, 383 + { PHY_REG_24, 0x60 }, { PHY_REG_25, 0x8f }, 384 + { PHY_REG_26, 0x00 }, { PHY_REG_27, 0x00 }, 385 + { PHY_REG_28, 0x08 }, { PHY_REG_29, 0x00 }, 386 + { PHY_REG_30, 0x00 }, { PHY_REG_31, 0x00 }, 387 + { PHY_REG_32, 0x00 }, { PHY_REG_33, 0x80 }, 388 + { PHY_REG_34, 0x00 }, { PHY_REG_35, 0x00 }, 389 + { PHY_REG_36, 0x00 }, { PHY_REG_37, 0x00 }, 390 + { PHY_REG_38, 0x00 }, { PHY_REG_39, 0x00 }, 391 + { PHY_REG_40, 0x00 }, { PHY_REG_41, 0xe0 }, 392 + { PHY_REG_42, 0x83 }, { PHY_REG_43, 0x0f }, 393 + { PHY_REG_44, 0x3E }, { PHY_REG_45, 0xf8 }, 394 + { PHY_REG_46, 0x00 }, { PHY_REG_47, 0x00 } 395 + }; 396 + 397 + struct fsl_samsung_hdmi_phy { 398 + struct device *dev; 399 + void __iomem *regs; 400 + struct clk *apbclk; 401 + struct clk *refclk; 402 + 403 + /* clk provider */ 404 + struct clk_hw hw; 405 + const struct phy_config *cur_cfg; 406 + }; 407 + 408 + static inline struct fsl_samsung_hdmi_phy * 409 + to_fsl_samsung_hdmi_phy(struct clk_hw *hw) 410 + { 411 + return container_of(hw, struct fsl_samsung_hdmi_phy, hw); 412 + } 413 + 414 + static void 415 + fsl_samsung_hdmi_phy_configure_pixclk(struct fsl_samsung_hdmi_phy *phy, 416 + const struct phy_config *cfg) 417 + { 418 + u8 div = 0x1; 419 + 420 + switch (cfg->pixclk) { 421 + case 22250000 ... 33750000: 422 + div = 0xf; 423 + break; 424 + case 35000000 ... 40000000: 425 + div = 0xb; 426 + break; 427 + case 43200000 ... 47500000: 428 + div = 0x9; 429 + break; 430 + case 50349650 ... 63500000: 431 + div = 0x7; 432 + break; 433 + case 67500000 ... 90000000: 434 + div = 0x5; 435 + break; 436 + case 94000000 ... 148500000: 437 + div = 0x3; 438 + break; 439 + case 154000000 ... 297000000: 440 + div = 0x1; 441 + break; 442 + } 443 + 444 + writeb(REG21_SEL_TX_CK_INV | FIELD_PREP(REG21_PMS_S_MASK, div), 445 + phy->regs + PHY_REG_21); 446 + } 447 + 448 + static void 449 + fsl_samsung_hdmi_phy_configure_pll_lock_det(struct fsl_samsung_hdmi_phy *phy, 450 + const struct phy_config *cfg) 451 + { 452 + u32 pclk = cfg->pixclk; 453 + u32 fld_tg_code; 454 + u32 pclk_khz; 455 + u8 div = 1; 456 + 457 + switch (cfg->pixclk) { 458 + case 22250000 ... 47500000: 459 + div = 1; 460 + break; 461 + case 50349650 ... 99000000: 462 + div = 2; 463 + break; 464 + case 100699300 ... 198000000: 465 + div = 4; 466 + break; 467 + case 205000000 ... 297000000: 468 + div = 8; 469 + break; 470 + } 471 + 472 + writeb(FIELD_PREP(REG12_CK_DIV_MASK, ilog2(div)), phy->regs + PHY_REG_12); 473 + 474 + /* 475 + * Calculation for the frequency lock detector target code (fld_tg_code) 476 + * is based on reference manual register description of PHY_REG13 477 + * (13.10.3.1.14.2): 478 + * 1st) Calculate int_pllclk which is determinded by FLD_CK_DIV 479 + * 2nd) Increase resolution to avoid rounding issues 480 + * 3th) Do the div (256 / Freq. of int_pllclk) * 24 481 + * 4th) Reduce the resolution and always round up since the NXP 482 + * settings rounding up always too. TODO: Check if that is 483 + * correct. 484 + */ 485 + pclk /= div; 486 + pclk_khz = pclk / 1000; 487 + fld_tg_code = 256 * 1000 * 1000 / pclk_khz * 24; 488 + fld_tg_code = DIV_ROUND_UP(fld_tg_code, 1000); 489 + 490 + /* FLD_TOL and FLD_RP_CODE taken from downstream driver */ 491 + writeb(FIELD_PREP(REG13_TG_CODE_LOW_MASK, fld_tg_code), 492 + phy->regs + PHY_REG_13); 493 + writeb(FIELD_PREP(REG14_TOL_MASK, 2) | 494 + FIELD_PREP(REG14_RP_CODE_MASK, 2) | 495 + FIELD_PREP(REG14_TG_CODE_HIGH_MASK, fld_tg_code >> 8), 496 + phy->regs + PHY_REG_14); 497 + } 498 + 499 + static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy, 500 + const struct phy_config *cfg) 501 + { 502 + int i, ret; 503 + u8 val; 504 + 505 + /* HDMI PHY init */ 506 + writeb(REG33_FIX_DA, phy->regs + PHY_REG_33); 507 + 508 + /* common PHY registers */ 509 + for (i = 0; i < ARRAY_SIZE(common_phy_cfg); i++) 510 + writeb(common_phy_cfg[i].val, phy->regs + common_phy_cfg[i].reg); 511 + 512 + /* set individual PLL registers PHY_REG2 ... PHY_REG7 */ 513 + for (i = 0; i < PHY_PLL_DIV_REGS_NUM; i++) 514 + writeb(cfg->pll_div_regs[i], phy->regs + PHY_REG_02 + i * 4); 515 + 516 + fsl_samsung_hdmi_phy_configure_pixclk(phy, cfg); 517 + fsl_samsung_hdmi_phy_configure_pll_lock_det(phy, cfg); 518 + 519 + writeb(REG33_FIX_DA | REG33_MODE_SET_DONE, phy->regs + PHY_REG_33); 520 + 521 + ret = readb_poll_timeout(phy->regs + PHY_REG_34, val, 522 + val & REG34_PLL_LOCK, 50, 20000); 523 + if (ret) 524 + dev_err(phy->dev, "PLL failed to lock\n"); 525 + 526 + return ret; 527 + } 528 + 529 + static unsigned long phy_clk_recalc_rate(struct clk_hw *hw, 530 + unsigned long parent_rate) 531 + { 532 + struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw); 533 + 534 + if (!phy->cur_cfg) 535 + return 74250000; 536 + 537 + return phy->cur_cfg->pixclk; 538 + } 539 + 540 + static long phy_clk_round_rate(struct clk_hw *hw, 541 + unsigned long rate, unsigned long *parent_rate) 542 + { 543 + int i; 544 + 545 + for (i = ARRAY_SIZE(phy_pll_cfg) - 1; i >= 0; i--) 546 + if (phy_pll_cfg[i].pixclk <= rate) 547 + return phy_pll_cfg[i].pixclk; 548 + 549 + return -EINVAL; 550 + } 551 + 552 + static int phy_clk_set_rate(struct clk_hw *hw, 553 + unsigned long rate, unsigned long parent_rate) 554 + { 555 + struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw); 556 + int i; 557 + 558 + for (i = ARRAY_SIZE(phy_pll_cfg) - 1; i >= 0; i--) 559 + if (phy_pll_cfg[i].pixclk <= rate) 560 + break; 561 + 562 + if (i < 0) 563 + return -EINVAL; 564 + 565 + phy->cur_cfg = &phy_pll_cfg[i]; 566 + 567 + return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg); 568 + } 569 + 570 + static const struct clk_ops phy_clk_ops = { 571 + .recalc_rate = phy_clk_recalc_rate, 572 + .round_rate = phy_clk_round_rate, 573 + .set_rate = phy_clk_set_rate, 574 + }; 575 + 576 + static int phy_clk_register(struct fsl_samsung_hdmi_phy *phy) 577 + { 578 + struct device *dev = phy->dev; 579 + struct device_node *np = dev->of_node; 580 + struct clk_init_data init; 581 + const char *parent_name; 582 + struct clk *phyclk; 583 + int ret; 584 + 585 + parent_name = __clk_get_name(phy->refclk); 586 + 587 + init.parent_names = &parent_name; 588 + init.num_parents = 1; 589 + init.flags = 0; 590 + init.name = "hdmi_pclk"; 591 + init.ops = &phy_clk_ops; 592 + 593 + phy->hw.init = &init; 594 + 595 + phyclk = devm_clk_register(dev, &phy->hw); 596 + if (IS_ERR(phyclk)) 597 + return dev_err_probe(dev, PTR_ERR(phyclk), 598 + "failed to register clock\n"); 599 + 600 + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, phyclk); 601 + if (ret) 602 + return dev_err_probe(dev, ret, 603 + "failed to register clock provider\n"); 604 + 605 + return 0; 606 + } 607 + 608 + static int fsl_samsung_hdmi_phy_probe(struct platform_device *pdev) 609 + { 610 + struct fsl_samsung_hdmi_phy *phy; 611 + int ret; 612 + 613 + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); 614 + if (!phy) 615 + return -ENOMEM; 616 + 617 + platform_set_drvdata(pdev, phy); 618 + phy->dev = &pdev->dev; 619 + 620 + phy->regs = devm_platform_ioremap_resource(pdev, 0); 621 + if (IS_ERR(phy->regs)) 622 + return PTR_ERR(phy->regs); 623 + 624 + phy->apbclk = devm_clk_get(phy->dev, "apb"); 625 + if (IS_ERR(phy->apbclk)) 626 + return dev_err_probe(phy->dev, PTR_ERR(phy->apbclk), 627 + "failed to get apb clk\n"); 628 + 629 + phy->refclk = devm_clk_get(phy->dev, "ref"); 630 + if (IS_ERR(phy->refclk)) 631 + return dev_err_probe(phy->dev, PTR_ERR(phy->refclk), 632 + "failed to get ref clk\n"); 633 + 634 + ret = clk_prepare_enable(phy->apbclk); 635 + if (ret) { 636 + dev_err(phy->dev, "failed to enable apbclk\n"); 637 + return ret; 638 + } 639 + 640 + pm_runtime_get_noresume(phy->dev); 641 + pm_runtime_set_active(phy->dev); 642 + pm_runtime_enable(phy->dev); 643 + 644 + ret = phy_clk_register(phy); 645 + if (ret) { 646 + dev_err(&pdev->dev, "register clk failed\n"); 647 + goto register_clk_failed; 648 + } 649 + 650 + pm_runtime_put(phy->dev); 651 + 652 + return 0; 653 + 654 + register_clk_failed: 655 + clk_disable_unprepare(phy->apbclk); 656 + 657 + return ret; 658 + } 659 + 660 + static void fsl_samsung_hdmi_phy_remove(struct platform_device *pdev) 661 + { 662 + of_clk_del_provider(pdev->dev.of_node); 663 + } 664 + 665 + static int __maybe_unused fsl_samsung_hdmi_phy_suspend(struct device *dev) 666 + { 667 + struct fsl_samsung_hdmi_phy *phy = dev_get_drvdata(dev); 668 + 669 + clk_disable_unprepare(phy->apbclk); 670 + 671 + return 0; 672 + } 673 + 674 + static int __maybe_unused fsl_samsung_hdmi_phy_resume(struct device *dev) 675 + { 676 + struct fsl_samsung_hdmi_phy *phy = dev_get_drvdata(dev); 677 + int ret = 0; 678 + 679 + ret = clk_prepare_enable(phy->apbclk); 680 + if (ret) { 681 + dev_err(phy->dev, "failed to enable apbclk\n"); 682 + return ret; 683 + } 684 + 685 + if (phy->cur_cfg) 686 + ret = fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg); 687 + 688 + return ret; 689 + 690 + } 691 + 692 + static DEFINE_RUNTIME_DEV_PM_OPS(fsl_samsung_hdmi_phy_pm_ops, 693 + fsl_samsung_hdmi_phy_suspend, 694 + fsl_samsung_hdmi_phy_resume, NULL); 695 + 696 + static const struct of_device_id fsl_samsung_hdmi_phy_of_match[] = { 697 + { 698 + .compatible = "fsl,imx8mp-hdmi-phy", 699 + }, { 700 + /* sentinel */ 701 + } 702 + }; 703 + MODULE_DEVICE_TABLE(of, fsl_samsung_hdmi_phy_of_match); 704 + 705 + static struct platform_driver fsl_samsung_hdmi_phy_driver = { 706 + .probe = fsl_samsung_hdmi_phy_probe, 707 + .remove_new = fsl_samsung_hdmi_phy_remove, 708 + .driver = { 709 + .name = "fsl-samsung-hdmi-phy", 710 + .of_match_table = fsl_samsung_hdmi_phy_of_match, 711 + .pm = pm_ptr(&fsl_samsung_hdmi_phy_pm_ops), 712 + }, 713 + }; 714 + module_platform_driver(fsl_samsung_hdmi_phy_driver); 715 + 716 + MODULE_AUTHOR("Sandor Yu <Sandor.yu@nxp.com>"); 717 + MODULE_DESCRIPTION("SAMSUNG HDMI 2.0 Transmitter PHY Driver"); 718 + MODULE_LICENSE("GPL");
+11
drivers/phy/mediatek/Kconfig
··· 13 13 callback for PCIe GEN3 port, it supports software efuse 14 14 initialization. 15 15 16 + config PHY_MTK_XFI_TPHY 17 + tristate "MediaTek 10GE SerDes XFI T-PHY driver" 18 + depends on ARCH_MEDIATEK || COMPILE_TEST 19 + depends on OF 20 + select GENERIC_PHY 21 + help 22 + Say 'Y' here to add support for MediaTek XFI T-PHY driver. 23 + The driver provides access to the Ethernet SerDes T-PHY supporting 24 + 1GE and 2.5GE modes via the LynxI PCS, and 5GE and 10GE modes 25 + via the USXGMII PCS found in MediaTek SoCs with 10G Ethernet. 26 + 16 27 config PHY_MTK_TPHY 17 28 tristate "MediaTek T-PHY Driver" 18 29 depends on ARCH_MEDIATEK || COMPILE_TEST
+1
drivers/phy/mediatek/Makefile
··· 8 8 obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o 9 9 obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o 10 10 obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o 11 + obj-$(CONFIG_PHY_MTK_XFI_TPHY) += phy-mtk-xfi-tphy.o 11 12 12 13 phy-mtk-hdmi-drv-y := phy-mtk-hdmi.o 13 14 phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt2701.o
+451
drivers/phy/mediatek/phy-mtk-xfi-tphy.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * MediaTek 10GE SerDes XFI T-PHY driver 4 + * 5 + * Copyright (c) 2024 Daniel Golle <daniel@makrotopia.org> 6 + * Bc-bocun Chen <bc-bocun.chen@mediatek.com> 7 + * based on mtk_usxgmii.c and mtk_sgmii.c found in MediaTek's SDK (GPL-2.0) 8 + * Copyright (c) 2022 MediaTek Inc. 9 + * Author: Henry Yen <henry.yen@mediatek.com> 10 + */ 11 + 12 + #include <linux/module.h> 13 + #include <linux/device.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/of.h> 16 + #include <linux/io.h> 17 + #include <linux/clk.h> 18 + #include <linux/reset.h> 19 + #include <linux/phy.h> 20 + #include <linux/phy/phy.h> 21 + 22 + #include "phy-mtk-io.h" 23 + 24 + #define MTK_XFI_TPHY_NUM_CLOCKS 2 25 + 26 + #define REG_DIG_GLB_70 0x0070 27 + #define XTP_PCS_RX_EQ_IN_PROGRESS(x) FIELD_PREP(GENMASK(25, 24), (x)) 28 + #define XTP_PCS_MODE_MASK GENMASK(17, 16) 29 + #define XTP_PCS_MODE(x) FIELD_PREP(GENMASK(17, 16), (x)) 30 + #define XTP_PCS_RST_B BIT(15) 31 + #define XTP_FRC_PCS_RST_B BIT(14) 32 + #define XTP_PCS_PWD_SYNC_MASK GENMASK(13, 12) 33 + #define XTP_PCS_PWD_SYNC(x) FIELD_PREP(XTP_PCS_PWD_SYNC_MASK, (x)) 34 + #define XTP_PCS_PWD_ASYNC_MASK GENMASK(11, 10) 35 + #define XTP_PCS_PWD_ASYNC(x) FIELD_PREP(XTP_PCS_PWD_ASYNC_MASK, (x)) 36 + #define XTP_FRC_PCS_PWD_ASYNC BIT(8) 37 + #define XTP_PCS_UPDT BIT(4) 38 + #define XTP_PCS_IN_FR_RG BIT(0) 39 + 40 + #define REG_DIG_GLB_F4 0x00f4 41 + #define XFI_DPHY_PCS_SEL BIT(0) 42 + #define XFI_DPHY_PCS_SEL_SGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 1) 43 + #define XFI_DPHY_PCS_SEL_USXGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 0) 44 + #define XFI_DPHY_AD_SGDT_FRC_EN BIT(5) 45 + 46 + #define REG_DIG_LN_TRX_40 0x3040 47 + #define XTP_LN_FRC_TX_DATA_EN BIT(29) 48 + #define XTP_LN_TX_DATA_EN BIT(28) 49 + 50 + #define REG_DIG_LN_TRX_B0 0x30b0 51 + #define XTP_LN_FRC_TX_MACCK_EN BIT(5) 52 + #define XTP_LN_TX_MACCK_EN BIT(4) 53 + 54 + #define REG_ANA_GLB_D0 0x90d0 55 + #define XTP_GLB_USXGMII_SEL_MASK GENMASK(3, 1) 56 + #define XTP_GLB_USXGMII_SEL(x) FIELD_PREP(GENMASK(3, 1), (x)) 57 + #define XTP_GLB_USXGMII_EN BIT(0) 58 + 59 + /** 60 + * struct mtk_xfi_tphy - run-time data of the XFI phy instance 61 + * @base: IO memory area to access phy registers. 62 + * @dev: Kernel device used to output prefixed debug info. 63 + * @reset: Reset control corresponding to the phy instance. 64 + * @clocks: All clocks required for the phy to operate. 65 + * @da_war: Enables work-around for 10GBase-R mode. 66 + */ 67 + struct mtk_xfi_tphy { 68 + void __iomem *base; 69 + struct device *dev; 70 + struct reset_control *reset; 71 + struct clk_bulk_data clocks[MTK_XFI_TPHY_NUM_CLOCKS]; 72 + bool da_war; 73 + }; 74 + 75 + /** 76 + * mtk_xfi_tphy_setup() - Setup phy for specified interface mode. 77 + * @xfi_tphy: XFI phy instance. 78 + * @interface: Ethernet interface mode 79 + * 80 + * The setup function is the condensed result of combining the 5 functions which 81 + * setup the phy in MediaTek's GPL licensed public SDK sources. They can be found 82 + * in mtk_sgmii.c[1] as well as mtk_usxgmii.c[2]. 83 + * 84 + * Many magic values have been replaced by register and bit definitions, however, 85 + * that has not been possible in all cases. While the vendor driver uses a 86 + * sequence of 32-bit writes, here we try to only modify the actually required 87 + * bits. 88 + * 89 + * [1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/b72d6cba92bf9e29fb035c03052fa1e86664a25b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c 90 + * 91 + * [2]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/dec96a1d9b82cdcda4a56453fd0b453d4cab4b85/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c 92 + */ 93 + static void mtk_xfi_tphy_setup(struct mtk_xfi_tphy *xfi_tphy, 94 + phy_interface_t interface) 95 + { 96 + bool is_1g, is_2p5g, is_5g, is_10g, da_war, use_lynxi_pcs; 97 + 98 + /* shorthands for specific clock speeds depending on interface mode */ 99 + is_1g = interface == PHY_INTERFACE_MODE_1000BASEX || 100 + interface == PHY_INTERFACE_MODE_SGMII; 101 + is_2p5g = interface == PHY_INTERFACE_MODE_2500BASEX; 102 + is_5g = interface == PHY_INTERFACE_MODE_5GBASER; 103 + is_10g = interface == PHY_INTERFACE_MODE_10GBASER || 104 + interface == PHY_INTERFACE_MODE_USXGMII; 105 + 106 + /* Is overriding 10GBase-R tuning value required? */ 107 + da_war = xfi_tphy->da_war && (interface == PHY_INTERFACE_MODE_10GBASER); 108 + 109 + /* configure input mux to either 110 + * - USXGMII PCS (64b/66b coding) for 5G/10G 111 + * - LynxI PCS (8b/10b coding) for 1G/2.5G 112 + */ 113 + use_lynxi_pcs = is_1g || is_2p5g; 114 + 115 + dev_dbg(xfi_tphy->dev, "setting up for mode %s\n", phy_modes(interface)); 116 + 117 + /* Setup PLL setting */ 118 + mtk_phy_update_bits(xfi_tphy->base + 0x9024, 0x100000, is_10g ? 0x0 : 0x100000); 119 + mtk_phy_update_bits(xfi_tphy->base + 0x2020, 0x202000, is_5g ? 0x202000 : 0x0); 120 + mtk_phy_update_bits(xfi_tphy->base + 0x2030, 0x500, is_1g ? 0x0 : 0x500); 121 + mtk_phy_update_bits(xfi_tphy->base + 0x2034, 0xa00, is_1g ? 0x0 : 0xa00); 122 + mtk_phy_update_bits(xfi_tphy->base + 0x2040, 0x340000, is_1g ? 0x200000 : 0x140000); 123 + 124 + /* Setup RXFE BW setting */ 125 + mtk_phy_update_bits(xfi_tphy->base + 0x50f0, 0xc10, is_1g ? 0x410 : is_5g ? 0x800 : 0x400); 126 + mtk_phy_update_bits(xfi_tphy->base + 0x50e0, 0x4000, is_5g ? 0x0 : 0x4000); 127 + 128 + /* Setup RX CDR setting */ 129 + mtk_phy_update_bits(xfi_tphy->base + 0x506c, 0x30000, is_5g ? 0x0 : 0x30000); 130 + mtk_phy_update_bits(xfi_tphy->base + 0x5070, 0x670000, is_5g ? 0x620000 : 0x50000); 131 + mtk_phy_update_bits(xfi_tphy->base + 0x5074, 0x180000, is_5g ? 0x180000 : 0x0); 132 + mtk_phy_update_bits(xfi_tphy->base + 0x5078, 0xf000400, is_5g ? 0x8000000 : 133 + 0x7000400); 134 + mtk_phy_update_bits(xfi_tphy->base + 0x507c, 0x5000500, is_5g ? 0x4000400 : 135 + 0x1000100); 136 + mtk_phy_update_bits(xfi_tphy->base + 0x5080, 0x1410, is_1g ? 0x400 : is_5g ? 0x1010 : 0x0); 137 + mtk_phy_update_bits(xfi_tphy->base + 0x5084, 0x30300, is_1g ? 0x30300 : 138 + is_5g ? 0x30100 : 139 + 0x100); 140 + mtk_phy_update_bits(xfi_tphy->base + 0x5088, 0x60200, is_1g ? 0x20200 : 141 + is_5g ? 0x40000 : 142 + 0x20000); 143 + 144 + /* Setting RXFE adaptation range setting */ 145 + mtk_phy_update_bits(xfi_tphy->base + 0x50e4, 0xc0000, is_5g ? 0x0 : 0xc0000); 146 + mtk_phy_update_bits(xfi_tphy->base + 0x50e8, 0x40000, is_5g ? 0x0 : 0x40000); 147 + mtk_phy_update_bits(xfi_tphy->base + 0x50ec, 0xa00, is_1g ? 0x200 : 0x800); 148 + mtk_phy_update_bits(xfi_tphy->base + 0x50a8, 0xee0000, is_5g ? 0x800000 : 149 + 0x6e0000); 150 + mtk_phy_update_bits(xfi_tphy->base + 0x6004, 0x190000, is_5g ? 0x0 : 0x190000); 151 + 152 + if (is_10g) 153 + writel(0x01423342, xfi_tphy->base + 0x00f8); 154 + else if (is_5g) 155 + writel(0x00a132a1, xfi_tphy->base + 0x00f8); 156 + else if (is_2p5g) 157 + writel(0x009c329c, xfi_tphy->base + 0x00f8); 158 + else 159 + writel(0x00fa32fa, xfi_tphy->base + 0x00f8); 160 + 161 + /* Force SGDT_OUT off and select PCS */ 162 + mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_F4, 163 + XFI_DPHY_AD_SGDT_FRC_EN | XFI_DPHY_PCS_SEL, 164 + XFI_DPHY_AD_SGDT_FRC_EN | 165 + (use_lynxi_pcs ? XFI_DPHY_PCS_SEL_SGMII : 166 + XFI_DPHY_PCS_SEL_USXGMII)); 167 + 168 + /* Force GLB_CKDET_OUT */ 169 + mtk_phy_set_bits(xfi_tphy->base + 0x0030, 0xc00); 170 + 171 + /* Force AEQ on */ 172 + writel(XTP_PCS_RX_EQ_IN_PROGRESS(2) | XTP_PCS_PWD_SYNC(2) | XTP_PCS_PWD_ASYNC(2), 173 + xfi_tphy->base + REG_DIG_GLB_70); 174 + 175 + usleep_range(1, 5); 176 + writel(XTP_LN_FRC_TX_DATA_EN, xfi_tphy->base + REG_DIG_LN_TRX_40); 177 + 178 + /* Setup TX DA default value */ 179 + mtk_phy_update_bits(xfi_tphy->base + 0x30b0, 0x30, 0x20); 180 + writel(0x00008a01, xfi_tphy->base + 0x3028); 181 + writel(0x0000a884, xfi_tphy->base + 0x302c); 182 + writel(0x00083002, xfi_tphy->base + 0x3024); 183 + 184 + /* Setup RG default value */ 185 + if (use_lynxi_pcs) { 186 + writel(0x00011110, xfi_tphy->base + 0x3010); 187 + writel(0x40704000, xfi_tphy->base + 0x3048); 188 + } else { 189 + writel(0x00022220, xfi_tphy->base + 0x3010); 190 + writel(0x0f020a01, xfi_tphy->base + 0x5064); 191 + writel(0x06100600, xfi_tphy->base + 0x50b4); 192 + if (interface == PHY_INTERFACE_MODE_USXGMII) 193 + writel(0x40704000, xfi_tphy->base + 0x3048); 194 + else 195 + writel(0x47684100, xfi_tphy->base + 0x3048); 196 + } 197 + 198 + if (is_1g) 199 + writel(0x0000c000, xfi_tphy->base + 0x3064); 200 + 201 + /* Setup RX EQ initial value */ 202 + mtk_phy_update_bits(xfi_tphy->base + 0x3050, 0xa8000000, 203 + (interface != PHY_INTERFACE_MODE_10GBASER) ? 0xa8000000 : 0x0); 204 + mtk_phy_update_bits(xfi_tphy->base + 0x3054, 0xaa, 205 + (interface != PHY_INTERFACE_MODE_10GBASER) ? 0xaa : 0x0); 206 + 207 + if (!use_lynxi_pcs) 208 + writel(0x00000f00, xfi_tphy->base + 0x306c); 209 + else if (is_2p5g) 210 + writel(0x22000f00, xfi_tphy->base + 0x306c); 211 + else 212 + writel(0x20200f00, xfi_tphy->base + 0x306c); 213 + 214 + mtk_phy_update_bits(xfi_tphy->base + 0xa008, 0x10000, da_war ? 0x10000 : 0x0); 215 + 216 + mtk_phy_update_bits(xfi_tphy->base + 0xa060, 0x50000, use_lynxi_pcs ? 0x50000 : 0x40000); 217 + 218 + /* Setup PHYA speed */ 219 + mtk_phy_update_bits(xfi_tphy->base + REG_ANA_GLB_D0, 220 + XTP_GLB_USXGMII_SEL_MASK | XTP_GLB_USXGMII_EN, 221 + is_10g ? XTP_GLB_USXGMII_SEL(0) : 222 + is_5g ? XTP_GLB_USXGMII_SEL(1) : 223 + is_2p5g ? XTP_GLB_USXGMII_SEL(2) : 224 + XTP_GLB_USXGMII_SEL(3)); 225 + mtk_phy_set_bits(xfi_tphy->base + REG_ANA_GLB_D0, XTP_GLB_USXGMII_EN); 226 + 227 + /* Release reset */ 228 + mtk_phy_set_bits(xfi_tphy->base + REG_DIG_GLB_70, 229 + XTP_PCS_RST_B | XTP_FRC_PCS_RST_B); 230 + usleep_range(150, 500); 231 + 232 + /* Switch to P0 */ 233 + mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_70, 234 + XTP_PCS_IN_FR_RG | 235 + XTP_FRC_PCS_PWD_ASYNC | 236 + XTP_PCS_PWD_ASYNC_MASK | 237 + XTP_PCS_PWD_SYNC_MASK | 238 + XTP_PCS_UPDT, 239 + XTP_PCS_IN_FR_RG | 240 + XTP_FRC_PCS_PWD_ASYNC | 241 + XTP_PCS_UPDT); 242 + usleep_range(1, 5); 243 + 244 + mtk_phy_clear_bits(xfi_tphy->base + REG_DIG_GLB_70, XTP_PCS_UPDT); 245 + usleep_range(15, 50); 246 + 247 + if (use_lynxi_pcs) { 248 + /* Switch to Gen2 */ 249 + mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_70, 250 + XTP_PCS_MODE_MASK | XTP_PCS_UPDT, 251 + XTP_PCS_MODE(1) | XTP_PCS_UPDT); 252 + } else { 253 + /* Switch to Gen3 */ 254 + mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_70, 255 + XTP_PCS_MODE_MASK | XTP_PCS_UPDT, 256 + XTP_PCS_MODE(2) | XTP_PCS_UPDT); 257 + } 258 + usleep_range(1, 5); 259 + 260 + mtk_phy_clear_bits(xfi_tphy->base + REG_DIG_GLB_70, XTP_PCS_UPDT); 261 + 262 + usleep_range(100, 500); 263 + 264 + /* Enable MAC CK */ 265 + mtk_phy_set_bits(xfi_tphy->base + REG_DIG_LN_TRX_B0, XTP_LN_TX_MACCK_EN); 266 + mtk_phy_clear_bits(xfi_tphy->base + REG_DIG_GLB_F4, XFI_DPHY_AD_SGDT_FRC_EN); 267 + 268 + /* Enable TX data */ 269 + mtk_phy_set_bits(xfi_tphy->base + REG_DIG_LN_TRX_40, 270 + XTP_LN_FRC_TX_DATA_EN | XTP_LN_TX_DATA_EN); 271 + usleep_range(400, 1000); 272 + } 273 + 274 + /** 275 + * mtk_xfi_tphy_set_mode() - Setup phy for specified interface mode. 276 + * 277 + * @phy: Phy instance. 278 + * @mode: Only PHY_MODE_ETHERNET is supported. 279 + * @submode: An Ethernet interface mode. 280 + * 281 + * Validate selected mode and call function mtk_xfi_tphy_setup(). 282 + * 283 + * Return: 284 + * * %0 - OK 285 + * * %-EINVAL - invalid mode 286 + */ 287 + static int mtk_xfi_tphy_set_mode(struct phy *phy, enum phy_mode mode, int 288 + submode) 289 + { 290 + struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); 291 + 292 + if (mode != PHY_MODE_ETHERNET) 293 + return -EINVAL; 294 + 295 + switch (submode) { 296 + case PHY_INTERFACE_MODE_1000BASEX: 297 + case PHY_INTERFACE_MODE_2500BASEX: 298 + case PHY_INTERFACE_MODE_SGMII: 299 + case PHY_INTERFACE_MODE_5GBASER: 300 + case PHY_INTERFACE_MODE_10GBASER: 301 + case PHY_INTERFACE_MODE_USXGMII: 302 + mtk_xfi_tphy_setup(xfi_tphy, submode); 303 + return 0; 304 + default: 305 + return -EINVAL; 306 + } 307 + } 308 + 309 + /** 310 + * mtk_xfi_tphy_reset() - Reset the phy. 311 + * 312 + * @phy: Phy instance. 313 + * 314 + * Reset the phy using the external reset controller. 315 + * 316 + * Return: 317 + * %0 - OK 318 + */ 319 + static int mtk_xfi_tphy_reset(struct phy *phy) 320 + { 321 + struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); 322 + 323 + reset_control_assert(xfi_tphy->reset); 324 + usleep_range(100, 500); 325 + reset_control_deassert(xfi_tphy->reset); 326 + usleep_range(1, 10); 327 + 328 + return 0; 329 + } 330 + 331 + /** 332 + * mtk_xfi_tphy_power_on() - Power-on the phy. 333 + * 334 + * @phy: Phy instance. 335 + * 336 + * Prepare and enable all clocks required for the phy to operate. 337 + * 338 + * Return: 339 + * See clk_bulk_prepare_enable(). 340 + */ 341 + static int mtk_xfi_tphy_power_on(struct phy *phy) 342 + { 343 + struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); 344 + 345 + return clk_bulk_prepare_enable(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks); 346 + } 347 + 348 + /** 349 + * mtk_xfi_tphy_power_off() - Power-off the phy. 350 + * 351 + * @phy: Phy instance. 352 + * 353 + * Disable and unprepare all clocks previously enabled. 354 + * 355 + * Return: 356 + * See clk_bulk_prepare_disable(). 357 + */ 358 + static int mtk_xfi_tphy_power_off(struct phy *phy) 359 + { 360 + struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); 361 + 362 + clk_bulk_disable_unprepare(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks); 363 + 364 + return 0; 365 + } 366 + 367 + static const struct phy_ops mtk_xfi_tphy_ops = { 368 + .power_on = mtk_xfi_tphy_power_on, 369 + .power_off = mtk_xfi_tphy_power_off, 370 + .set_mode = mtk_xfi_tphy_set_mode, 371 + .reset = mtk_xfi_tphy_reset, 372 + .owner = THIS_MODULE, 373 + }; 374 + 375 + /** 376 + * mtk_xfi_tphy_probe() - Probe phy instance from Device Tree. 377 + * @pdev: Matching platform device. 378 + * 379 + * The probe function gets IO resource, clocks, reset controller and 380 + * whether the DA work-around for 10GBase-R is required from Device Tree and 381 + * allocates memory for holding that information in a struct mtk_xfi_tphy. 382 + * 383 + * Return: 384 + * * %0 - OK 385 + * * %-ENODEV - Missing associated Device Tree node (should never happen). 386 + * * %-ENOMEM - Out of memory. 387 + * * Any error value which devm_platform_ioremap_resource(), 388 + * devm_clk_bulk_get(), devm_reset_control_get_exclusive(), 389 + * devm_phy_create() or devm_of_phy_provider_register() may return. 390 + */ 391 + static int mtk_xfi_tphy_probe(struct platform_device *pdev) 392 + { 393 + struct device_node *np = pdev->dev.of_node; 394 + struct phy_provider *phy_provider; 395 + struct mtk_xfi_tphy *xfi_tphy; 396 + struct phy *phy; 397 + int ret; 398 + 399 + if (!np) 400 + return -ENODEV; 401 + 402 + xfi_tphy = devm_kzalloc(&pdev->dev, sizeof(*xfi_tphy), GFP_KERNEL); 403 + if (!xfi_tphy) 404 + return -ENOMEM; 405 + 406 + xfi_tphy->base = devm_platform_ioremap_resource(pdev, 0); 407 + if (IS_ERR(xfi_tphy->base)) 408 + return PTR_ERR(xfi_tphy->base); 409 + 410 + xfi_tphy->dev = &pdev->dev; 411 + xfi_tphy->clocks[0].id = "topxtal"; 412 + xfi_tphy->clocks[1].id = "xfipll"; 413 + ret = devm_clk_bulk_get(&pdev->dev, MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks); 414 + if (ret) 415 + return ret; 416 + 417 + xfi_tphy->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); 418 + if (IS_ERR(xfi_tphy->reset)) 419 + return PTR_ERR(xfi_tphy->reset); 420 + 421 + xfi_tphy->da_war = of_property_read_bool(np, "mediatek,usxgmii-performance-errata"); 422 + 423 + phy = devm_phy_create(&pdev->dev, NULL, &mtk_xfi_tphy_ops); 424 + if (IS_ERR(phy)) 425 + return PTR_ERR(phy); 426 + 427 + phy_set_drvdata(phy, xfi_tphy); 428 + phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); 429 + 430 + return PTR_ERR_OR_ZERO(phy_provider); 431 + } 432 + 433 + static const struct of_device_id mtk_xfi_tphy_match[] = { 434 + { .compatible = "mediatek,mt7988-xfi-tphy", }, 435 + { /* sentinel */ } 436 + }; 437 + MODULE_DEVICE_TABLE(of, mtk_xfi_tphy_match); 438 + 439 + static struct platform_driver mtk_xfi_tphy_driver = { 440 + .probe = mtk_xfi_tphy_probe, 441 + .driver = { 442 + .name = "mtk-xfi-tphy", 443 + .of_match_table = mtk_xfi_tphy_match, 444 + }, 445 + }; 446 + module_platform_driver(mtk_xfi_tphy_driver); 447 + 448 + MODULE_DESCRIPTION("MediaTek 10GE SerDes XFI T-PHY driver"); 449 + MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>"); 450 + MODULE_AUTHOR("Bc-bocun Chen <bc-bocun.chen@mediatek.com>"); 451 + MODULE_LICENSE("GPL");
+15 -11
drivers/phy/phy-core.c
··· 20 20 #include <linux/pm_runtime.h> 21 21 #include <linux/regulator/consumer.h> 22 22 23 - static struct class *phy_class; 23 + static void phy_release(struct device *dev); 24 + static const struct class phy_class = { 25 + .name = "phy", 26 + .dev_release = phy_release, 27 + }; 28 + 24 29 static struct dentry *phy_debugfs_root; 25 30 static DEFINE_MUTEX(phy_provider_mutex); 26 31 static LIST_HEAD(phy_provider_list); ··· 758 753 struct phy *phy; 759 754 struct class_dev_iter iter; 760 755 761 - class_dev_iter_init(&iter, phy_class, NULL, NULL); 756 + class_dev_iter_init(&iter, &phy_class, NULL, NULL); 762 757 while ((dev = class_dev_iter_next(&iter))) { 763 758 phy = to_phy(dev); 764 759 if (args->np != phy->dev.of_node) ··· 1021 1016 device_initialize(&phy->dev); 1022 1017 mutex_init(&phy->mutex); 1023 1018 1024 - phy->dev.class = phy_class; 1019 + phy->dev.class = &phy_class; 1025 1020 phy->dev.parent = dev; 1026 1021 phy->dev.of_node = node ?: dev->of_node; 1027 1022 phy->id = id; ··· 1290 1285 1291 1286 static int __init phy_core_init(void) 1292 1287 { 1293 - phy_class = class_create("phy"); 1294 - if (IS_ERR(phy_class)) { 1295 - pr_err("failed to create phy class --> %ld\n", 1296 - PTR_ERR(phy_class)); 1297 - return PTR_ERR(phy_class); 1298 - } 1288 + int err; 1299 1289 1300 - phy_class->dev_release = phy_release; 1290 + err = class_register(&phy_class); 1291 + if (err) { 1292 + pr_err("failed to register phy class"); 1293 + return err; 1294 + } 1301 1295 1302 1296 phy_debugfs_root = debugfs_create_dir("phy", NULL); 1303 1297 ··· 1307 1303 static void __exit phy_core_exit(void) 1308 1304 { 1309 1305 debugfs_remove_recursive(phy_debugfs_root); 1310 - class_destroy(phy_class); 1306 + class_unregister(&phy_class); 1311 1307 } 1312 1308 module_exit(phy_core_exit);
+301 -68
drivers/phy/qualcomm/phy-qcom-edp.c
··· 24 24 25 25 #include "phy-qcom-qmp-dp-phy.h" 26 26 #include "phy-qcom-qmp-qserdes-com-v4.h" 27 + #include "phy-qcom-qmp-qserdes-com-v6.h" 27 28 28 29 /* EDP_PHY registers */ 29 30 #define DP_PHY_CFG 0x0010 ··· 78 77 const u8 (*pre_emphasis_hbr3_hbr2)[4][4]; 79 78 }; 80 79 80 + struct qcom_edp; 81 + 82 + struct phy_ver_ops { 83 + int (*com_power_on)(const struct qcom_edp *edp); 84 + int (*com_resetsm_cntrl)(const struct qcom_edp *edp); 85 + int (*com_bias_en_clkbuflr)(const struct qcom_edp *edp); 86 + int (*com_configure_pll)(const struct qcom_edp *edp); 87 + int (*com_configure_ssc)(const struct qcom_edp *edp); 88 + }; 89 + 81 90 struct qcom_edp_phy_cfg { 82 91 bool is_edp; 83 92 const struct qcom_edp_swing_pre_emph_cfg *swing_pre_emph_cfg; 93 + const struct phy_ver_ops *ver_ops; 84 94 }; 85 95 86 96 struct qcom_edp { ··· 186 174 .pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3, 187 175 }; 188 176 189 - static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = { 190 - }; 191 - 192 - static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = { 193 - .swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg, 194 - }; 195 - 196 - static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = { 197 - .is_edp = true, 198 - .swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg, 199 - }; 200 - 201 177 static int qcom_edp_phy_init(struct phy *phy) 202 178 { 203 179 struct qcom_edp *edp = phy_get_drvdata(phy); ··· 204 204 DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, 205 205 edp->edp + DP_PHY_PD_CTL); 206 206 207 - /* Turn on BIAS current for PHY/PLL */ 208 - writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN); 207 + ret = edp->cfg->ver_ops->com_bias_en_clkbuflr(edp); 208 + if (ret) 209 + return ret; 209 210 210 211 writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL); 211 212 msleep(20); ··· 314 313 315 314 static int qcom_edp_configure_ssc(const struct qcom_edp *edp) 316 315 { 316 + return edp->cfg->ver_ops->com_configure_ssc(edp); 317 + } 318 + 319 + static int qcom_edp_configure_pll(const struct qcom_edp *edp) 320 + { 321 + return edp->cfg->ver_ops->com_configure_pll(edp); 322 + } 323 + 324 + static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel_freq) 325 + { 326 + const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts; 327 + u32 vco_div; 328 + 329 + switch (dp_opts->link_rate) { 330 + case 1620: 331 + vco_div = 0x1; 332 + *pixel_freq = 1620000000UL / 2; 333 + break; 334 + 335 + case 2700: 336 + vco_div = 0x1; 337 + *pixel_freq = 2700000000UL / 2; 338 + break; 339 + 340 + case 5400: 341 + vco_div = 0x2; 342 + *pixel_freq = 5400000000UL / 4; 343 + break; 344 + 345 + case 8100: 346 + vco_div = 0x0; 347 + *pixel_freq = 8100000000UL / 6; 348 + break; 349 + 350 + default: 351 + /* Other link rates aren't supported */ 352 + return -EINVAL; 353 + } 354 + 355 + writel(vco_div, edp->edp + DP_PHY_VCO_DIV); 356 + 357 + return 0; 358 + } 359 + 360 + static int qcom_edp_phy_power_on_v4(const struct qcom_edp *edp) 361 + { 362 + u32 val; 363 + 364 + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | 365 + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | 366 + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, 367 + edp->edp + DP_PHY_PD_CTL); 368 + writel(0xfc, edp->edp + DP_PHY_MODE); 369 + 370 + return readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS, 371 + val, val & BIT(7), 5, 200); 372 + } 373 + 374 + static int qcom_edp_phy_com_resetsm_cntrl_v4(const struct qcom_edp *edp) 375 + { 376 + u32 val; 377 + 378 + writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL); 379 + 380 + return readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS, 381 + val, val & BIT(0), 500, 10000); 382 + } 383 + 384 + static int qcom_edp_com_bias_en_clkbuflr_v4(const struct qcom_edp *edp) 385 + { 386 + /* Turn on BIAS current for PHY/PLL */ 387 + writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN); 388 + 389 + return 0; 390 + } 391 + 392 + static int qcom_edp_com_configure_ssc_v4(const struct qcom_edp *edp) 393 + { 317 394 const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts; 318 395 u32 step1; 319 396 u32 step2; ··· 424 345 return 0; 425 346 } 426 347 427 - static int qcom_edp_configure_pll(const struct qcom_edp *edp) 348 + static int qcom_edp_com_configure_pll_v4(const struct qcom_edp *edp) 428 349 { 429 350 const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts; 430 351 u32 div_frac_start2_mode0; ··· 510 431 return 0; 511 432 } 512 433 513 - static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel_freq) 434 + static const struct phy_ver_ops qcom_edp_phy_ops_v4 = { 435 + .com_power_on = qcom_edp_phy_power_on_v4, 436 + .com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v4, 437 + .com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v4, 438 + .com_configure_pll = qcom_edp_com_configure_pll_v4, 439 + .com_configure_ssc = qcom_edp_com_configure_ssc_v4, 440 + }; 441 + 442 + static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = { 443 + .ver_ops = &qcom_edp_phy_ops_v4, 444 + }; 445 + 446 + static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = { 447 + .swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg, 448 + .ver_ops = &qcom_edp_phy_ops_v4, 449 + }; 450 + 451 + static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = { 452 + .is_edp = true, 453 + .swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg, 454 + .ver_ops = &qcom_edp_phy_ops_v4, 455 + }; 456 + 457 + static int qcom_edp_phy_power_on_v6(const struct qcom_edp *edp) 514 458 { 515 - const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts; 516 - u32 vco_div; 517 - 518 - switch (dp_opts->link_rate) { 519 - case 1620: 520 - vco_div = 0x1; 521 - *pixel_freq = 1620000000UL / 2; 522 - break; 523 - 524 - case 2700: 525 - vco_div = 0x1; 526 - *pixel_freq = 2700000000UL / 2; 527 - break; 528 - 529 - case 5400: 530 - vco_div = 0x2; 531 - *pixel_freq = 5400000000UL / 4; 532 - break; 533 - 534 - case 8100: 535 - vco_div = 0x0; 536 - *pixel_freq = 8100000000UL / 6; 537 - break; 538 - 539 - default: 540 - /* Other link rates aren't supported */ 541 - return -EINVAL; 542 - } 543 - 544 - writel(vco_div, edp->edp + DP_PHY_VCO_DIV); 545 - 546 - return 0; 547 - } 548 - 549 - static int qcom_edp_phy_power_on(struct phy *phy) 550 - { 551 - const struct qcom_edp *edp = phy_get_drvdata(phy); 552 - u32 bias0_en, drvr0_en, bias1_en, drvr1_en; 553 - unsigned long pixel_freq; 554 - u8 ldo_config = 0x0; 555 - int timeout; 556 - int ret; 557 459 u32 val; 558 - u8 cfg1; 559 460 560 461 writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | 561 462 DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | ··· 543 484 edp->edp + DP_PHY_PD_CTL); 544 485 writel(0xfc, edp->edp + DP_PHY_MODE); 545 486 546 - timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS, 487 + return readl_poll_timeout(edp->pll + QSERDES_V6_COM_CMN_STATUS, 547 488 val, val & BIT(7), 5, 200); 548 - if (timeout) 549 - return timeout; 489 + } 550 490 491 + static int qcom_edp_phy_com_resetsm_cntrl_v6(const struct qcom_edp *edp) 492 + { 493 + u32 val; 494 + 495 + writel(0x20, edp->pll + QSERDES_V6_COM_RESETSM_CNTRL); 496 + 497 + return readl_poll_timeout(edp->pll + QSERDES_V6_COM_C_READY_STATUS, 498 + val, val & BIT(0), 500, 10000); 499 + } 500 + 501 + static int qcom_edp_com_bias_en_clkbuflr_v6(const struct qcom_edp *edp) 502 + { 503 + /* Turn on BIAS current for PHY/PLL */ 504 + writel(0x1f, edp->pll + QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN); 505 + 506 + return 0; 507 + } 508 + 509 + static int qcom_edp_com_configure_ssc_v6(const struct qcom_edp *edp) 510 + { 511 + const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts; 512 + u32 step1; 513 + u32 step2; 514 + 515 + switch (dp_opts->link_rate) { 516 + case 1620: 517 + case 2700: 518 + case 8100: 519 + step1 = 0x92; 520 + step2 = 0x01; 521 + break; 522 + 523 + case 5400: 524 + step1 = 0x18; 525 + step2 = 0x02; 526 + break; 527 + 528 + default: 529 + /* Other link rates aren't supported */ 530 + return -EINVAL; 531 + } 532 + 533 + writel(0x01, edp->pll + QSERDES_V6_COM_SSC_EN_CENTER); 534 + writel(0x00, edp->pll + QSERDES_V6_COM_SSC_ADJ_PER1); 535 + writel(0x36, edp->pll + QSERDES_V6_COM_SSC_PER1); 536 + writel(0x01, edp->pll + QSERDES_V6_COM_SSC_PER2); 537 + writel(step1, edp->pll + QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0); 538 + writel(step2, edp->pll + QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0); 539 + 540 + return 0; 541 + } 542 + 543 + static int qcom_edp_com_configure_pll_v6(const struct qcom_edp *edp) 544 + { 545 + const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts; 546 + u32 div_frac_start2_mode0; 547 + u32 div_frac_start3_mode0; 548 + u32 dec_start_mode0; 549 + u32 lock_cmp1_mode0; 550 + u32 lock_cmp2_mode0; 551 + u32 code1_mode0; 552 + u32 code2_mode0; 553 + u32 hsclk_sel; 554 + 555 + switch (dp_opts->link_rate) { 556 + case 1620: 557 + hsclk_sel = 0x5; 558 + dec_start_mode0 = 0x34; 559 + div_frac_start2_mode0 = 0xc0; 560 + div_frac_start3_mode0 = 0x0b; 561 + lock_cmp1_mode0 = 0x37; 562 + lock_cmp2_mode0 = 0x04; 563 + code1_mode0 = 0x71; 564 + code2_mode0 = 0x0c; 565 + break; 566 + 567 + case 2700: 568 + hsclk_sel = 0x3; 569 + dec_start_mode0 = 0x34; 570 + div_frac_start2_mode0 = 0xc0; 571 + div_frac_start3_mode0 = 0x0b; 572 + lock_cmp1_mode0 = 0x07; 573 + lock_cmp2_mode0 = 0x07; 574 + code1_mode0 = 0x71; 575 + code2_mode0 = 0x0c; 576 + break; 577 + 578 + case 5400: 579 + hsclk_sel = 0x1; 580 + dec_start_mode0 = 0x46; 581 + div_frac_start2_mode0 = 0x00; 582 + div_frac_start3_mode0 = 0x05; 583 + lock_cmp1_mode0 = 0x0f; 584 + lock_cmp2_mode0 = 0x0e; 585 + code1_mode0 = 0x97; 586 + code2_mode0 = 0x10; 587 + break; 588 + 589 + case 8100: 590 + hsclk_sel = 0x0; 591 + dec_start_mode0 = 0x34; 592 + div_frac_start2_mode0 = 0xc0; 593 + div_frac_start3_mode0 = 0x0b; 594 + lock_cmp1_mode0 = 0x17; 595 + lock_cmp2_mode0 = 0x15; 596 + code1_mode0 = 0x71; 597 + code2_mode0 = 0x0c; 598 + break; 599 + 600 + default: 601 + /* Other link rates aren't supported */ 602 + return -EINVAL; 603 + } 604 + 605 + writel(0x01, edp->pll + QSERDES_V6_COM_SVS_MODE_CLK_SEL); 606 + writel(0x0b, edp->pll + QSERDES_V6_COM_SYSCLK_EN_SEL); 607 + writel(0x02, edp->pll + QSERDES_V6_COM_SYS_CLK_CTRL); 608 + writel(0x0c, edp->pll + QSERDES_V6_COM_CLK_ENABLE1); 609 + writel(0x06, edp->pll + QSERDES_V6_COM_SYSCLK_BUF_ENABLE); 610 + writel(0x30, edp->pll + QSERDES_V6_COM_CLK_SELECT); 611 + writel(hsclk_sel, edp->pll + QSERDES_V6_COM_HSCLK_SEL_1); 612 + writel(0x07, edp->pll + QSERDES_V6_COM_PLL_IVCO); 613 + writel(0x08, edp->pll + QSERDES_V6_COM_LOCK_CMP_EN); 614 + writel(0x36, edp->pll + QSERDES_V6_COM_PLL_CCTRL_MODE0); 615 + writel(0x16, edp->pll + QSERDES_V6_COM_PLL_RCTRL_MODE0); 616 + writel(0x06, edp->pll + QSERDES_V6_COM_CP_CTRL_MODE0); 617 + writel(dec_start_mode0, edp->pll + QSERDES_V6_COM_DEC_START_MODE0); 618 + writel(0x00, edp->pll + QSERDES_V6_COM_DIV_FRAC_START1_MODE0); 619 + writel(div_frac_start2_mode0, edp->pll + QSERDES_V6_COM_DIV_FRAC_START2_MODE0); 620 + writel(div_frac_start3_mode0, edp->pll + QSERDES_V6_COM_DIV_FRAC_START3_MODE0); 621 + writel(0x12, edp->pll + QSERDES_V6_COM_CMN_CONFIG_1); 622 + writel(0x3f, edp->pll + QSERDES_V6_COM_INTEGLOOP_GAIN0_MODE0); 623 + writel(0x00, edp->pll + QSERDES_V6_COM_INTEGLOOP_GAIN1_MODE0); 624 + writel(0x00, edp->pll + QSERDES_V6_COM_VCO_TUNE_MAP); 625 + writel(lock_cmp1_mode0, edp->pll + QSERDES_V6_COM_LOCK_CMP1_MODE0); 626 + writel(lock_cmp2_mode0, edp->pll + QSERDES_V6_COM_LOCK_CMP2_MODE0); 627 + 628 + writel(0x0a, edp->pll + QSERDES_V6_COM_BG_TIMER); 629 + writel(0x14, edp->pll + QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0); 630 + writel(0x00, edp->pll + QSERDES_V6_COM_VCO_TUNE_CTRL); 631 + writel(0x1f, edp->pll + QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN); 632 + writel(0x0f, edp->pll + QSERDES_V6_COM_CORE_CLK_EN); 633 + writel(0xa0, edp->pll + QSERDES_V6_COM_VCO_TUNE1_MODE0); 634 + writel(0x03, edp->pll + QSERDES_V6_COM_VCO_TUNE2_MODE0); 635 + 636 + writel(code1_mode0, edp->pll + QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0); 637 + writel(code2_mode0, edp->pll + QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0); 638 + 639 + return 0; 640 + } 641 + 642 + static const struct phy_ver_ops qcom_edp_phy_ops_v6 = { 643 + .com_power_on = qcom_edp_phy_power_on_v6, 644 + .com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v6, 645 + .com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v6, 646 + .com_configure_pll = qcom_edp_com_configure_pll_v6, 647 + .com_configure_ssc = qcom_edp_com_configure_ssc_v6, 648 + }; 649 + 650 + static struct qcom_edp_phy_cfg x1e80100_phy_cfg = { 651 + .swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg, 652 + .ver_ops = &qcom_edp_phy_ops_v6, 653 + }; 654 + 655 + static int qcom_edp_phy_power_on(struct phy *phy) 656 + { 657 + const struct qcom_edp *edp = phy_get_drvdata(phy); 658 + u32 bias0_en, drvr0_en, bias1_en, drvr1_en; 659 + unsigned long pixel_freq; 660 + u8 ldo_config = 0x0; 661 + int ret; 662 + u32 val; 663 + u8 cfg1; 664 + 665 + ret = edp->cfg->ver_ops->com_power_on(edp); 666 + if (ret) 667 + return ret; 551 668 552 669 if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp) 553 670 ldo_config = 0x1; ··· 770 535 writel(0x01, edp->edp + DP_PHY_CFG); 771 536 writel(0x09, edp->edp + DP_PHY_CFG); 772 537 773 - writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL); 774 - 775 - timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS, 776 - val, val & BIT(0), 500, 10000); 777 - if (timeout) 778 - return timeout; 538 + ret = edp->cfg->ver_ops->com_resetsm_cntrl(edp); 539 + if (ret) 540 + return ret; 779 541 780 542 writel(0x19, edp->edp + DP_PHY_CFG); 781 543 writel(0x1f, edp->tx0 + TXn_HIGHZ_DRVR_EN); ··· 1112 880 { .compatible = "qcom,sc8180x-edp-phy", .data = &sc7280_dp_phy_cfg, }, 1113 881 { .compatible = "qcom,sc8280xp-dp-phy", .data = &sc8280xp_dp_phy_cfg, }, 1114 882 { .compatible = "qcom,sc8280xp-edp-phy", .data = &sc8280xp_edp_phy_cfg, }, 883 + { .compatible = "qcom,x1e80100-dp-phy", .data = &x1e80100_phy_cfg, }, 1115 884 { } 1116 885 }; 1117 886 MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table);
+17
drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
··· 88 88 [TUNE_USB2_PREEM] = 0x5, 89 89 }; 90 90 91 + static const u32 smb2360_init_tbl[NUM_TUNE_FIELDS] = { 92 + [TUNE_IUSB2] = 0x5, 93 + [TUNE_SQUELCH_U] = 0x3, 94 + [TUNE_USB2_PREEM] = 0x2, 95 + }; 96 + 91 97 static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = { 92 98 .init_tbl = pm8550b_init_tbl, 93 99 .init_tbl_num = ARRAY_SIZE(pm8550b_init_tbl), 100 + .vreg_list = pm8550b_vreg_l, 101 + .num_vregs = ARRAY_SIZE(pm8550b_vreg_l), 102 + }; 103 + 104 + static const struct eusb2_repeater_cfg smb2360_eusb2_cfg = { 105 + .init_tbl = smb2360_init_tbl, 106 + .init_tbl_num = ARRAY_SIZE(smb2360_init_tbl), 94 107 .vreg_list = pm8550b_vreg_l, 95 108 .num_vregs = ARRAY_SIZE(pm8550b_vreg_l), 96 109 }; ··· 283 270 { 284 271 .compatible = "qcom,pm8550b-eusb2-repeater", 285 272 .data = &pm8550b_eusb2_cfg, 273 + }, 274 + { 275 + .compatible = "qcom,smb2360-eusb2-repeater", 276 + .data = &smb2360_eusb2_cfg, 286 277 }, 287 278 { }, 288 279 };
+53 -3
drivers/phy/qualcomm/phy-qcom-qmp-combo.c
··· 1382 1382 { 0x3f, 0xff, 0xff, 0xff } 1383 1383 }; 1384 1384 1385 + static const u8 qmp_dp_v6_voltage_swing_hbr_rbr[4][4] = { 1386 + { 0x27, 0x2f, 0x36, 0x3f }, 1387 + { 0x31, 0x3e, 0x3f, 0xff }, 1388 + { 0x36, 0x3f, 0xff, 0xff }, 1389 + { 0x3f, 0xff, 0xff, 0xff } 1390 + }; 1391 + 1385 1392 static const u8 qmp_dp_v6_pre_emphasis_hbr_rbr[4][4] = { 1386 1393 { 0x20, 0x2d, 0x34, 0x3a }, 1387 1394 { 0x20, 0x2e, 0x35, 0xff }, ··· 2008 2001 .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 2009 2002 }; 2010 2003 2004 + static const struct qmp_phy_cfg sm8650_usb3dpphy_cfg = { 2005 + .offsets = &qmp_combo_offsets_v3, 2006 + 2007 + .serdes_tbl = sm8550_usb3_serdes_tbl, 2008 + .serdes_tbl_num = ARRAY_SIZE(sm8550_usb3_serdes_tbl), 2009 + .tx_tbl = sm8550_usb3_tx_tbl, 2010 + .tx_tbl_num = ARRAY_SIZE(sm8550_usb3_tx_tbl), 2011 + .rx_tbl = sm8550_usb3_rx_tbl, 2012 + .rx_tbl_num = ARRAY_SIZE(sm8550_usb3_rx_tbl), 2013 + .pcs_tbl = sm8550_usb3_pcs_tbl, 2014 + .pcs_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_tbl), 2015 + .pcs_usb_tbl = sm8550_usb3_pcs_usb_tbl, 2016 + .pcs_usb_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_usb_tbl), 2017 + 2018 + .dp_serdes_tbl = qmp_v6_dp_serdes_tbl, 2019 + .dp_serdes_tbl_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl), 2020 + .dp_tx_tbl = qmp_v6_dp_tx_tbl, 2021 + .dp_tx_tbl_num = ARRAY_SIZE(qmp_v6_dp_tx_tbl), 2022 + 2023 + .serdes_tbl_rbr = qmp_v6_dp_serdes_tbl_rbr, 2024 + .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_rbr), 2025 + .serdes_tbl_hbr = qmp_v6_dp_serdes_tbl_hbr, 2026 + .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr), 2027 + .serdes_tbl_hbr2 = qmp_v6_dp_serdes_tbl_hbr2, 2028 + .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr2), 2029 + .serdes_tbl_hbr3 = qmp_v6_dp_serdes_tbl_hbr3, 2030 + .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr3), 2031 + 2032 + .swing_hbr_rbr = &qmp_dp_v6_voltage_swing_hbr_rbr, 2033 + .pre_emphasis_hbr_rbr = &qmp_dp_v6_pre_emphasis_hbr_rbr, 2034 + .swing_hbr3_hbr2 = &qmp_dp_v5_voltage_swing_hbr3_hbr2, 2035 + .pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2, 2036 + 2037 + .dp_aux_init = qmp_v4_dp_aux_init, 2038 + .configure_dp_tx = qmp_v4_configure_dp_tx, 2039 + .configure_dp_phy = qmp_v4_configure_dp_phy, 2040 + .calibrate_dp_phy = qmp_v4_calibrate_dp_phy, 2041 + 2042 + .regs = qmp_v6_usb3phy_regs_layout, 2043 + .reset_list = msm8996_usb3phy_reset_l, 2044 + .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), 2045 + .vreg_list = qmp_phy_vreg_l, 2046 + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 2047 + }; 2048 + 2011 2049 static int qmp_combo_dp_serdes_init(struct qmp_combo *qmp) 2012 2050 { 2013 2051 const struct qmp_phy_cfg *cfg = qmp->cfg; ··· 2487 2435 2488 2436 writel(0x20, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); 2489 2437 writel(0x20, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); 2490 - 2491 - return 0; 2492 2438 2493 2439 return 0; 2494 2440 } ··· 3681 3631 }, 3682 3632 { 3683 3633 .compatible = "qcom,sm8650-qmp-usb3-dp-phy", 3684 - .data = &sm8550_usb3dpphy_cfg, 3634 + .data = &sm8650_usb3dpphy_cfg, 3685 3635 }, 3686 3636 { 3687 3637 .compatible = "qcom,x1e80100-qmp-usb3-dp-phy",
+102 -7
drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
··· 22 22 #include <linux/reset.h> 23 23 #include <linux/slab.h> 24 24 25 + #include <dt-bindings/phy/phy-qcom-qmp.h> 26 + 25 27 #include "phy-qcom-qmp-common.h" 26 28 27 29 #include "phy-qcom-qmp.h" ··· 2248 2246 }; 2249 2247 2250 2248 static const struct qmp_phy_init_tbl sa8775p_qmp_gen4x4_pcie_serdes_alt_tbl[] = { 2249 + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), 2251 2250 QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), 2252 2251 QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), 2253 2252 QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ··· 2275 2272 QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), 2276 2273 QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x97), 2277 2274 QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x0c), 2278 - QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), 2279 2275 QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), 2280 2276 QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), 2281 2277 QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ··· 2391 2389 2392 2390 /* QMP PHY pipe clock interface rate */ 2393 2391 unsigned long pipe_clock_rate; 2392 + 2393 + /* QMP PHY AUX clock interface rate */ 2394 + unsigned long aux_clock_rate; 2394 2395 }; 2395 2396 2396 2397 struct qmp_pcie { ··· 2425 2420 int mode; 2426 2421 2427 2422 struct clk_fixed_rate pipe_clk_fixed; 2423 + struct clk_fixed_rate aux_clk_fixed; 2428 2424 }; 2429 2425 2430 2426 static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) ··· 3141 3135 3142 3136 .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, 3143 3137 .phy_status = PHYSTATUS_4_20, 3138 + 3139 + /* 20MHz PHY AUX Clock */ 3140 + .aux_clock_rate = 20000000, 3144 3141 }; 3145 3142 3146 3143 static const struct qmp_phy_cfg sm8550_qmp_gen3x2_pciephy_cfg = { ··· 3201 3192 .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, 3202 3193 .phy_status = PHYSTATUS_4_20, 3203 3194 .has_nocsr_reset = true, 3195 + 3196 + /* 20MHz PHY AUX Clock */ 3197 + .aux_clock_rate = 20000000, 3204 3198 }; 3205 3199 3206 3200 static const struct qmp_phy_cfg sm8650_qmp_gen4x2_pciephy_cfg = { ··· 3234 3222 .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, 3235 3223 .phy_status = PHYSTATUS_4_20, 3236 3224 .has_nocsr_reset = true, 3225 + 3226 + /* 20MHz PHY AUX Clock */ 3227 + .aux_clock_rate = 20000000, 3237 3228 }; 3238 3229 3239 3230 static const struct qmp_phy_cfg sa8775p_qmp_gen4x2_pciephy_cfg = { ··· 3304 3289 .serdes_num = ARRAY_SIZE(sa8775p_qmp_gen4x4_pcie_rc_serdes_alt_tbl), 3305 3290 .pcs_misc = sa8775p_qmp_gen4_pcie_rc_pcs_misc_tbl, 3306 3291 .pcs_misc_num = ARRAY_SIZE(sa8775p_qmp_gen4_pcie_rc_pcs_misc_tbl), 3292 + }, 3293 + 3294 + .tbls_ep = &(const struct qmp_phy_cfg_tbls) { 3295 + .serdes = sa8775p_qmp_gen4x2_pcie_ep_serdes_alt_tbl, 3296 + .serdes_num = ARRAY_SIZE(sa8775p_qmp_gen4x2_pcie_ep_serdes_alt_tbl), 3297 + .pcs_misc = sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl, 3298 + .pcs_misc_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl), 3307 3299 }, 3308 3300 3309 3301 .reset_list = sdm845_pciephy_reset_l, ··· 3686 3664 struct clk_init_data init = { }; 3687 3665 int ret; 3688 3666 3689 - ret = of_property_read_string(np, "clock-output-names", &init.name); 3667 + ret = of_property_read_string_index(np, "clock-output-names", 0, &init.name); 3690 3668 if (ret) { 3691 3669 dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); 3692 3670 return ret; ··· 3705 3683 3706 3684 fixed->hw.init = &init; 3707 3685 3708 - ret = devm_clk_hw_register(qmp->dev, &fixed->hw); 3686 + return devm_clk_hw_register(qmp->dev, &fixed->hw); 3687 + } 3688 + 3689 + /* 3690 + * Register a fixed rate PHY aux clock. 3691 + * 3692 + * The <s>_phy_aux_clksrc generated by PHY goes to the GCC that gate 3693 + * controls it. The <s>_phy_aux_clk coming out of the GCC is requested 3694 + * by the PHY driver for its operations. 3695 + * We register the <s>_phy_aux_clksrc here. The gcc driver takes care 3696 + * of assigning this <s>_phy_aux_clksrc as parent to <s>_phy_aux_clk. 3697 + * Below picture shows this relationship. 3698 + * 3699 + * +---------------+ 3700 + * | PHY block |<<---------------------------------------------+ 3701 + * | | | 3702 + * | +-------+ | +-----+ | 3703 + * I/P---^-->| PLL |---^--->phy_aux_clksrc--->| GCC |--->phy_aux_clk---+ 3704 + * clk | +-------+ | +-----+ 3705 + * +---------------+ 3706 + */ 3707 + static int phy_aux_clk_register(struct qmp_pcie *qmp, struct device_node *np) 3708 + { 3709 + struct clk_fixed_rate *fixed = &qmp->aux_clk_fixed; 3710 + struct clk_init_data init = { }; 3711 + int ret; 3712 + 3713 + ret = of_property_read_string_index(np, "clock-output-names", 1, &init.name); 3714 + if (ret) { 3715 + dev_err(qmp->dev, "%pOFn: No clock-output-names index 1\n", np); 3716 + return ret; 3717 + } 3718 + 3719 + init.ops = &clk_fixed_rate_ops; 3720 + 3721 + fixed->fixed_rate = qmp->cfg->aux_clock_rate; 3722 + fixed->hw.init = &init; 3723 + 3724 + return devm_clk_hw_register(qmp->dev, &fixed->hw); 3725 + } 3726 + 3727 + static struct clk_hw *qmp_pcie_clk_hw_get(struct of_phandle_args *clkspec, void *data) 3728 + { 3729 + struct qmp_pcie *qmp = data; 3730 + 3731 + /* Support legacy bindings */ 3732 + if (!clkspec->args_count) 3733 + return &qmp->pipe_clk_fixed.hw; 3734 + 3735 + switch (clkspec->args[0]) { 3736 + case QMP_PCIE_PIPE_CLK: 3737 + return &qmp->pipe_clk_fixed.hw; 3738 + case QMP_PCIE_PHY_AUX_CLK: 3739 + return &qmp->aux_clk_fixed.hw; 3740 + } 3741 + 3742 + return ERR_PTR(-EINVAL); 3743 + } 3744 + 3745 + static int qmp_pcie_register_clocks(struct qmp_pcie *qmp, struct device_node *np) 3746 + { 3747 + int ret; 3748 + 3749 + ret = phy_pipe_clk_register(qmp, np); 3709 3750 if (ret) 3710 3751 return ret; 3711 3752 3712 - ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); 3713 - if (ret) 3714 - return ret; 3753 + if (qmp->cfg->aux_clock_rate) { 3754 + ret = phy_aux_clk_register(qmp, np); 3755 + if (ret) 3756 + return ret; 3757 + 3758 + ret = of_clk_add_hw_provider(np, qmp_pcie_clk_hw_get, qmp); 3759 + if (ret) 3760 + return ret; 3761 + } else { 3762 + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &qmp->pipe_clk_fixed.hw); 3763 + if (ret) 3764 + return ret; 3765 + } 3715 3766 3716 3767 /* 3717 3768 * Roll a devm action because the clock provider is the child node, but ··· 3994 3899 if (ret) 3995 3900 goto err_node_put; 3996 3901 3997 - ret = phy_pipe_clk_register(qmp, np); 3902 + ret = qmp_pcie_register_clocks(qmp, np); 3998 3903 if (ret) 3999 3904 goto err_node_put; 4000 3905
+4
drivers/phy/qualcomm/phy-qcom-qmp-pcs-ufs-v6.h
··· 30 30 #define QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1 0x1f4 31 31 #define QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1 0x1fc 32 32 #define QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME 0x220 33 + #define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4 0x240 34 + #define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S5 0x244 35 + #define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S6 0x248 36 + #define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S7 0x24c 33 37 34 38 #endif
+6
drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-ufs-v6.h
··· 25 25 #define QSERDES_UFS_V6_RX_UCDR_SO_GAIN_RATE4 0xf0 26 26 #define QSERDES_UFS_V6_RX_UCDR_PI_CONTROLS 0xf4 27 27 #define QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL 0x178 28 + #define QSERDES_UFS_V6_RX_RX_EQU_ADAPTOR_CNTRL4 0x1ac 28 29 #define QSERDES_UFS_V6_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x1bc 29 30 #define QSERDES_UFS_V6_RX_INTERFACE_MODE 0x1e0 30 31 #define QSERDES_UFS_V6_RX_OFFSET_ADAPTOR_CNTRL3 0x1c4 31 32 #define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0 0x208 32 33 #define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1 0x20c 34 + #define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B2 0x210 33 35 #define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B3 0x214 36 + #define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B4 0x218 34 37 #define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B6 0x220 35 38 #define QSERDES_UFS_V6_RX_MODE_RATE2_B3 0x238 36 39 #define QSERDES_UFS_V6_RX_MODE_RATE2_B6 0x244 ··· 41 38 #define QSERDES_UFS_V6_RX_MODE_RATE3_B4 0x260 42 39 #define QSERDES_UFS_V6_RX_MODE_RATE3_B5 0x264 43 40 #define QSERDES_UFS_V6_RX_MODE_RATE3_B8 0x270 41 + #define QSERDES_UFS_V6_RX_MODE_RATE4_B0 0x274 42 + #define QSERDES_UFS_V6_RX_MODE_RATE4_B1 0x278 43 + #define QSERDES_UFS_V6_RX_MODE_RATE4_B2 0x27c 44 44 #define QSERDES_UFS_V6_RX_MODE_RATE4_B3 0x280 45 45 #define QSERDES_UFS_V6_RX_MODE_RATE4_B4 0x284 46 46 #define QSERDES_UFS_V6_RX_MODE_RATE4_B6 0x28c
+129 -15
drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
··· 722 722 QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_BIST_FIXED_PAT_CTRL, 0x0a), 723 723 }; 724 724 725 + static const struct qmp_phy_init_tbl sm8475_ufsphy_serdes[] = { 726 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9), 727 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16), 728 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11), 729 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00), 730 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01), 731 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00), 732 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x82), 733 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18), 734 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x18), 735 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0xff), 736 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0c), 737 + }; 738 + 739 + static const struct qmp_phy_init_tbl sm8475_ufsphy_g4_serdes[] = { 740 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04), 741 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f), 742 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x14), 743 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x98), 744 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x14), 745 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18), 746 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x18), 747 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x32), 748 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x0f), 749 + }; 750 + 751 + static const struct qmp_phy_init_tbl sm8475_ufsphy_g4_pcs[] = { 752 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x0b), 753 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04), 754 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04), 755 + }; 756 + 725 757 static const struct qmp_phy_init_tbl sm8550_ufsphy_serdes[] = { 726 758 QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9), 727 759 QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16), ··· 862 830 QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11), 863 831 QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00), 864 832 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01), 865 - QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f), 866 - QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x44), 833 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x1f), 834 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO_MODE1, 0x1f), 835 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IETRIM, 0x0a), 836 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IPTRIM, 0x17), 837 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04), 867 838 QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00), 868 839 QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41), 869 - QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x0a), 840 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06), 870 841 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18), 871 842 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x14), 872 843 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x7f), 873 844 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x06), 874 845 QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x4c), 875 - QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x0a), 846 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06), 876 847 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18), 877 848 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x14), 878 849 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x99), ··· 883 848 }; 884 849 885 850 static const struct qmp_phy_init_tbl sm8650_ufsphy_tx[] = { 886 - QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x05), 851 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x01), 887 852 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x07), 853 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), 888 854 }; 889 855 890 856 static const struct qmp_phy_init_tbl sm8650_ufsphy_rx[] = { 891 857 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE2, 0x0c), 892 - QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4, 0x0f), 893 - QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x0e), 894 - QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xc2), 895 - QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xc2), 858 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4, 0x0c), 859 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_SO_GAIN_RATE4, 0x04), 860 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14), 861 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CONTROLS, 0x07), 862 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_OFFSET_ADAPTOR_CNTRL3, 0x0e), 863 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4, 0x02), 864 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_FO_GAIN_RATE4, 0x1c), 865 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_SO_GAIN_RATE4, 0x06), 866 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x3e), 867 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f), 868 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xce), 869 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xce), 870 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B2, 0x18), 896 871 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B3, 0x1a), 872 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B4, 0x0f), 897 873 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B6, 0x60), 898 874 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B3, 0x9e), 899 875 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B6, 0x60), ··· 912 866 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B4, 0x0e), 913 867 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B5, 0x36), 914 868 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B8, 0x02), 869 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B0, 0x24), 870 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B1, 0x24), 871 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B2, 0x20), 915 872 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B3, 0xb9), 916 - QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B6, 0xff), 873 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B4, 0x4f), 917 874 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_SO_SATURATION, 0x1f), 918 875 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CTRL1, 0x94), 919 876 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_RX_TERM_BW_CTRL0, 0xfa), 877 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_DLL0_FTUNE_CTRL, 0x30), 920 878 }; 921 879 922 880 static const struct qmp_phy_init_tbl sm8650_ufsphy_pcs[] = { 923 - QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x00), 881 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02), 924 882 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), 925 883 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PCS_CTRL1, 0xc1), 926 - QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33), 884 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f), 885 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x68), 886 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4, 0x0e), 887 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S5, 0x12), 888 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S6, 0x15), 889 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S7, 0x19), 890 + }; 891 + 892 + static const struct qmp_phy_init_tbl sm8650_ufsphy_g4_pcs[] = { 893 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x13), 927 894 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04), 928 895 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04), 929 - QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f), 930 - QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x69), 931 - QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02), 896 + }; 897 + 898 + static const struct qmp_phy_init_tbl sm8650_ufsphy_g5_pcs[] = { 899 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33), 900 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x05), 901 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x05), 902 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HS_G5_SYNC_LENGTH_CAPABILITY, 0x4d), 903 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME, 0x9e), 932 904 }; 933 905 934 906 struct qmp_ufs_offsets { ··· 1410 1346 .regs = ufsphy_v5_regs_layout, 1411 1347 }; 1412 1348 1349 + static const struct qmp_phy_cfg sm8475_ufsphy_cfg = { 1350 + .lanes = 2, 1351 + 1352 + .offsets = &qmp_ufs_offsets_v6, 1353 + .max_supported_gear = UFS_HS_G4, 1354 + 1355 + .tbls = { 1356 + .serdes = sm8475_ufsphy_serdes, 1357 + .serdes_num = ARRAY_SIZE(sm8475_ufsphy_serdes), 1358 + .tx = sm8550_ufsphy_tx, 1359 + .tx_num = ARRAY_SIZE(sm8550_ufsphy_tx), 1360 + .rx = sm8550_ufsphy_rx, 1361 + .rx_num = ARRAY_SIZE(sm8550_ufsphy_rx), 1362 + .pcs = sm8550_ufsphy_pcs, 1363 + .pcs_num = ARRAY_SIZE(sm8550_ufsphy_pcs), 1364 + }, 1365 + .tbls_hs_b = { 1366 + .serdes = sm8550_ufsphy_hs_b_serdes, 1367 + .serdes_num = ARRAY_SIZE(sm8550_ufsphy_hs_b_serdes), 1368 + }, 1369 + .tbls_hs_overlay[0] = { 1370 + .serdes = sm8475_ufsphy_g4_serdes, 1371 + .serdes_num = ARRAY_SIZE(sm8475_ufsphy_g4_serdes), 1372 + .tx = sm8550_ufsphy_g4_tx, 1373 + .tx_num = ARRAY_SIZE(sm8550_ufsphy_g4_tx), 1374 + .rx = sm8550_ufsphy_g4_rx, 1375 + .rx_num = ARRAY_SIZE(sm8550_ufsphy_g4_rx), 1376 + .pcs = sm8475_ufsphy_g4_pcs, 1377 + .pcs_num = ARRAY_SIZE(sm8475_ufsphy_g4_pcs), 1378 + .max_gear = UFS_HS_G4, 1379 + }, 1380 + .vreg_list = qmp_phy_vreg_l, 1381 + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 1382 + .regs = ufsphy_v6_regs_layout, 1383 + }; 1384 + 1413 1385 static const struct qmp_phy_cfg sm8550_ufsphy_cfg = { 1414 1386 .lanes = 2, 1415 1387 ··· 1507 1407 .pcs = sm8650_ufsphy_pcs, 1508 1408 .pcs_num = ARRAY_SIZE(sm8650_ufsphy_pcs), 1509 1409 }, 1410 + .tbls_hs_overlay[0] = { 1411 + .pcs = sm8650_ufsphy_g4_pcs, 1412 + .pcs_num = ARRAY_SIZE(sm8650_ufsphy_g4_pcs), 1413 + .max_gear = UFS_HS_G4, 1414 + }, 1415 + .tbls_hs_overlay[1] = { 1416 + .pcs = sm8650_ufsphy_g5_pcs, 1417 + .pcs_num = ARRAY_SIZE(sm8650_ufsphy_g5_pcs), 1418 + .max_gear = UFS_HS_G5, 1419 + }, 1420 + 1510 1421 .vreg_list = qmp_phy_vreg_l, 1511 1422 .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 1512 1423 .regs = ufsphy_v6_regs_layout, ··· 2052 1941 }, { 2053 1942 .compatible = "qcom,sm8450-qmp-ufs-phy", 2054 1943 .data = &sm8450_ufsphy_cfg, 1944 + }, { 1945 + .compatible = "qcom,sm8475-qmp-ufs-phy", 1946 + .data = &sm8475_ufsphy_cfg, 2055 1947 }, { 2056 1948 .compatible = "qcom,sm8550-qmp-ufs-phy", 2057 1949 .data = &sm8550_ufsphy_cfg,
+47
drivers/phy/qualcomm/phy-qcom-qmp-usb.c
··· 337 337 QMP_PHY_INIT_CFG(QPHY_V2_PCS_POWER_STATE_CONFIG2, 0x08), 338 338 }; 339 339 340 + static const struct qmp_phy_init_tbl qdu1000_usb3_uniphy_pcs_tbl[] = { 341 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xc4), 342 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x89), 343 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), 344 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), 345 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), 346 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), 347 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), 348 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), 349 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), 350 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), 351 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), 352 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), 353 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), 354 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), 355 + }; 356 + 357 + static const struct qmp_phy_init_tbl qdu1000_usb3_uniphy_pcs_usb_tbl[] = { 358 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), 359 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), 360 + QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_POWER_STATE_CONFIG1, 0x6f), 361 + }; 362 + 340 363 static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_serdes_tbl[] = { 341 364 QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), 342 365 QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ··· 1423 1400 .regs = qmp_v2_usb3phy_regs_layout, 1424 1401 }; 1425 1402 1403 + static const struct qmp_phy_cfg qdu1000_usb3_uniphy_cfg = { 1404 + .offsets = &qmp_usb_offsets_v5, 1405 + 1406 + .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, 1407 + .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), 1408 + .tx_tbl = sm8350_usb3_uniphy_tx_tbl, 1409 + .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_tx_tbl), 1410 + .rx_tbl = sm8350_usb3_uniphy_rx_tbl, 1411 + .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_rx_tbl), 1412 + .pcs_tbl = qdu1000_usb3_uniphy_pcs_tbl, 1413 + .pcs_tbl_num = ARRAY_SIZE(qdu1000_usb3_uniphy_pcs_tbl), 1414 + .pcs_usb_tbl = qdu1000_usb3_uniphy_pcs_usb_tbl, 1415 + .pcs_usb_tbl_num = ARRAY_SIZE(qdu1000_usb3_uniphy_pcs_usb_tbl), 1416 + .vreg_list = qmp_phy_vreg_l, 1417 + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 1418 + .regs = qmp_v4_usb3phy_regs_layout, 1419 + .pcs_usb_offset = 0x1000, 1420 + 1421 + .has_pwrdn_delay = true, 1422 + }; 1423 + 1426 1424 static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = { 1427 1425 .offsets = &qmp_usb_offsets_v5, 1428 1426 ··· 2246 2202 }, { 2247 2203 .compatible = "qcom,msm8996-qmp-usb3-phy", 2248 2204 .data = &msm8996_usb3phy_cfg, 2205 + }, { 2206 + .compatible = "qcom,qdu1000-qmp-usb3-uni-phy", 2207 + .data = &qdu1000_usb3_uniphy_cfg, 2249 2208 }, { 2250 2209 .compatible = "qcom,sa8775p-qmp-usb3-uni-phy", 2251 2210 .data = &sa8775p_usb3_uniphy_cfg,
+12
drivers/phy/rockchip/Kconfig
··· 116 116 select GENERIC_PHY 117 117 help 118 118 Enable this to support the Rockchip USB 2.0 PHY. 119 + 120 + config PHY_ROCKCHIP_USBDP 121 + tristate "Rockchip USBDP COMBO PHY Driver" 122 + depends on ARCH_ROCKCHIP && OF 123 + depends on TYPEC 124 + select GENERIC_PHY 125 + help 126 + Enable this to support the Rockchip USB3.0/DP combo PHY with 127 + Samsung IP block. This is required for USB3 support on RK3588. 128 + 129 + To compile this driver as a module, choose M here: the module 130 + will be called phy-rockchip-usbdp
+1
drivers/phy/rockchip/Makefile
··· 12 12 obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o 13 13 obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o 14 14 obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o 15 + obj-$(CONFIG_PHY_ROCKCHIP_USBDP) += phy-rockchip-usbdp.o
+2 -2
drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
··· 248 248 return 0; 249 249 } 250 250 251 - static const struct phy_ops rochchip_combphy_ops = { 251 + static const struct phy_ops rockchip_combphy_ops = { 252 252 .init = rockchip_combphy_init, 253 253 .exit = rockchip_combphy_exit, 254 254 .owner = THIS_MODULE, ··· 364 364 return ret; 365 365 } 366 366 367 - priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops); 367 + priv->phy = devm_phy_create(dev, NULL, &rockchip_combphy_ops); 368 368 if (IS_ERR(priv->phy)) { 369 369 dev_err(dev, "failed to create combphy\n"); 370 370 return PTR_ERR(priv->phy);
+43 -6
drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
··· 35 35 #define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0 36 36 #define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904 37 37 #define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04 38 + #define RK3588_PCIE3PHY_GRF_PHY0_LN0_CON1 0x1004 39 + #define RK3588_PCIE3PHY_GRF_PHY0_LN1_CON1 0x1104 40 + #define RK3588_PCIE3PHY_GRF_PHY1_LN0_CON1 0x2004 41 + #define RK3588_PCIE3PHY_GRF_PHY1_LN1_CON1 0x2104 38 42 #define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0)) 39 43 40 44 #define RK3588_BIFURCATION_LANE_0_1 BIT(0) 41 45 #define RK3588_BIFURCATION_LANE_2_3 BIT(1) 42 46 #define RK3588_LANE_AGGREGATION BIT(2) 47 + #define RK3588_RX_CMN_REFCLK_MODE_EN ((BIT(7) << 16) | BIT(7)) 48 + #define RK3588_RX_CMN_REFCLK_MODE_DIS (BIT(7) << 16) 43 49 #define RK3588_PCIE1LN_SEL_EN (GENMASK(1, 0) << 16) 44 50 #define RK3588_PCIE30_PHY_MODE_EN (GENMASK(2, 0) << 16) 45 51 ··· 66 60 int num_clks; 67 61 int num_lanes; 68 62 u32 lanes[4]; 63 + u32 rx_cmn_refclk_mode[4]; 69 64 }; 70 65 71 66 struct rockchip_p3phy_ops { ··· 144 137 u8 mode = RK3588_LANE_AGGREGATION; /* default */ 145 138 int ret; 146 139 140 + regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY0_LN0_CON1, 141 + priv->rx_cmn_refclk_mode[0] ? RK3588_RX_CMN_REFCLK_MODE_EN : 142 + RK3588_RX_CMN_REFCLK_MODE_DIS); 143 + regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY0_LN1_CON1, 144 + priv->rx_cmn_refclk_mode[1] ? RK3588_RX_CMN_REFCLK_MODE_EN : 145 + RK3588_RX_CMN_REFCLK_MODE_DIS); 146 + regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY1_LN0_CON1, 147 + priv->rx_cmn_refclk_mode[2] ? RK3588_RX_CMN_REFCLK_MODE_EN : 148 + RK3588_RX_CMN_REFCLK_MODE_DIS); 149 + regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY1_LN1_CON1, 150 + priv->rx_cmn_refclk_mode[3] ? RK3588_RX_CMN_REFCLK_MODE_EN : 151 + RK3588_RX_CMN_REFCLK_MODE_DIS); 152 + 147 153 /* Deassert PCIe PMA output clamp mode */ 148 154 regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, BIT(8) | BIT(24)); 149 155 ··· 202 182 .phy_init = rockchip_p3phy_rk3588_init, 203 183 }; 204 184 205 - static int rochchip_p3phy_init(struct phy *phy) 185 + static int rockchip_p3phy_init(struct phy *phy) 206 186 { 207 187 struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); 208 188 int ret; ··· 225 205 return ret; 226 206 } 227 207 228 - static int rochchip_p3phy_exit(struct phy *phy) 208 + static int rockchip_p3phy_exit(struct phy *phy) 229 209 { 230 210 struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); 231 211 ··· 234 214 return 0; 235 215 } 236 216 237 - static const struct phy_ops rochchip_p3phy_ops = { 238 - .init = rochchip_p3phy_init, 239 - .exit = rochchip_p3phy_exit, 217 + static const struct phy_ops rockchip_p3phy_ops = { 218 + .init = rockchip_p3phy_init, 219 + .exit = rockchip_p3phy_exit, 240 220 .set_mode = rockchip_p3phy_set_mode, 241 221 .owner = THIS_MODULE, 242 222 }; ··· 295 275 return priv->num_lanes; 296 276 } 297 277 298 - priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops); 278 + ret = of_property_read_variable_u32_array(dev->of_node, 279 + "rockchip,rx-common-refclk-mode", 280 + priv->rx_cmn_refclk_mode, 1, 281 + ARRAY_SIZE(priv->rx_cmn_refclk_mode)); 282 + /* 283 + * if no rockchip,rx-common-refclk-mode, assume enabled for all lanes in 284 + * order to be DT backwards compatible. (Since HW reset val is enabled.) 285 + */ 286 + if (ret == -EINVAL) { 287 + for (int i = 0; i < ARRAY_SIZE(priv->rx_cmn_refclk_mode); i++) 288 + priv->rx_cmn_refclk_mode[i] = 1; 289 + } else if (ret < 0) { 290 + dev_err(dev, "failed to read rockchip,rx-common-refclk-mode property %d\n", 291 + ret); 292 + return ret; 293 + } 294 + 295 + priv->phy = devm_phy_create(dev, NULL, &rockchip_p3phy_ops); 299 296 if (IS_ERR(priv->phy)) { 300 297 dev_err(dev, "failed to create combphy\n"); 301 298 return PTR_ERR(priv->phy);
+1608
drivers/phy/rockchip/phy-rockchip-usbdp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Rockchip USBDP Combo PHY with Samsung IP block driver 4 + * 5 + * Copyright (C) 2021-2024 Rockchip Electronics Co., Ltd 6 + * Copyright (C) 2024 Collabora Ltd 7 + */ 8 + 9 + #include <dt-bindings/phy/phy.h> 10 + #include <linux/bitfield.h> 11 + #include <linux/bits.h> 12 + #include <linux/clk.h> 13 + #include <linux/delay.h> 14 + #include <linux/gpio.h> 15 + #include <linux/mfd/syscon.h> 16 + #include <linux/mod_devicetable.h> 17 + #include <linux/module.h> 18 + #include <linux/mutex.h> 19 + #include <linux/phy/phy.h> 20 + #include <linux/platform_device.h> 21 + #include <linux/property.h> 22 + #include <linux/regmap.h> 23 + #include <linux/reset.h> 24 + #include <linux/usb/ch9.h> 25 + #include <linux/usb/typec_dp.h> 26 + #include <linux/usb/typec_mux.h> 27 + 28 + /* USBDP PHY Register Definitions */ 29 + #define UDPHY_PCS 0x4000 30 + #define UDPHY_PMA 0x8000 31 + 32 + /* VO0 GRF Registers */ 33 + #define DP_SINK_HPD_CFG BIT(11) 34 + #define DP_SINK_HPD_SEL BIT(10) 35 + #define DP_AUX_DIN_SEL BIT(9) 36 + #define DP_AUX_DOUT_SEL BIT(8) 37 + #define DP_LANE_SEL_N(n) GENMASK(2 * (n) + 1, 2 * (n)) 38 + #define DP_LANE_SEL_ALL GENMASK(7, 0) 39 + 40 + /* PMA CMN Registers */ 41 + #define CMN_LANE_MUX_AND_EN_OFFSET 0x0288 /* cmn_reg00A2 */ 42 + #define CMN_DP_LANE_MUX_N(n) BIT((n) + 4) 43 + #define CMN_DP_LANE_EN_N(n) BIT(n) 44 + #define CMN_DP_LANE_MUX_ALL GENMASK(7, 4) 45 + #define CMN_DP_LANE_EN_ALL GENMASK(3, 0) 46 + 47 + #define CMN_DP_LINK_OFFSET 0x28c /* cmn_reg00A3 */ 48 + #define CMN_DP_TX_LINK_BW GENMASK(6, 5) 49 + #define CMN_DP_TX_LANE_SWAP_EN BIT(2) 50 + 51 + #define CMN_SSC_EN_OFFSET 0x2d0 /* cmn_reg00B4 */ 52 + #define CMN_ROPLL_SSC_EN BIT(1) 53 + #define CMN_LCPLL_SSC_EN BIT(0) 54 + 55 + #define CMN_ANA_LCPLL_DONE_OFFSET 0x0350 /* cmn_reg00D4 */ 56 + #define CMN_ANA_LCPLL_LOCK_DONE BIT(7) 57 + #define CMN_ANA_LCPLL_AFC_DONE BIT(6) 58 + 59 + #define CMN_ANA_ROPLL_DONE_OFFSET 0x0354 /* cmn_reg00D5 */ 60 + #define CMN_ANA_ROPLL_LOCK_DONE BIT(1) 61 + #define CMN_ANA_ROPLL_AFC_DONE BIT(0) 62 + 63 + #define CMN_DP_RSTN_OFFSET 0x038c /* cmn_reg00E3 */ 64 + #define CMN_DP_INIT_RSTN BIT(3) 65 + #define CMN_DP_CMN_RSTN BIT(2) 66 + #define CMN_CDR_WTCHDG_EN BIT(1) 67 + #define CMN_CDR_WTCHDG_MSK_CDR_EN BIT(0) 68 + 69 + #define TRSV_ANA_TX_CLK_OFFSET_N(n) (0x854 + (n) * 0x800) /* trsv_reg0215 */ 70 + #define LN_ANA_TX_SER_TXCLK_INV BIT(1) 71 + 72 + #define TRSV_LN0_MON_RX_CDR_DONE_OFFSET 0x0b84 /* trsv_reg02E1 */ 73 + #define TRSV_LN0_MON_RX_CDR_LOCK_DONE BIT(0) 74 + 75 + #define TRSV_LN2_MON_RX_CDR_DONE_OFFSET 0x1b84 /* trsv_reg06E1 */ 76 + #define TRSV_LN2_MON_RX_CDR_LOCK_DONE BIT(0) 77 + 78 + #define BIT_WRITEABLE_SHIFT 16 79 + #define PHY_AUX_DP_DATA_POL_NORMAL 0 80 + #define PHY_AUX_DP_DATA_POL_INVERT 1 81 + #define PHY_LANE_MUX_USB 0 82 + #define PHY_LANE_MUX_DP 1 83 + 84 + enum { 85 + DP_BW_RBR, 86 + DP_BW_HBR, 87 + DP_BW_HBR2, 88 + DP_BW_HBR3, 89 + }; 90 + 91 + enum { 92 + UDPHY_MODE_NONE = 0, 93 + UDPHY_MODE_USB = BIT(0), 94 + UDPHY_MODE_DP = BIT(1), 95 + UDPHY_MODE_DP_USB = BIT(1) | BIT(0), 96 + }; 97 + 98 + struct rk_udphy_grf_reg { 99 + unsigned int offset; 100 + unsigned int disable; 101 + unsigned int enable; 102 + }; 103 + 104 + #define _RK_UDPHY_GEN_GRF_REG(offset, mask, disable, enable) \ 105 + {\ 106 + offset, \ 107 + FIELD_PREP_CONST(mask, disable) | (mask << BIT_WRITEABLE_SHIFT), \ 108 + FIELD_PREP_CONST(mask, enable) | (mask << BIT_WRITEABLE_SHIFT), \ 109 + } 110 + 111 + #define RK_UDPHY_GEN_GRF_REG(offset, bitend, bitstart, disable, enable) \ 112 + _RK_UDPHY_GEN_GRF_REG(offset, GENMASK(bitend, bitstart), disable, enable) 113 + 114 + struct rk_udphy_grf_cfg { 115 + /* u2phy-grf */ 116 + struct rk_udphy_grf_reg bvalid_phy_con; 117 + struct rk_udphy_grf_reg bvalid_grf_con; 118 + 119 + /* usb-grf */ 120 + struct rk_udphy_grf_reg usb3otg0_cfg; 121 + struct rk_udphy_grf_reg usb3otg1_cfg; 122 + 123 + /* usbdpphy-grf */ 124 + struct rk_udphy_grf_reg low_pwrn; 125 + struct rk_udphy_grf_reg rx_lfps; 126 + }; 127 + 128 + struct rk_udphy_vogrf_cfg { 129 + /* vo-grf */ 130 + struct rk_udphy_grf_reg hpd_trigger; 131 + u32 dp_lane_reg; 132 + }; 133 + 134 + struct rk_udphy_dp_tx_drv_ctrl { 135 + u32 trsv_reg0204; 136 + u32 trsv_reg0205; 137 + u32 trsv_reg0206; 138 + u32 trsv_reg0207; 139 + }; 140 + 141 + struct rk_udphy_cfg { 142 + unsigned int num_phys; 143 + unsigned int phy_ids[2]; 144 + /* resets to be requested */ 145 + const char * const *rst_list; 146 + int num_rsts; 147 + 148 + struct rk_udphy_grf_cfg grfcfg; 149 + struct rk_udphy_vogrf_cfg vogrfcfg[2]; 150 + const struct rk_udphy_dp_tx_drv_ctrl (*dp_tx_ctrl_cfg[4])[4]; 151 + const struct rk_udphy_dp_tx_drv_ctrl (*dp_tx_ctrl_cfg_typec[4])[4]; 152 + }; 153 + 154 + struct rk_udphy { 155 + struct device *dev; 156 + struct regmap *pma_regmap; 157 + struct regmap *u2phygrf; 158 + struct regmap *udphygrf; 159 + struct regmap *usbgrf; 160 + struct regmap *vogrf; 161 + struct typec_switch_dev *sw; 162 + struct typec_mux_dev *mux; 163 + struct mutex mutex; /* mutex to protect access to individual PHYs */ 164 + 165 + /* clocks and rests */ 166 + int num_clks; 167 + struct clk_bulk_data *clks; 168 + struct clk *refclk; 169 + int num_rsts; 170 + struct reset_control_bulk_data *rsts; 171 + 172 + /* PHY status management */ 173 + bool flip; 174 + bool mode_change; 175 + u8 mode; 176 + u8 status; 177 + 178 + /* utilized for USB */ 179 + bool hs; /* flag for high-speed */ 180 + 181 + /* utilized for DP */ 182 + struct gpio_desc *sbu1_dc_gpio; 183 + struct gpio_desc *sbu2_dc_gpio; 184 + u32 lane_mux_sel[4]; 185 + u32 dp_lane_sel[4]; 186 + u32 dp_aux_dout_sel; 187 + u32 dp_aux_din_sel; 188 + bool dp_sink_hpd_sel; 189 + bool dp_sink_hpd_cfg; 190 + u8 bw; 191 + int id; 192 + 193 + bool dp_in_use; 194 + 195 + /* PHY const config */ 196 + const struct rk_udphy_cfg *cfgs; 197 + 198 + /* PHY devices */ 199 + struct phy *phy_dp; 200 + struct phy *phy_u3; 201 + }; 202 + 203 + static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr[4][4] = { 204 + /* voltage swing 0, pre-emphasis 0->3 */ 205 + { 206 + { 0x20, 0x10, 0x42, 0xe5 }, 207 + { 0x26, 0x14, 0x42, 0xe5 }, 208 + { 0x29, 0x18, 0x42, 0xe5 }, 209 + { 0x2b, 0x1c, 0x43, 0xe7 }, 210 + }, 211 + 212 + /* voltage swing 1, pre-emphasis 0->2 */ 213 + { 214 + { 0x23, 0x10, 0x42, 0xe7 }, 215 + { 0x2a, 0x17, 0x43, 0xe7 }, 216 + { 0x2b, 0x1a, 0x43, 0xe7 }, 217 + }, 218 + 219 + /* voltage swing 2, pre-emphasis 0->1 */ 220 + { 221 + { 0x27, 0x10, 0x42, 0xe7 }, 222 + { 0x2b, 0x17, 0x43, 0xe7 }, 223 + }, 224 + 225 + /* voltage swing 3, pre-emphasis 0 */ 226 + { 227 + { 0x29, 0x10, 0x43, 0xe7 }, 228 + }, 229 + }; 230 + 231 + static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr_typec[4][4] = { 232 + /* voltage swing 0, pre-emphasis 0->3 */ 233 + { 234 + { 0x20, 0x10, 0x42, 0xe5 }, 235 + { 0x26, 0x14, 0x42, 0xe5 }, 236 + { 0x29, 0x18, 0x42, 0xe5 }, 237 + { 0x2b, 0x1c, 0x43, 0xe7 }, 238 + }, 239 + 240 + /* voltage swing 1, pre-emphasis 0->2 */ 241 + { 242 + { 0x23, 0x10, 0x42, 0xe7 }, 243 + { 0x2a, 0x17, 0x43, 0xe7 }, 244 + { 0x2b, 0x1a, 0x43, 0xe7 }, 245 + }, 246 + 247 + /* voltage swing 2, pre-emphasis 0->1 */ 248 + { 249 + { 0x27, 0x10, 0x43, 0x67 }, 250 + { 0x2b, 0x17, 0x43, 0xe7 }, 251 + }, 252 + 253 + /* voltage swing 3, pre-emphasis 0 */ 254 + { 255 + { 0x29, 0x10, 0x43, 0xe7 }, 256 + }, 257 + }; 258 + 259 + static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr2[4][4] = { 260 + /* voltage swing 0, pre-emphasis 0->3 */ 261 + { 262 + { 0x21, 0x10, 0x42, 0xe5 }, 263 + { 0x26, 0x14, 0x42, 0xe5 }, 264 + { 0x26, 0x16, 0x43, 0xe5 }, 265 + { 0x2a, 0x19, 0x43, 0xe7 }, 266 + }, 267 + 268 + /* voltage swing 1, pre-emphasis 0->2 */ 269 + { 270 + { 0x24, 0x10, 0x42, 0xe7 }, 271 + { 0x2a, 0x17, 0x43, 0xe7 }, 272 + { 0x2b, 0x1a, 0x43, 0xe7 }, 273 + }, 274 + 275 + /* voltage swing 2, pre-emphasis 0->1 */ 276 + { 277 + { 0x28, 0x10, 0x42, 0xe7 }, 278 + { 0x2b, 0x17, 0x43, 0xe7 }, 279 + }, 280 + 281 + /* voltage swing 3, pre-emphasis 0 */ 282 + { 283 + { 0x28, 0x10, 0x43, 0xe7 }, 284 + }, 285 + }; 286 + 287 + static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr3[4][4] = { 288 + /* voltage swing 0, pre-emphasis 0->3 */ 289 + { 290 + { 0x21, 0x10, 0x42, 0xe5 }, 291 + { 0x26, 0x14, 0x42, 0xe5 }, 292 + { 0x26, 0x16, 0x43, 0xe5 }, 293 + { 0x29, 0x18, 0x43, 0xe7 }, 294 + }, 295 + 296 + /* voltage swing 1, pre-emphasis 0->2 */ 297 + { 298 + { 0x24, 0x10, 0x42, 0xe7 }, 299 + { 0x2a, 0x18, 0x43, 0xe7 }, 300 + { 0x2b, 0x1b, 0x43, 0xe7 } 301 + }, 302 + 303 + /* voltage swing 2, pre-emphasis 0->1 */ 304 + { 305 + { 0x27, 0x10, 0x42, 0xe7 }, 306 + { 0x2b, 0x18, 0x43, 0xe7 } 307 + }, 308 + 309 + /* voltage swing 3, pre-emphasis 0 */ 310 + { 311 + { 0x28, 0x10, 0x43, 0xe7 }, 312 + }, 313 + }; 314 + 315 + static const struct reg_sequence rk_udphy_24m_refclk_cfg[] = { 316 + {0x0090, 0x68}, {0x0094, 0x68}, 317 + {0x0128, 0x24}, {0x012c, 0x44}, 318 + {0x0130, 0x3f}, {0x0134, 0x44}, 319 + {0x015c, 0xa9}, {0x0160, 0x71}, 320 + {0x0164, 0x71}, {0x0168, 0xa9}, 321 + {0x0174, 0xa9}, {0x0178, 0x71}, 322 + {0x017c, 0x71}, {0x0180, 0xa9}, 323 + {0x018c, 0x41}, {0x0190, 0x00}, 324 + {0x0194, 0x05}, {0x01ac, 0x2a}, 325 + {0x01b0, 0x17}, {0x01b4, 0x17}, 326 + {0x01b8, 0x2a}, {0x01c8, 0x04}, 327 + {0x01cc, 0x08}, {0x01d0, 0x08}, 328 + {0x01d4, 0x04}, {0x01d8, 0x20}, 329 + {0x01dc, 0x01}, {0x01e0, 0x09}, 330 + {0x01e4, 0x03}, {0x01f0, 0x29}, 331 + {0x01f4, 0x02}, {0x01f8, 0x02}, 332 + {0x01fc, 0x29}, {0x0208, 0x2a}, 333 + {0x020c, 0x17}, {0x0210, 0x17}, 334 + {0x0214, 0x2a}, {0x0224, 0x20}, 335 + {0x03f0, 0x0a}, {0x03f4, 0x07}, 336 + {0x03f8, 0x07}, {0x03fc, 0x0c}, 337 + {0x0404, 0x12}, {0x0408, 0x1a}, 338 + {0x040c, 0x1a}, {0x0410, 0x3f}, 339 + {0x0ce0, 0x68}, {0x0ce8, 0xd0}, 340 + {0x0cf0, 0x87}, {0x0cf8, 0x70}, 341 + {0x0d00, 0x70}, {0x0d08, 0xa9}, 342 + {0x1ce0, 0x68}, {0x1ce8, 0xd0}, 343 + {0x1cf0, 0x87}, {0x1cf8, 0x70}, 344 + {0x1d00, 0x70}, {0x1d08, 0xa9}, 345 + {0x0a3c, 0xd0}, {0x0a44, 0xd0}, 346 + {0x0a48, 0x01}, {0x0a4c, 0x0d}, 347 + {0x0a54, 0xe0}, {0x0a5c, 0xe0}, 348 + {0x0a64, 0xa8}, {0x1a3c, 0xd0}, 349 + {0x1a44, 0xd0}, {0x1a48, 0x01}, 350 + {0x1a4c, 0x0d}, {0x1a54, 0xe0}, 351 + {0x1a5c, 0xe0}, {0x1a64, 0xa8} 352 + }; 353 + 354 + static const struct reg_sequence rk_udphy_26m_refclk_cfg[] = { 355 + {0x0830, 0x07}, {0x085c, 0x80}, 356 + {0x1030, 0x07}, {0x105c, 0x80}, 357 + {0x1830, 0x07}, {0x185c, 0x80}, 358 + {0x2030, 0x07}, {0x205c, 0x80}, 359 + {0x0228, 0x38}, {0x0104, 0x44}, 360 + {0x0248, 0x44}, {0x038c, 0x02}, 361 + {0x0878, 0x04}, {0x1878, 0x04}, 362 + {0x0898, 0x77}, {0x1898, 0x77}, 363 + {0x0054, 0x01}, {0x00e0, 0x38}, 364 + {0x0060, 0x24}, {0x0064, 0x77}, 365 + {0x0070, 0x76}, {0x0234, 0xe8}, 366 + {0x0af4, 0x15}, {0x1af4, 0x15}, 367 + {0x081c, 0xe5}, {0x181c, 0xe5}, 368 + {0x099c, 0x48}, {0x199c, 0x48}, 369 + {0x09a4, 0x07}, {0x09a8, 0x22}, 370 + {0x19a4, 0x07}, {0x19a8, 0x22}, 371 + {0x09b8, 0x3e}, {0x19b8, 0x3e}, 372 + {0x09e4, 0x02}, {0x19e4, 0x02}, 373 + {0x0a34, 0x1e}, {0x1a34, 0x1e}, 374 + {0x0a98, 0x2f}, {0x1a98, 0x2f}, 375 + {0x0c30, 0x0e}, {0x0c48, 0x06}, 376 + {0x1c30, 0x0e}, {0x1c48, 0x06}, 377 + {0x028c, 0x18}, {0x0af0, 0x00}, 378 + {0x1af0, 0x00} 379 + }; 380 + 381 + static const struct reg_sequence rk_udphy_init_sequence[] = { 382 + {0x0104, 0x44}, {0x0234, 0xe8}, 383 + {0x0248, 0x44}, {0x028c, 0x18}, 384 + {0x081c, 0xe5}, {0x0878, 0x00}, 385 + {0x0994, 0x1c}, {0x0af0, 0x00}, 386 + {0x181c, 0xe5}, {0x1878, 0x00}, 387 + {0x1994, 0x1c}, {0x1af0, 0x00}, 388 + {0x0428, 0x60}, {0x0d58, 0x33}, 389 + {0x1d58, 0x33}, {0x0990, 0x74}, 390 + {0x0d64, 0x17}, {0x08c8, 0x13}, 391 + {0x1990, 0x74}, {0x1d64, 0x17}, 392 + {0x18c8, 0x13}, {0x0d90, 0x40}, 393 + {0x0da8, 0x40}, {0x0dc0, 0x40}, 394 + {0x0dd8, 0x40}, {0x1d90, 0x40}, 395 + {0x1da8, 0x40}, {0x1dc0, 0x40}, 396 + {0x1dd8, 0x40}, {0x03c0, 0x30}, 397 + {0x03c4, 0x06}, {0x0e10, 0x00}, 398 + {0x1e10, 0x00}, {0x043c, 0x0f}, 399 + {0x0d2c, 0xff}, {0x1d2c, 0xff}, 400 + {0x0d34, 0x0f}, {0x1d34, 0x0f}, 401 + {0x08fc, 0x2a}, {0x0914, 0x28}, 402 + {0x0a30, 0x03}, {0x0e38, 0x03}, 403 + {0x0ecc, 0x27}, {0x0ed0, 0x22}, 404 + {0x0ed4, 0x26}, {0x18fc, 0x2a}, 405 + {0x1914, 0x28}, {0x1a30, 0x03}, 406 + {0x1e38, 0x03}, {0x1ecc, 0x27}, 407 + {0x1ed0, 0x22}, {0x1ed4, 0x26}, 408 + {0x0048, 0x0f}, {0x0060, 0x3c}, 409 + {0x0064, 0xf7}, {0x006c, 0x20}, 410 + {0x0070, 0x7d}, {0x0074, 0x68}, 411 + {0x0af4, 0x1a}, {0x1af4, 0x1a}, 412 + {0x0440, 0x3f}, {0x10d4, 0x08}, 413 + {0x20d4, 0x08}, {0x00d4, 0x30}, 414 + {0x0024, 0x6e}, 415 + }; 416 + 417 + static inline int rk_udphy_grfreg_write(struct regmap *base, 418 + const struct rk_udphy_grf_reg *reg, bool en) 419 + { 420 + return regmap_write(base, reg->offset, en ? reg->enable : reg->disable); 421 + } 422 + 423 + static int rk_udphy_clk_init(struct rk_udphy *udphy, struct device *dev) 424 + { 425 + int i; 426 + 427 + udphy->num_clks = devm_clk_bulk_get_all(dev, &udphy->clks); 428 + if (udphy->num_clks < 1) 429 + return -ENODEV; 430 + 431 + /* used for configure phy reference clock frequency */ 432 + for (i = 0; i < udphy->num_clks; i++) { 433 + if (!strncmp(udphy->clks[i].id, "refclk", 6)) { 434 + udphy->refclk = udphy->clks[i].clk; 435 + break; 436 + } 437 + } 438 + 439 + if (!udphy->refclk) 440 + return dev_err_probe(udphy->dev, -EINVAL, "no refclk found\n"); 441 + 442 + return 0; 443 + } 444 + 445 + static int rk_udphy_reset_assert_all(struct rk_udphy *udphy) 446 + { 447 + return reset_control_bulk_assert(udphy->num_rsts, udphy->rsts); 448 + } 449 + 450 + static int rk_udphy_reset_deassert_all(struct rk_udphy *udphy) 451 + { 452 + return reset_control_bulk_deassert(udphy->num_rsts, udphy->rsts); 453 + } 454 + 455 + static int rk_udphy_reset_deassert(struct rk_udphy *udphy, char *name) 456 + { 457 + struct reset_control_bulk_data *list = udphy->rsts; 458 + int idx; 459 + 460 + for (idx = 0; idx < udphy->num_rsts; idx++) { 461 + if (!strcmp(list[idx].id, name)) 462 + return reset_control_deassert(list[idx].rstc); 463 + } 464 + 465 + return -EINVAL; 466 + } 467 + 468 + static int rk_udphy_reset_init(struct rk_udphy *udphy, struct device *dev) 469 + { 470 + const struct rk_udphy_cfg *cfg = udphy->cfgs; 471 + int idx; 472 + 473 + udphy->num_rsts = cfg->num_rsts; 474 + udphy->rsts = devm_kcalloc(dev, udphy->num_rsts, 475 + sizeof(*udphy->rsts), GFP_KERNEL); 476 + if (!udphy->rsts) 477 + return -ENOMEM; 478 + 479 + for (idx = 0; idx < cfg->num_rsts; idx++) 480 + udphy->rsts[idx].id = cfg->rst_list[idx]; 481 + 482 + return devm_reset_control_bulk_get_exclusive(dev, cfg->num_rsts, 483 + udphy->rsts); 484 + } 485 + 486 + static void rk_udphy_u3_port_disable(struct rk_udphy *udphy, u8 disable) 487 + { 488 + const struct rk_udphy_cfg *cfg = udphy->cfgs; 489 + const struct rk_udphy_grf_reg *preg; 490 + 491 + preg = udphy->id ? &cfg->grfcfg.usb3otg1_cfg : &cfg->grfcfg.usb3otg0_cfg; 492 + rk_udphy_grfreg_write(udphy->usbgrf, preg, disable); 493 + } 494 + 495 + static void rk_udphy_usb_bvalid_enable(struct rk_udphy *udphy, u8 enable) 496 + { 497 + const struct rk_udphy_cfg *cfg = udphy->cfgs; 498 + 499 + rk_udphy_grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_phy_con, enable); 500 + rk_udphy_grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_grf_con, enable); 501 + } 502 + 503 + /* 504 + * In usb/dp combo phy driver, here are 2 ways to mapping lanes. 505 + * 506 + * 1 Type-C Mapping table (DP_Alt_Mode V1.0b remove ABF pin mapping) 507 + * --------------------------------------------------------------------------- 508 + * Type-C Pin B11-B10 A2-A3 A11-A10 B2-B3 509 + * PHY Pad ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) 510 + * C/E(Normal) dpln3 dpln2 dpln0 dpln1 511 + * C/E(Flip ) dpln0 dpln1 dpln3 dpln2 512 + * D/F(Normal) usbrx usbtx dpln0 dpln1 513 + * D/F(Flip ) dpln0 dpln1 usbrx usbtx 514 + * A(Normal ) dpln3 dpln1 dpln2 dpln0 515 + * A(Flip ) dpln2 dpln0 dpln3 dpln1 516 + * B(Normal ) usbrx usbtx dpln1 dpln0 517 + * B(Flip ) dpln1 dpln0 usbrx usbtx 518 + * --------------------------------------------------------------------------- 519 + * 520 + * 2 Mapping the lanes in dtsi 521 + * if all 4 lane assignment for dp function, define rockchip,dp-lane-mux = <x x x x>; 522 + * sample as follow: 523 + * --------------------------------------------------------------------------- 524 + * B11-B10 A2-A3 A11-A10 B2-B3 525 + * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) 526 + * <0 1 2 3> dpln0 dpln1 dpln2 dpln3 527 + * <2 3 0 1> dpln2 dpln3 dpln0 dpln1 528 + * --------------------------------------------------------------------------- 529 + * if 2 lane for dp function, 2 lane for usb function, define rockchip,dp-lane-mux = <x x>; 530 + * sample as follow: 531 + * --------------------------------------------------------------------------- 532 + * B11-B10 A2-A3 A11-A10 B2-B3 533 + * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) 534 + * <0 1> dpln0 dpln1 usbrx usbtx 535 + * <2 3> usbrx usbtx dpln0 dpln1 536 + * --------------------------------------------------------------------------- 537 + */ 538 + 539 + static void rk_udphy_dplane_select(struct rk_udphy *udphy) 540 + { 541 + const struct rk_udphy_cfg *cfg = udphy->cfgs; 542 + u32 value = 0; 543 + 544 + switch (udphy->mode) { 545 + case UDPHY_MODE_DP: 546 + value |= 2 << udphy->dp_lane_sel[2] * 2; 547 + value |= 3 << udphy->dp_lane_sel[3] * 2; 548 + fallthrough; 549 + 550 + case UDPHY_MODE_DP_USB: 551 + value |= 0 << udphy->dp_lane_sel[0] * 2; 552 + value |= 1 << udphy->dp_lane_sel[1] * 2; 553 + break; 554 + 555 + case UDPHY_MODE_USB: 556 + break; 557 + 558 + default: 559 + break; 560 + } 561 + 562 + regmap_write(udphy->vogrf, cfg->vogrfcfg[udphy->id].dp_lane_reg, 563 + ((DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL) << 16) | 564 + FIELD_PREP(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel) | 565 + FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value); 566 + } 567 + 568 + static int rk_udphy_dplane_get(struct rk_udphy *udphy) 569 + { 570 + int dp_lanes; 571 + 572 + switch (udphy->mode) { 573 + case UDPHY_MODE_DP: 574 + dp_lanes = 4; 575 + break; 576 + 577 + case UDPHY_MODE_DP_USB: 578 + dp_lanes = 2; 579 + break; 580 + 581 + case UDPHY_MODE_USB: 582 + default: 583 + dp_lanes = 0; 584 + break; 585 + } 586 + 587 + return dp_lanes; 588 + } 589 + 590 + static void rk_udphy_dplane_enable(struct rk_udphy *udphy, int dp_lanes) 591 + { 592 + u32 val = 0; 593 + int i; 594 + 595 + for (i = 0; i < dp_lanes; i++) 596 + val |= BIT(udphy->dp_lane_sel[i]); 597 + 598 + regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, CMN_DP_LANE_EN_ALL, 599 + FIELD_PREP(CMN_DP_LANE_EN_ALL, val)); 600 + 601 + if (!dp_lanes) 602 + regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, 603 + CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); 604 + } 605 + 606 + static void rk_udphy_dp_hpd_event_trigger(struct rk_udphy *udphy, bool hpd) 607 + { 608 + const struct rk_udphy_cfg *cfg = udphy->cfgs; 609 + 610 + udphy->dp_sink_hpd_sel = true; 611 + udphy->dp_sink_hpd_cfg = hpd; 612 + 613 + if (!udphy->dp_in_use) 614 + return; 615 + 616 + rk_udphy_grfreg_write(udphy->vogrf, &cfg->vogrfcfg[udphy->id].hpd_trigger, hpd); 617 + } 618 + 619 + static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy) 620 + { 621 + if (udphy->flip) { 622 + udphy->dp_lane_sel[0] = 0; 623 + udphy->dp_lane_sel[1] = 1; 624 + udphy->dp_lane_sel[2] = 3; 625 + udphy->dp_lane_sel[3] = 2; 626 + udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; 627 + udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; 628 + udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB; 629 + udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB; 630 + udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_INVERT; 631 + udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_INVERT; 632 + gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 1); 633 + gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0); 634 + } else { 635 + udphy->dp_lane_sel[0] = 2; 636 + udphy->dp_lane_sel[1] = 3; 637 + udphy->dp_lane_sel[2] = 1; 638 + udphy->dp_lane_sel[3] = 0; 639 + udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB; 640 + udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB; 641 + udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; 642 + udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; 643 + udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_NORMAL; 644 + udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_NORMAL; 645 + gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0); 646 + gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 1); 647 + } 648 + 649 + udphy->mode = UDPHY_MODE_DP_USB; 650 + } 651 + 652 + static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw, 653 + enum typec_orientation orien) 654 + { 655 + struct rk_udphy *udphy = typec_switch_get_drvdata(sw); 656 + 657 + mutex_lock(&udphy->mutex); 658 + 659 + if (orien == TYPEC_ORIENTATION_NONE) { 660 + gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0); 661 + gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0); 662 + /* unattached */ 663 + rk_udphy_usb_bvalid_enable(udphy, false); 664 + goto unlock_ret; 665 + } 666 + 667 + udphy->flip = (orien == TYPEC_ORIENTATION_REVERSE) ? true : false; 668 + rk_udphy_set_typec_default_mapping(udphy); 669 + rk_udphy_usb_bvalid_enable(udphy, true); 670 + 671 + unlock_ret: 672 + mutex_unlock(&udphy->mutex); 673 + return 0; 674 + } 675 + 676 + static void rk_udphy_orien_switch_unregister(void *data) 677 + { 678 + struct rk_udphy *udphy = data; 679 + 680 + typec_switch_unregister(udphy->sw); 681 + } 682 + 683 + static int rk_udphy_setup_orien_switch(struct rk_udphy *udphy) 684 + { 685 + struct typec_switch_desc sw_desc = { }; 686 + 687 + sw_desc.drvdata = udphy; 688 + sw_desc.fwnode = dev_fwnode(udphy->dev); 689 + sw_desc.set = rk_udphy_orien_sw_set; 690 + 691 + udphy->sw = typec_switch_register(udphy->dev, &sw_desc); 692 + if (IS_ERR(udphy->sw)) { 693 + dev_err(udphy->dev, "Error register typec orientation switch: %ld\n", 694 + PTR_ERR(udphy->sw)); 695 + return PTR_ERR(udphy->sw); 696 + } 697 + 698 + return devm_add_action_or_reset(udphy->dev, 699 + rk_udphy_orien_switch_unregister, udphy); 700 + } 701 + 702 + static int rk_udphy_refclk_set(struct rk_udphy *udphy) 703 + { 704 + unsigned long rate; 705 + int ret; 706 + 707 + /* configure phy reference clock */ 708 + rate = clk_get_rate(udphy->refclk); 709 + dev_dbg(udphy->dev, "refclk freq %ld\n", rate); 710 + 711 + switch (rate) { 712 + case 24000000: 713 + ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_24m_refclk_cfg, 714 + ARRAY_SIZE(rk_udphy_24m_refclk_cfg)); 715 + if (ret) 716 + return ret; 717 + break; 718 + 719 + case 26000000: 720 + /* register default is 26MHz */ 721 + ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_26m_refclk_cfg, 722 + ARRAY_SIZE(rk_udphy_26m_refclk_cfg)); 723 + if (ret) 724 + return ret; 725 + break; 726 + 727 + default: 728 + dev_err(udphy->dev, "unsupported refclk freq %ld\n", rate); 729 + return -EINVAL; 730 + } 731 + 732 + return 0; 733 + } 734 + 735 + static int rk_udphy_status_check(struct rk_udphy *udphy) 736 + { 737 + unsigned int val; 738 + int ret; 739 + 740 + /* LCPLL check */ 741 + if (udphy->mode & UDPHY_MODE_USB) { 742 + ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_LCPLL_DONE_OFFSET, 743 + val, (val & CMN_ANA_LCPLL_AFC_DONE) && 744 + (val & CMN_ANA_LCPLL_LOCK_DONE), 200, 100000); 745 + if (ret) { 746 + dev_err(udphy->dev, "cmn ana lcpll lock timeout\n"); 747 + /* 748 + * If earlier software (U-Boot) enabled USB once already 749 + * the PLL may have problems locking on the first try. 750 + * It will be successful on the second try, so for the 751 + * time being a -EPROBE_DEFER will solve the issue. 752 + * 753 + * This requires further investigation to understand the 754 + * root cause, especially considering that the driver is 755 + * asserting all reset lines at probe time. 756 + */ 757 + return -EPROBE_DEFER; 758 + } 759 + 760 + if (!udphy->flip) { 761 + ret = regmap_read_poll_timeout(udphy->pma_regmap, 762 + TRSV_LN0_MON_RX_CDR_DONE_OFFSET, val, 763 + val & TRSV_LN0_MON_RX_CDR_LOCK_DONE, 764 + 200, 100000); 765 + if (ret) 766 + dev_err(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n"); 767 + } else { 768 + ret = regmap_read_poll_timeout(udphy->pma_regmap, 769 + TRSV_LN2_MON_RX_CDR_DONE_OFFSET, val, 770 + val & TRSV_LN2_MON_RX_CDR_LOCK_DONE, 771 + 200, 100000); 772 + if (ret) 773 + dev_err(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n"); 774 + } 775 + } 776 + 777 + return 0; 778 + } 779 + 780 + static int rk_udphy_init(struct rk_udphy *udphy) 781 + { 782 + const struct rk_udphy_cfg *cfg = udphy->cfgs; 783 + int ret; 784 + 785 + rk_udphy_reset_assert_all(udphy); 786 + usleep_range(10000, 11000); 787 + 788 + /* enable rx lfps for usb */ 789 + if (udphy->mode & UDPHY_MODE_USB) 790 + rk_udphy_grfreg_write(udphy->udphygrf, &cfg->grfcfg.rx_lfps, true); 791 + 792 + /* Step 1: power on pma and deassert apb rstn */ 793 + rk_udphy_grfreg_write(udphy->udphygrf, &cfg->grfcfg.low_pwrn, true); 794 + 795 + rk_udphy_reset_deassert(udphy, "pma_apb"); 796 + rk_udphy_reset_deassert(udphy, "pcs_apb"); 797 + 798 + /* Step 2: set init sequence and phy refclk */ 799 + ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_init_sequence, 800 + ARRAY_SIZE(rk_udphy_init_sequence)); 801 + if (ret) { 802 + dev_err(udphy->dev, "init sequence set error %d\n", ret); 803 + goto assert_resets; 804 + } 805 + 806 + ret = rk_udphy_refclk_set(udphy); 807 + if (ret) { 808 + dev_err(udphy->dev, "refclk set error %d\n", ret); 809 + goto assert_resets; 810 + } 811 + 812 + /* Step 3: configure lane mux */ 813 + regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, 814 + CMN_DP_LANE_MUX_ALL | CMN_DP_LANE_EN_ALL, 815 + FIELD_PREP(CMN_DP_LANE_MUX_N(3), udphy->lane_mux_sel[3]) | 816 + FIELD_PREP(CMN_DP_LANE_MUX_N(2), udphy->lane_mux_sel[2]) | 817 + FIELD_PREP(CMN_DP_LANE_MUX_N(1), udphy->lane_mux_sel[1]) | 818 + FIELD_PREP(CMN_DP_LANE_MUX_N(0), udphy->lane_mux_sel[0]) | 819 + FIELD_PREP(CMN_DP_LANE_EN_ALL, 0)); 820 + 821 + /* Step 4: deassert init rstn and wait for 200ns from datasheet */ 822 + if (udphy->mode & UDPHY_MODE_USB) 823 + rk_udphy_reset_deassert(udphy, "init"); 824 + 825 + if (udphy->mode & UDPHY_MODE_DP) { 826 + regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, 827 + CMN_DP_INIT_RSTN, 828 + FIELD_PREP(CMN_DP_INIT_RSTN, 0x1)); 829 + } 830 + 831 + udelay(1); 832 + 833 + /* Step 5: deassert cmn/lane rstn */ 834 + if (udphy->mode & UDPHY_MODE_USB) { 835 + rk_udphy_reset_deassert(udphy, "cmn"); 836 + rk_udphy_reset_deassert(udphy, "lane"); 837 + } 838 + 839 + /* Step 6: wait for lock done of pll */ 840 + ret = rk_udphy_status_check(udphy); 841 + if (ret) 842 + goto assert_resets; 843 + 844 + return 0; 845 + 846 + assert_resets: 847 + rk_udphy_reset_assert_all(udphy); 848 + return ret; 849 + } 850 + 851 + static int rk_udphy_setup(struct rk_udphy *udphy) 852 + { 853 + int ret; 854 + 855 + ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks); 856 + if (ret) { 857 + dev_err(udphy->dev, "failed to enable clk\n"); 858 + return ret; 859 + } 860 + 861 + ret = rk_udphy_init(udphy); 862 + if (ret) { 863 + dev_err(udphy->dev, "failed to init combophy\n"); 864 + clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks); 865 + return ret; 866 + } 867 + 868 + return 0; 869 + } 870 + 871 + static void rk_udphy_disable(struct rk_udphy *udphy) 872 + { 873 + clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks); 874 + rk_udphy_reset_assert_all(udphy); 875 + } 876 + 877 + static int rk_udphy_parse_lane_mux_data(struct rk_udphy *udphy) 878 + { 879 + int ret, i, num_lanes; 880 + 881 + num_lanes = device_property_count_u32(udphy->dev, "rockchip,dp-lane-mux"); 882 + if (num_lanes < 0) { 883 + dev_dbg(udphy->dev, "no dp-lane-mux, following dp alt mode\n"); 884 + udphy->mode = UDPHY_MODE_USB; 885 + return 0; 886 + } 887 + 888 + if (num_lanes != 2 && num_lanes != 4) 889 + return dev_err_probe(udphy->dev, -EINVAL, 890 + "invalid number of lane mux\n"); 891 + 892 + ret = device_property_read_u32_array(udphy->dev, "rockchip,dp-lane-mux", 893 + udphy->dp_lane_sel, num_lanes); 894 + if (ret) 895 + return dev_err_probe(udphy->dev, ret, "get dp lane mux failed\n"); 896 + 897 + for (i = 0; i < num_lanes; i++) { 898 + int j; 899 + 900 + if (udphy->dp_lane_sel[i] > 3) 901 + return dev_err_probe(udphy->dev, -EINVAL, 902 + "lane mux between 0 and 3, exceeding the range\n"); 903 + 904 + udphy->lane_mux_sel[udphy->dp_lane_sel[i]] = PHY_LANE_MUX_DP; 905 + 906 + for (j = i + 1; j < num_lanes; j++) { 907 + if (udphy->dp_lane_sel[i] == udphy->dp_lane_sel[j]) 908 + return dev_err_probe(udphy->dev, -EINVAL, 909 + "set repeat lane mux value\n"); 910 + } 911 + } 912 + 913 + udphy->mode = UDPHY_MODE_DP; 914 + if (num_lanes == 2) { 915 + udphy->mode |= UDPHY_MODE_USB; 916 + udphy->flip = (udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP); 917 + } 918 + 919 + return 0; 920 + } 921 + 922 + static int rk_udphy_get_initial_status(struct rk_udphy *udphy) 923 + { 924 + int ret; 925 + u32 value; 926 + 927 + ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks); 928 + if (ret) { 929 + dev_err(udphy->dev, "failed to enable clk\n"); 930 + return ret; 931 + } 932 + 933 + rk_udphy_reset_deassert_all(udphy); 934 + 935 + regmap_read(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, &value); 936 + if (FIELD_GET(CMN_DP_LANE_MUX_ALL, value) && FIELD_GET(CMN_DP_LANE_EN_ALL, value)) 937 + udphy->status = UDPHY_MODE_DP; 938 + else 939 + rk_udphy_disable(udphy); 940 + 941 + return 0; 942 + } 943 + 944 + static int rk_udphy_parse_dt(struct rk_udphy *udphy) 945 + { 946 + struct device *dev = udphy->dev; 947 + struct device_node *np = dev_of_node(dev); 948 + enum usb_device_speed maximum_speed; 949 + int ret; 950 + 951 + udphy->u2phygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,u2phy-grf"); 952 + if (IS_ERR(udphy->u2phygrf)) 953 + return dev_err_probe(dev, PTR_ERR(udphy->u2phygrf), "failed to get u2phy-grf\n"); 954 + 955 + udphy->udphygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbdpphy-grf"); 956 + if (IS_ERR(udphy->udphygrf)) 957 + return dev_err_probe(dev, PTR_ERR(udphy->udphygrf), "failed to get usbdpphy-grf\n"); 958 + 959 + udphy->usbgrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usb-grf"); 960 + if (IS_ERR(udphy->usbgrf)) 961 + return dev_err_probe(dev, PTR_ERR(udphy->usbgrf), "failed to get usb-grf\n"); 962 + 963 + udphy->vogrf = syscon_regmap_lookup_by_phandle(np, "rockchip,vo-grf"); 964 + if (IS_ERR(udphy->vogrf)) 965 + return dev_err_probe(dev, PTR_ERR(udphy->vogrf), "failed to get vo-grf\n"); 966 + 967 + ret = rk_udphy_parse_lane_mux_data(udphy); 968 + if (ret) 969 + return ret; 970 + 971 + udphy->sbu1_dc_gpio = devm_gpiod_get_optional(dev, "sbu1-dc", GPIOD_OUT_LOW); 972 + if (IS_ERR(udphy->sbu1_dc_gpio)) 973 + return PTR_ERR(udphy->sbu1_dc_gpio); 974 + 975 + udphy->sbu2_dc_gpio = devm_gpiod_get_optional(dev, "sbu2-dc", GPIOD_OUT_LOW); 976 + if (IS_ERR(udphy->sbu2_dc_gpio)) 977 + return PTR_ERR(udphy->sbu2_dc_gpio); 978 + 979 + if (device_property_present(dev, "maximum-speed")) { 980 + maximum_speed = usb_get_maximum_speed(dev); 981 + udphy->hs = maximum_speed <= USB_SPEED_HIGH ? true : false; 982 + } 983 + 984 + ret = rk_udphy_clk_init(udphy, dev); 985 + if (ret) 986 + return ret; 987 + 988 + return rk_udphy_reset_init(udphy, dev); 989 + } 990 + 991 + static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode) 992 + { 993 + int ret; 994 + 995 + if (!(udphy->mode & mode)) { 996 + dev_info(udphy->dev, "mode 0x%02x is not support\n", mode); 997 + return 0; 998 + } 999 + 1000 + if (udphy->status == UDPHY_MODE_NONE) { 1001 + udphy->mode_change = false; 1002 + ret = rk_udphy_setup(udphy); 1003 + if (ret) 1004 + return ret; 1005 + 1006 + if (udphy->mode & UDPHY_MODE_USB) 1007 + rk_udphy_u3_port_disable(udphy, false); 1008 + } else if (udphy->mode_change) { 1009 + udphy->mode_change = false; 1010 + udphy->status = UDPHY_MODE_NONE; 1011 + if (udphy->mode == UDPHY_MODE_DP) 1012 + rk_udphy_u3_port_disable(udphy, true); 1013 + 1014 + rk_udphy_disable(udphy); 1015 + ret = rk_udphy_setup(udphy); 1016 + if (ret) 1017 + return ret; 1018 + } 1019 + 1020 + udphy->status |= mode; 1021 + 1022 + return 0; 1023 + } 1024 + 1025 + static void rk_udphy_power_off(struct rk_udphy *udphy, u8 mode) 1026 + { 1027 + if (!(udphy->mode & mode)) { 1028 + dev_info(udphy->dev, "mode 0x%02x is not support\n", mode); 1029 + return; 1030 + } 1031 + 1032 + if (!udphy->status) 1033 + return; 1034 + 1035 + udphy->status &= ~mode; 1036 + 1037 + if (udphy->status == UDPHY_MODE_NONE) 1038 + rk_udphy_disable(udphy); 1039 + } 1040 + 1041 + static int rk_udphy_dp_phy_init(struct phy *phy) 1042 + { 1043 + struct rk_udphy *udphy = phy_get_drvdata(phy); 1044 + 1045 + mutex_lock(&udphy->mutex); 1046 + 1047 + udphy->dp_in_use = true; 1048 + rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg); 1049 + 1050 + mutex_unlock(&udphy->mutex); 1051 + 1052 + return 0; 1053 + } 1054 + 1055 + static int rk_udphy_dp_phy_exit(struct phy *phy) 1056 + { 1057 + struct rk_udphy *udphy = phy_get_drvdata(phy); 1058 + 1059 + mutex_lock(&udphy->mutex); 1060 + udphy->dp_in_use = false; 1061 + mutex_unlock(&udphy->mutex); 1062 + return 0; 1063 + } 1064 + 1065 + static int rk_udphy_dp_phy_power_on(struct phy *phy) 1066 + { 1067 + struct rk_udphy *udphy = phy_get_drvdata(phy); 1068 + int ret, dp_lanes; 1069 + 1070 + mutex_lock(&udphy->mutex); 1071 + 1072 + dp_lanes = rk_udphy_dplane_get(udphy); 1073 + phy_set_bus_width(phy, dp_lanes); 1074 + 1075 + ret = rk_udphy_power_on(udphy, UDPHY_MODE_DP); 1076 + if (ret) 1077 + goto unlock; 1078 + 1079 + rk_udphy_dplane_enable(udphy, dp_lanes); 1080 + 1081 + rk_udphy_dplane_select(udphy); 1082 + 1083 + unlock: 1084 + mutex_unlock(&udphy->mutex); 1085 + /* 1086 + * If data send by aux channel too fast after phy power on, 1087 + * the aux may be not ready which will cause aux error. Adding 1088 + * delay to avoid this issue. 1089 + */ 1090 + usleep_range(10000, 11000); 1091 + return ret; 1092 + } 1093 + 1094 + static int rk_udphy_dp_phy_power_off(struct phy *phy) 1095 + { 1096 + struct rk_udphy *udphy = phy_get_drvdata(phy); 1097 + 1098 + mutex_lock(&udphy->mutex); 1099 + rk_udphy_dplane_enable(udphy, 0); 1100 + rk_udphy_power_off(udphy, UDPHY_MODE_DP); 1101 + mutex_unlock(&udphy->mutex); 1102 + 1103 + return 0; 1104 + } 1105 + 1106 + static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate) 1107 + { 1108 + switch (link_rate) { 1109 + case 1620: 1110 + case 2700: 1111 + case 5400: 1112 + case 8100: 1113 + break; 1114 + 1115 + default: 1116 + return -EINVAL; 1117 + } 1118 + 1119 + return 0; 1120 + } 1121 + 1122 + static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy, 1123 + struct phy_configure_opts_dp *dp) 1124 + { 1125 + int i, ret; 1126 + 1127 + /* If changing link rate was required, verify it's supported. */ 1128 + ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate); 1129 + if (ret) 1130 + return ret; 1131 + 1132 + /* Verify lane count. */ 1133 + switch (dp->lanes) { 1134 + case 1: 1135 + case 2: 1136 + case 4: 1137 + /* valid lane count. */ 1138 + break; 1139 + 1140 + default: 1141 + return -EINVAL; 1142 + } 1143 + 1144 + /* 1145 + * If changing voltages is required, check swing and pre-emphasis 1146 + * levels, per-lane. 1147 + */ 1148 + if (dp->set_voltages) { 1149 + /* Lane count verified previously. */ 1150 + for (i = 0; i < dp->lanes; i++) { 1151 + if (dp->voltage[i] > 3 || dp->pre[i] > 3) 1152 + return -EINVAL; 1153 + 1154 + /* 1155 + * Sum of voltage swing and pre-emphasis levels cannot 1156 + * exceed 3. 1157 + */ 1158 + if (dp->voltage[i] + dp->pre[i] > 3) 1159 + return -EINVAL; 1160 + } 1161 + } 1162 + 1163 + return 0; 1164 + } 1165 + 1166 + static void rk_udphy_dp_set_voltage(struct rk_udphy *udphy, u8 bw, 1167 + u32 voltage, u32 pre, u32 lane) 1168 + { 1169 + const struct rk_udphy_cfg *cfg = udphy->cfgs; 1170 + const struct rk_udphy_dp_tx_drv_ctrl (*dp_ctrl)[4]; 1171 + u32 offset = 0x800 * lane; 1172 + u32 val; 1173 + 1174 + if (udphy->mux) 1175 + dp_ctrl = cfg->dp_tx_ctrl_cfg_typec[bw]; 1176 + else 1177 + dp_ctrl = cfg->dp_tx_ctrl_cfg[bw]; 1178 + 1179 + val = dp_ctrl[voltage][pre].trsv_reg0204; 1180 + regmap_write(udphy->pma_regmap, 0x0810 + offset, val); 1181 + 1182 + val = dp_ctrl[voltage][pre].trsv_reg0205; 1183 + regmap_write(udphy->pma_regmap, 0x0814 + offset, val); 1184 + 1185 + val = dp_ctrl[voltage][pre].trsv_reg0206; 1186 + regmap_write(udphy->pma_regmap, 0x0818 + offset, val); 1187 + 1188 + val = dp_ctrl[voltage][pre].trsv_reg0207; 1189 + regmap_write(udphy->pma_regmap, 0x081c + offset, val); 1190 + } 1191 + 1192 + static int rk_udphy_dp_phy_configure(struct phy *phy, 1193 + union phy_configure_opts *opts) 1194 + { 1195 + struct rk_udphy *udphy = phy_get_drvdata(phy); 1196 + struct phy_configure_opts_dp *dp = &opts->dp; 1197 + u32 i, val, lane; 1198 + int ret; 1199 + 1200 + ret = rk_udphy_dp_phy_verify_config(udphy, dp); 1201 + if (ret) 1202 + return ret; 1203 + 1204 + if (dp->set_rate) { 1205 + regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, 1206 + CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); 1207 + 1208 + switch (dp->link_rate) { 1209 + case 1620: 1210 + udphy->bw = DP_BW_RBR; 1211 + break; 1212 + 1213 + case 2700: 1214 + udphy->bw = DP_BW_HBR; 1215 + break; 1216 + 1217 + case 5400: 1218 + udphy->bw = DP_BW_HBR2; 1219 + break; 1220 + 1221 + case 8100: 1222 + udphy->bw = DP_BW_HBR3; 1223 + break; 1224 + 1225 + default: 1226 + return -EINVAL; 1227 + } 1228 + 1229 + regmap_update_bits(udphy->pma_regmap, CMN_DP_LINK_OFFSET, CMN_DP_TX_LINK_BW, 1230 + FIELD_PREP(CMN_DP_TX_LINK_BW, udphy->bw)); 1231 + regmap_update_bits(udphy->pma_regmap, CMN_SSC_EN_OFFSET, CMN_ROPLL_SSC_EN, 1232 + FIELD_PREP(CMN_ROPLL_SSC_EN, dp->ssc)); 1233 + regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, CMN_DP_CMN_RSTN, 1234 + FIELD_PREP(CMN_DP_CMN_RSTN, 0x1)); 1235 + 1236 + ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_ROPLL_DONE_OFFSET, val, 1237 + FIELD_GET(CMN_ANA_ROPLL_LOCK_DONE, val) && 1238 + FIELD_GET(CMN_ANA_ROPLL_AFC_DONE, val), 1239 + 0, 1000); 1240 + if (ret) { 1241 + dev_err(udphy->dev, "ROPLL is not lock, set_rate failed\n"); 1242 + return ret; 1243 + } 1244 + } 1245 + 1246 + if (dp->set_voltages) { 1247 + for (i = 0; i < dp->lanes; i++) { 1248 + lane = udphy->dp_lane_sel[i]; 1249 + switch (dp->link_rate) { 1250 + case 1620: 1251 + case 2700: 1252 + regmap_update_bits(udphy->pma_regmap, 1253 + TRSV_ANA_TX_CLK_OFFSET_N(lane), 1254 + LN_ANA_TX_SER_TXCLK_INV, 1255 + FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, 1256 + udphy->lane_mux_sel[lane])); 1257 + break; 1258 + 1259 + case 5400: 1260 + case 8100: 1261 + regmap_update_bits(udphy->pma_regmap, 1262 + TRSV_ANA_TX_CLK_OFFSET_N(lane), 1263 + LN_ANA_TX_SER_TXCLK_INV, 1264 + FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, 0x0)); 1265 + break; 1266 + } 1267 + 1268 + rk_udphy_dp_set_voltage(udphy, udphy->bw, dp->voltage[i], 1269 + dp->pre[i], lane); 1270 + } 1271 + } 1272 + 1273 + return 0; 1274 + } 1275 + 1276 + static const struct phy_ops rk_udphy_dp_phy_ops = { 1277 + .init = rk_udphy_dp_phy_init, 1278 + .exit = rk_udphy_dp_phy_exit, 1279 + .power_on = rk_udphy_dp_phy_power_on, 1280 + .power_off = rk_udphy_dp_phy_power_off, 1281 + .configure = rk_udphy_dp_phy_configure, 1282 + .owner = THIS_MODULE, 1283 + }; 1284 + 1285 + static int rk_udphy_usb3_phy_init(struct phy *phy) 1286 + { 1287 + struct rk_udphy *udphy = phy_get_drvdata(phy); 1288 + int ret = 0; 1289 + 1290 + mutex_lock(&udphy->mutex); 1291 + /* DP only or high-speed, disable U3 port */ 1292 + if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) { 1293 + rk_udphy_u3_port_disable(udphy, true); 1294 + goto unlock; 1295 + } 1296 + 1297 + ret = rk_udphy_power_on(udphy, UDPHY_MODE_USB); 1298 + 1299 + unlock: 1300 + mutex_unlock(&udphy->mutex); 1301 + return ret; 1302 + } 1303 + 1304 + static int rk_udphy_usb3_phy_exit(struct phy *phy) 1305 + { 1306 + struct rk_udphy *udphy = phy_get_drvdata(phy); 1307 + 1308 + mutex_lock(&udphy->mutex); 1309 + /* DP only or high-speed */ 1310 + if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) 1311 + goto unlock; 1312 + 1313 + rk_udphy_power_off(udphy, UDPHY_MODE_USB); 1314 + 1315 + unlock: 1316 + mutex_unlock(&udphy->mutex); 1317 + return 0; 1318 + } 1319 + 1320 + static const struct phy_ops rk_udphy_usb3_phy_ops = { 1321 + .init = rk_udphy_usb3_phy_init, 1322 + .exit = rk_udphy_usb3_phy_exit, 1323 + .owner = THIS_MODULE, 1324 + }; 1325 + 1326 + static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux, 1327 + struct typec_mux_state *state) 1328 + { 1329 + struct rk_udphy *udphy = typec_mux_get_drvdata(mux); 1330 + u8 mode; 1331 + 1332 + mutex_lock(&udphy->mutex); 1333 + 1334 + switch (state->mode) { 1335 + case TYPEC_DP_STATE_C: 1336 + case TYPEC_DP_STATE_E: 1337 + udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; 1338 + udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; 1339 + udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; 1340 + udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; 1341 + mode = UDPHY_MODE_DP; 1342 + break; 1343 + 1344 + case TYPEC_DP_STATE_D: 1345 + default: 1346 + if (udphy->flip) { 1347 + udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; 1348 + udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; 1349 + udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB; 1350 + udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB; 1351 + } else { 1352 + udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB; 1353 + udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB; 1354 + udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; 1355 + udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; 1356 + } 1357 + mode = UDPHY_MODE_DP_USB; 1358 + break; 1359 + } 1360 + 1361 + if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) { 1362 + struct typec_displayport_data *data = state->data; 1363 + 1364 + if (!data) { 1365 + rk_udphy_dp_hpd_event_trigger(udphy, false); 1366 + } else if (data->status & DP_STATUS_IRQ_HPD) { 1367 + rk_udphy_dp_hpd_event_trigger(udphy, false); 1368 + usleep_range(750, 800); 1369 + rk_udphy_dp_hpd_event_trigger(udphy, true); 1370 + } else if (data->status & DP_STATUS_HPD_STATE) { 1371 + if (udphy->mode != mode) { 1372 + udphy->mode = mode; 1373 + udphy->mode_change = true; 1374 + } 1375 + rk_udphy_dp_hpd_event_trigger(udphy, true); 1376 + } else { 1377 + rk_udphy_dp_hpd_event_trigger(udphy, false); 1378 + } 1379 + } 1380 + 1381 + mutex_unlock(&udphy->mutex); 1382 + return 0; 1383 + } 1384 + 1385 + static void rk_udphy_typec_mux_unregister(void *data) 1386 + { 1387 + struct rk_udphy *udphy = data; 1388 + 1389 + typec_mux_unregister(udphy->mux); 1390 + } 1391 + 1392 + static int rk_udphy_setup_typec_mux(struct rk_udphy *udphy) 1393 + { 1394 + struct typec_mux_desc mux_desc = {}; 1395 + 1396 + mux_desc.drvdata = udphy; 1397 + mux_desc.fwnode = dev_fwnode(udphy->dev); 1398 + mux_desc.set = rk_udphy_typec_mux_set; 1399 + 1400 + udphy->mux = typec_mux_register(udphy->dev, &mux_desc); 1401 + if (IS_ERR(udphy->mux)) { 1402 + dev_err(udphy->dev, "Error register typec mux: %ld\n", 1403 + PTR_ERR(udphy->mux)); 1404 + return PTR_ERR(udphy->mux); 1405 + } 1406 + 1407 + return devm_add_action_or_reset(udphy->dev, rk_udphy_typec_mux_unregister, 1408 + udphy); 1409 + } 1410 + 1411 + static const struct regmap_config rk_udphy_pma_regmap_cfg = { 1412 + .reg_bits = 32, 1413 + .reg_stride = 4, 1414 + .val_bits = 32, 1415 + .fast_io = true, 1416 + .max_register = 0x20dc, 1417 + }; 1418 + 1419 + static struct phy *rk_udphy_phy_xlate(struct device *dev, const struct of_phandle_args *args) 1420 + { 1421 + struct rk_udphy *udphy = dev_get_drvdata(dev); 1422 + 1423 + if (args->args_count == 0) 1424 + return ERR_PTR(-EINVAL); 1425 + 1426 + switch (args->args[0]) { 1427 + case PHY_TYPE_USB3: 1428 + return udphy->phy_u3; 1429 + case PHY_TYPE_DP: 1430 + return udphy->phy_dp; 1431 + } 1432 + 1433 + return ERR_PTR(-EINVAL); 1434 + } 1435 + 1436 + static int rk_udphy_probe(struct platform_device *pdev) 1437 + { 1438 + struct device *dev = &pdev->dev; 1439 + struct phy_provider *phy_provider; 1440 + struct resource *res; 1441 + struct rk_udphy *udphy; 1442 + void __iomem *base; 1443 + int id, ret; 1444 + 1445 + udphy = devm_kzalloc(dev, sizeof(*udphy), GFP_KERNEL); 1446 + if (!udphy) 1447 + return -ENOMEM; 1448 + 1449 + udphy->cfgs = device_get_match_data(dev); 1450 + if (!udphy->cfgs) 1451 + return dev_err_probe(dev, -EINVAL, "missing match data\n"); 1452 + 1453 + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 1454 + if (IS_ERR(base)) 1455 + return PTR_ERR(base); 1456 + 1457 + /* find the phy-id from the io address */ 1458 + udphy->id = -ENODEV; 1459 + for (id = 0; id < udphy->cfgs->num_phys; id++) { 1460 + if (res->start == udphy->cfgs->phy_ids[id]) { 1461 + udphy->id = id; 1462 + break; 1463 + } 1464 + } 1465 + 1466 + if (udphy->id < 0) 1467 + return dev_err_probe(dev, -ENODEV, "no matching device found\n"); 1468 + 1469 + udphy->pma_regmap = devm_regmap_init_mmio(dev, base + UDPHY_PMA, 1470 + &rk_udphy_pma_regmap_cfg); 1471 + if (IS_ERR(udphy->pma_regmap)) 1472 + return PTR_ERR(udphy->pma_regmap); 1473 + 1474 + udphy->dev = dev; 1475 + ret = rk_udphy_parse_dt(udphy); 1476 + if (ret) 1477 + return ret; 1478 + 1479 + ret = rk_udphy_get_initial_status(udphy); 1480 + if (ret) 1481 + return ret; 1482 + 1483 + mutex_init(&udphy->mutex); 1484 + platform_set_drvdata(pdev, udphy); 1485 + 1486 + if (device_property_present(dev, "orientation-switch")) { 1487 + ret = rk_udphy_setup_orien_switch(udphy); 1488 + if (ret) 1489 + return ret; 1490 + } 1491 + 1492 + if (device_property_present(dev, "mode-switch")) { 1493 + ret = rk_udphy_setup_typec_mux(udphy); 1494 + if (ret) 1495 + return ret; 1496 + } 1497 + 1498 + udphy->phy_u3 = devm_phy_create(dev, dev->of_node, &rk_udphy_usb3_phy_ops); 1499 + if (IS_ERR(udphy->phy_u3)) { 1500 + ret = PTR_ERR(udphy->phy_u3); 1501 + return dev_err_probe(dev, ret, "failed to create USB3 phy\n"); 1502 + } 1503 + phy_set_drvdata(udphy->phy_u3, udphy); 1504 + 1505 + udphy->phy_dp = devm_phy_create(dev, dev->of_node, &rk_udphy_dp_phy_ops); 1506 + if (IS_ERR(udphy->phy_dp)) { 1507 + ret = PTR_ERR(udphy->phy_dp); 1508 + return dev_err_probe(dev, ret, "failed to create DP phy\n"); 1509 + } 1510 + phy_set_bus_width(udphy->phy_dp, rk_udphy_dplane_get(udphy)); 1511 + udphy->phy_dp->attrs.max_link_rate = 8100; 1512 + phy_set_drvdata(udphy->phy_dp, udphy); 1513 + 1514 + phy_provider = devm_of_phy_provider_register(dev, rk_udphy_phy_xlate); 1515 + if (IS_ERR(phy_provider)) { 1516 + ret = PTR_ERR(phy_provider); 1517 + return dev_err_probe(dev, ret, "failed to register phy provider\n"); 1518 + } 1519 + 1520 + return 0; 1521 + } 1522 + 1523 + static int __maybe_unused rk_udphy_resume(struct device *dev) 1524 + { 1525 + struct rk_udphy *udphy = dev_get_drvdata(dev); 1526 + 1527 + if (udphy->dp_sink_hpd_sel) 1528 + rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg); 1529 + 1530 + return 0; 1531 + } 1532 + 1533 + static const struct dev_pm_ops rk_udphy_pm_ops = { 1534 + SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, rk_udphy_resume) 1535 + }; 1536 + 1537 + static const char * const rk_udphy_rst_list[] = { 1538 + "init", "cmn", "lane", "pcs_apb", "pma_apb" 1539 + }; 1540 + 1541 + static const struct rk_udphy_cfg rk3588_udphy_cfgs = { 1542 + .num_phys = 2, 1543 + .phy_ids = { 1544 + 0xfed80000, 1545 + 0xfed90000, 1546 + }, 1547 + .num_rsts = ARRAY_SIZE(rk_udphy_rst_list), 1548 + .rst_list = rk_udphy_rst_list, 1549 + .grfcfg = { 1550 + /* u2phy-grf */ 1551 + .bvalid_phy_con = RK_UDPHY_GEN_GRF_REG(0x0008, 1, 0, 0x2, 0x3), 1552 + .bvalid_grf_con = RK_UDPHY_GEN_GRF_REG(0x0010, 3, 2, 0x2, 0x3), 1553 + 1554 + /* usb-grf */ 1555 + .usb3otg0_cfg = RK_UDPHY_GEN_GRF_REG(0x001c, 15, 0, 0x1100, 0x0188), 1556 + .usb3otg1_cfg = RK_UDPHY_GEN_GRF_REG(0x0034, 15, 0, 0x1100, 0x0188), 1557 + 1558 + /* usbdpphy-grf */ 1559 + .low_pwrn = RK_UDPHY_GEN_GRF_REG(0x0004, 13, 13, 0, 1), 1560 + .rx_lfps = RK_UDPHY_GEN_GRF_REG(0x0004, 14, 14, 0, 1), 1561 + }, 1562 + .vogrfcfg = { 1563 + { 1564 + .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3), 1565 + .dp_lane_reg = 0x0000, 1566 + }, 1567 + { 1568 + .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0008, 11, 10, 1, 3), 1569 + .dp_lane_reg = 0x0008, 1570 + }, 1571 + }, 1572 + .dp_tx_ctrl_cfg = { 1573 + rk3588_dp_tx_drv_ctrl_rbr_hbr, 1574 + rk3588_dp_tx_drv_ctrl_rbr_hbr, 1575 + rk3588_dp_tx_drv_ctrl_hbr2, 1576 + rk3588_dp_tx_drv_ctrl_hbr3, 1577 + }, 1578 + .dp_tx_ctrl_cfg_typec = { 1579 + rk3588_dp_tx_drv_ctrl_rbr_hbr_typec, 1580 + rk3588_dp_tx_drv_ctrl_rbr_hbr_typec, 1581 + rk3588_dp_tx_drv_ctrl_hbr2, 1582 + rk3588_dp_tx_drv_ctrl_hbr3, 1583 + }, 1584 + }; 1585 + 1586 + static const struct of_device_id rk_udphy_dt_match[] = { 1587 + { 1588 + .compatible = "rockchip,rk3588-usbdp-phy", 1589 + .data = &rk3588_udphy_cfgs 1590 + }, 1591 + { /* sentinel */ } 1592 + }; 1593 + MODULE_DEVICE_TABLE(of, rk_udphy_dt_match); 1594 + 1595 + static struct platform_driver rk_udphy_driver = { 1596 + .probe = rk_udphy_probe, 1597 + .driver = { 1598 + .name = "rockchip-usbdp-phy", 1599 + .of_match_table = rk_udphy_dt_match, 1600 + .pm = &rk_udphy_pm_ops, 1601 + }, 1602 + }; 1603 + module_platform_driver(rk_udphy_driver); 1604 + 1605 + MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>"); 1606 + MODULE_AUTHOR("Zhang Yubing <yubing.zhang@rock-chips.com>"); 1607 + MODULE_DESCRIPTION("Rockchip USBDP Combo PHY driver"); 1608 + MODULE_LICENSE("GPL");
+1
drivers/phy/samsung/Makefile
··· 3 3 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o 4 4 obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o 5 5 obj-$(CONFIG_PHY_SAMSUNG_UFS) += phy-exynos-ufs.o 6 + phy-exynos-ufs-y += phy-gs101-ufs.o 6 7 phy-exynos-ufs-y += phy-samsung-ufs.o 7 8 phy-exynos-ufs-y += phy-exynos7-ufs.o 8 9 phy-exynos-ufs-y += phy-exynosautov9-ufs.o
+1
drivers/phy/samsung/phy-exynos7-ufs.c
··· 82 82 .clk_list = exynos7_ufs_phy_clks, 83 83 .num_clks = ARRAY_SIZE(exynos7_ufs_phy_clks), 84 84 .cdr_lock_status_offset = EXYNOS7_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS, 85 + .wait_for_cdr = samsung_ufs_phy_wait_for_lock_acq, 85 86 };
+1
drivers/phy/samsung/phy-exynosautov9-ufs.c
··· 71 71 .clk_list = exynosautov9_ufs_phy_clks, 72 72 .num_clks = ARRAY_SIZE(exynosautov9_ufs_phy_clks), 73 73 .cdr_lock_status_offset = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS, 74 + .wait_for_cdr = samsung_ufs_phy_wait_for_lock_acq, 74 75 };
+1
drivers/phy/samsung/phy-fsd-ufs.c
··· 60 60 .clk_list = fsd_ufs_phy_clks, 61 61 .num_clks = ARRAY_SIZE(fsd_ufs_phy_clks), 62 62 .cdr_lock_status_offset = FSD_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS, 63 + .wait_for_cdr = samsung_ufs_phy_wait_for_lock_acq, 63 64 };
+182
drivers/phy/samsung/phy-gs101-ufs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * UFS PHY driver data for Google Tensor gs101 SoC 4 + * 5 + * Copyright (C) 2024 Linaro Ltd 6 + * Author: Peter Griffin <peter.griffin@linaro.org> 7 + */ 8 + 9 + #include "phy-samsung-ufs.h" 10 + 11 + #define TENSOR_GS101_PHY_CTRL 0x3ec8 12 + #define TENSOR_GS101_PHY_CTRL_MASK 0x1 13 + #define TENSOR_GS101_PHY_CTRL_EN BIT(0) 14 + #define PHY_GS101_LANE_OFFSET 0x200 15 + #define TRSV_REG338 0x338 16 + #define LN0_MON_RX_CAL_DONE BIT(3) 17 + #define TRSV_REG339 0x339 18 + #define LN0_MON_RX_CDR_FLD_CK_MODE_DONE BIT(3) 19 + #define TRSV_REG222 0x222 20 + #define LN0_OVRD_RX_CDR_EN BIT(4) 21 + #define LN0_RX_CDR_EN BIT(3) 22 + 23 + #define PHY_PMA_TRSV_ADDR(reg, lane) (PHY_APB_ADDR((reg) + \ 24 + ((lane) * PHY_GS101_LANE_OFFSET))) 25 + 26 + #define PHY_TRSV_REG_CFG_GS101(o, v, d) \ 27 + PHY_TRSV_REG_CFG_OFFSET(o, v, d, PHY_GS101_LANE_OFFSET) 28 + 29 + /* Calibration for phy initialization */ 30 + static const struct samsung_ufs_phy_cfg tensor_gs101_pre_init_cfg[] = { 31 + PHY_COMN_REG_CFG(0x43, 0x10, PWR_MODE_ANY), 32 + PHY_COMN_REG_CFG(0x3C, 0x14, PWR_MODE_ANY), 33 + PHY_COMN_REG_CFG(0x46, 0x48, PWR_MODE_ANY), 34 + PHY_TRSV_REG_CFG_GS101(0x200, 0x00, PWR_MODE_ANY), 35 + PHY_TRSV_REG_CFG_GS101(0x201, 0x06, PWR_MODE_ANY), 36 + PHY_TRSV_REG_CFG_GS101(0x202, 0x06, PWR_MODE_ANY), 37 + PHY_TRSV_REG_CFG_GS101(0x203, 0x0a, PWR_MODE_ANY), 38 + PHY_TRSV_REG_CFG_GS101(0x204, 0x00, PWR_MODE_ANY), 39 + PHY_TRSV_REG_CFG_GS101(0x205, 0x11, PWR_MODE_ANY), 40 + PHY_TRSV_REG_CFG_GS101(0x207, 0x0c, PWR_MODE_ANY), 41 + PHY_TRSV_REG_CFG_GS101(0x2E1, 0xc0, PWR_MODE_ANY), 42 + PHY_TRSV_REG_CFG_GS101(0x22D, 0xb8, PWR_MODE_ANY), 43 + PHY_TRSV_REG_CFG_GS101(0x234, 0x60, PWR_MODE_ANY), 44 + PHY_TRSV_REG_CFG_GS101(0x238, 0x13, PWR_MODE_ANY), 45 + PHY_TRSV_REG_CFG_GS101(0x239, 0x48, PWR_MODE_ANY), 46 + PHY_TRSV_REG_CFG_GS101(0x23A, 0x01, PWR_MODE_ANY), 47 + PHY_TRSV_REG_CFG_GS101(0x23B, 0x25, PWR_MODE_ANY), 48 + PHY_TRSV_REG_CFG_GS101(0x23C, 0x2a, PWR_MODE_ANY), 49 + PHY_TRSV_REG_CFG_GS101(0x23D, 0x01, PWR_MODE_ANY), 50 + PHY_TRSV_REG_CFG_GS101(0x23E, 0x13, PWR_MODE_ANY), 51 + PHY_TRSV_REG_CFG_GS101(0x23F, 0x13, PWR_MODE_ANY), 52 + PHY_TRSV_REG_CFG_GS101(0x240, 0x4a, PWR_MODE_ANY), 53 + PHY_TRSV_REG_CFG_GS101(0x243, 0x40, PWR_MODE_ANY), 54 + PHY_TRSV_REG_CFG_GS101(0x244, 0x02, PWR_MODE_ANY), 55 + PHY_TRSV_REG_CFG_GS101(0x25D, 0x00, PWR_MODE_ANY), 56 + PHY_TRSV_REG_CFG_GS101(0x25E, 0x3f, PWR_MODE_ANY), 57 + PHY_TRSV_REG_CFG_GS101(0x25F, 0xff, PWR_MODE_ANY), 58 + PHY_TRSV_REG_CFG_GS101(0x273, 0x33, PWR_MODE_ANY), 59 + PHY_TRSV_REG_CFG_GS101(0x274, 0x50, PWR_MODE_ANY), 60 + PHY_TRSV_REG_CFG_GS101(0x284, 0x02, PWR_MODE_ANY), 61 + PHY_TRSV_REG_CFG_GS101(0x285, 0x02, PWR_MODE_ANY), 62 + PHY_TRSV_REG_CFG_GS101(0x2A2, 0x04, PWR_MODE_ANY), 63 + PHY_TRSV_REG_CFG_GS101(0x25D, 0x01, PWR_MODE_ANY), 64 + PHY_TRSV_REG_CFG_GS101(0x2FA, 0x01, PWR_MODE_ANY), 65 + PHY_TRSV_REG_CFG_GS101(0x286, 0x03, PWR_MODE_ANY), 66 + PHY_TRSV_REG_CFG_GS101(0x287, 0x03, PWR_MODE_ANY), 67 + PHY_TRSV_REG_CFG_GS101(0x288, 0x03, PWR_MODE_ANY), 68 + PHY_TRSV_REG_CFG_GS101(0x289, 0x03, PWR_MODE_ANY), 69 + PHY_TRSV_REG_CFG_GS101(0x2B3, 0x04, PWR_MODE_ANY), 70 + PHY_TRSV_REG_CFG_GS101(0x2B6, 0x0b, PWR_MODE_ANY), 71 + PHY_TRSV_REG_CFG_GS101(0x2B7, 0x0b, PWR_MODE_ANY), 72 + PHY_TRSV_REG_CFG_GS101(0x2B8, 0x0b, PWR_MODE_ANY), 73 + PHY_TRSV_REG_CFG_GS101(0x2B9, 0x0b, PWR_MODE_ANY), 74 + PHY_TRSV_REG_CFG_GS101(0x2BA, 0x0b, PWR_MODE_ANY), 75 + PHY_TRSV_REG_CFG_GS101(0x2BB, 0x06, PWR_MODE_ANY), 76 + PHY_TRSV_REG_CFG_GS101(0x2BC, 0x06, PWR_MODE_ANY), 77 + PHY_TRSV_REG_CFG_GS101(0x2BD, 0x06, PWR_MODE_ANY), 78 + PHY_TRSV_REG_CFG_GS101(0x29E, 0x06, PWR_MODE_ANY), 79 + PHY_TRSV_REG_CFG_GS101(0x2E4, 0x1a, PWR_MODE_ANY), 80 + PHY_TRSV_REG_CFG_GS101(0x2ED, 0x25, PWR_MODE_ANY), 81 + PHY_TRSV_REG_CFG_GS101(0x269, 0x1a, PWR_MODE_ANY), 82 + PHY_TRSV_REG_CFG_GS101(0x2F4, 0x2f, PWR_MODE_ANY), 83 + PHY_TRSV_REG_CFG_GS101(0x34B, 0x01, PWR_MODE_ANY), 84 + PHY_TRSV_REG_CFG_GS101(0x34C, 0x23, PWR_MODE_ANY), 85 + PHY_TRSV_REG_CFG_GS101(0x34D, 0x23, PWR_MODE_ANY), 86 + PHY_TRSV_REG_CFG_GS101(0x34E, 0x45, PWR_MODE_ANY), 87 + PHY_TRSV_REG_CFG_GS101(0x34F, 0x00, PWR_MODE_ANY), 88 + PHY_TRSV_REG_CFG_GS101(0x350, 0x31, PWR_MODE_ANY), 89 + PHY_TRSV_REG_CFG_GS101(0x351, 0x00, PWR_MODE_ANY), 90 + PHY_TRSV_REG_CFG_GS101(0x352, 0x02, PWR_MODE_ANY), 91 + PHY_TRSV_REG_CFG_GS101(0x353, 0x00, PWR_MODE_ANY), 92 + PHY_TRSV_REG_CFG_GS101(0x354, 0x01, PWR_MODE_ANY), 93 + PHY_COMN_REG_CFG(0x43, 0x18, PWR_MODE_ANY), 94 + PHY_COMN_REG_CFG(0x43, 0x00, PWR_MODE_ANY), 95 + END_UFS_PHY_CFG, 96 + }; 97 + 98 + static const struct samsung_ufs_phy_cfg tensor_gs101_pre_pwr_hs_config[] = { 99 + PHY_TRSV_REG_CFG_GS101(0x369, 0x11, PWR_MODE_ANY), 100 + PHY_TRSV_REG_CFG_GS101(0x246, 0x03, PWR_MODE_ANY), 101 + }; 102 + 103 + /* Calibration for HS mode series A/B */ 104 + static const struct samsung_ufs_phy_cfg tensor_gs101_post_pwr_hs_config[] = { 105 + PHY_COMN_REG_CFG(0x8, 0x60, PWR_MODE_PWM_ANY), 106 + PHY_TRSV_REG_CFG_GS101(0x222, 0x08, PWR_MODE_PWM_ANY), 107 + PHY_TRSV_REG_CFG_GS101(0x246, 0x01, PWR_MODE_ANY), 108 + END_UFS_PHY_CFG, 109 + }; 110 + 111 + static const struct samsung_ufs_phy_cfg *tensor_gs101_ufs_phy_cfgs[CFG_TAG_MAX] = { 112 + [CFG_PRE_INIT] = tensor_gs101_pre_init_cfg, 113 + [CFG_PRE_PWR_HS] = tensor_gs101_pre_pwr_hs_config, 114 + [CFG_POST_PWR_HS] = tensor_gs101_post_pwr_hs_config, 115 + }; 116 + 117 + static const char * const tensor_gs101_ufs_phy_clks[] = { 118 + "ref_clk", 119 + }; 120 + 121 + static int gs101_phy_wait_for_calibration(struct phy *phy, u8 lane) 122 + { 123 + struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy); 124 + const unsigned int timeout_us = 40000; 125 + const unsigned int sleep_us = 40; 126 + u32 val; 127 + u32 off; 128 + int err; 129 + 130 + off = PHY_PMA_TRSV_ADDR(TRSV_REG338, lane); 131 + 132 + err = readl_poll_timeout(ufs_phy->reg_pma + off, 133 + val, (val & LN0_MON_RX_CAL_DONE), 134 + sleep_us, timeout_us); 135 + 136 + if (err) { 137 + dev_err(ufs_phy->dev, 138 + "failed to get phy cal done %d\n", err); 139 + } 140 + 141 + return err; 142 + } 143 + 144 + #define DELAY_IN_US 40 145 + #define RETRY_CNT 100 146 + static int gs101_phy_wait_for_cdr_lock(struct phy *phy, u8 lane) 147 + { 148 + struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy); 149 + u32 val; 150 + int i; 151 + 152 + for (i = 0; i < RETRY_CNT; i++) { 153 + udelay(DELAY_IN_US); 154 + val = readl(ufs_phy->reg_pma + 155 + PHY_PMA_TRSV_ADDR(TRSV_REG339, lane)); 156 + 157 + if (val & LN0_MON_RX_CDR_FLD_CK_MODE_DONE) 158 + return 0; 159 + 160 + udelay(DELAY_IN_US); 161 + /* Override and enable clock data recovery */ 162 + writel(LN0_OVRD_RX_CDR_EN, ufs_phy->reg_pma + 163 + PHY_PMA_TRSV_ADDR(TRSV_REG222, lane)); 164 + writel(LN0_OVRD_RX_CDR_EN | LN0_RX_CDR_EN, 165 + ufs_phy->reg_pma + PHY_PMA_TRSV_ADDR(TRSV_REG222, lane)); 166 + } 167 + dev_err(ufs_phy->dev, "failed to get cdr lock\n"); 168 + return -ETIMEDOUT; 169 + } 170 + 171 + const struct samsung_ufs_phy_drvdata tensor_gs101_ufs_phy = { 172 + .cfgs = tensor_gs101_ufs_phy_cfgs, 173 + .isol = { 174 + .offset = TENSOR_GS101_PHY_CTRL, 175 + .mask = TENSOR_GS101_PHY_CTRL_MASK, 176 + .en = TENSOR_GS101_PHY_CTRL_EN, 177 + }, 178 + .clk_list = tensor_gs101_ufs_phy_clks, 179 + .num_clks = ARRAY_SIZE(tensor_gs101_ufs_phy_clks), 180 + .wait_for_cal = gs101_phy_wait_for_calibration, 181 + .wait_for_cdr = gs101_phy_wait_for_cdr_lock, 182 + };
+22 -6
drivers/phy/samsung/phy-samsung-ufs.c
··· 13 13 #include <linux/of.h> 14 14 #include <linux/io.h> 15 15 #include <linux/iopoll.h> 16 - #include <linux/mfd/syscon.h> 17 16 #include <linux/module.h> 18 17 #include <linux/phy/phy.h> 19 18 #include <linux/platform_device.h> 20 19 #include <linux/regmap.h> 20 + #include <linux/soc/samsung/exynos-pmu.h> 21 21 22 22 #include "phy-samsung-ufs.h" 23 23 ··· 45 45 } 46 46 } 47 47 48 - static int samsung_ufs_phy_wait_for_lock_acq(struct phy *phy) 48 + int samsung_ufs_phy_wait_for_lock_acq(struct phy *phy, u8 lane) 49 49 { 50 50 struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy); 51 51 const unsigned int timeout_us = 100000; ··· 97 97 } 98 98 } 99 99 100 - if (ufs_phy->ufs_phy_state == CFG_POST_PWR_HS) 101 - err = samsung_ufs_phy_wait_for_lock_acq(phy); 100 + for_each_phy_lane(ufs_phy, i) { 101 + if (ufs_phy->ufs_phy_state == CFG_PRE_INIT && 102 + ufs_phy->drvdata->wait_for_cal) { 103 + err = ufs_phy->drvdata->wait_for_cal(phy, i); 104 + if (err) 105 + goto out; 106 + } 107 + 108 + if (ufs_phy->ufs_phy_state == CFG_POST_PWR_HS && 109 + ufs_phy->drvdata->wait_for_cdr) { 110 + err = ufs_phy->drvdata->wait_for_cdr(phy, i); 111 + if (err) 112 + goto out; 113 + } 114 + } 102 115 103 116 /** 104 117 * In Samsung ufshci, PHY need to be calibrated at different ··· 268 255 goto out; 269 256 } 270 257 271 - phy->reg_pmu = syscon_regmap_lookup_by_phandle( 272 - dev->of_node, "samsung,pmu-syscon"); 258 + phy->reg_pmu = exynos_get_pmu_regmap_by_phandle(dev->of_node, 259 + "samsung,pmu-syscon"); 273 260 if (IS_ERR(phy->reg_pmu)) { 274 261 err = PTR_ERR(phy->reg_pmu); 275 262 dev_err(dev, "failed syscon remap for pmu\n"); ··· 315 302 316 303 static const struct of_device_id samsung_ufs_phy_match[] = { 317 304 { 305 + .compatible = "google,gs101-ufs-phy", 306 + .data = &tensor_gs101_ufs_phy, 307 + }, { 318 308 .compatible = "samsung,exynos7-ufs-phy", 319 309 .data = &exynos7_ufs_phy, 320 310 }, {
+6
drivers/phy/samsung/phy-samsung-ufs.h
··· 112 112 const char * const *clk_list; 113 113 int num_clks; 114 114 u32 cdr_lock_status_offset; 115 + /* SoC's specific operations */ 116 + int (*wait_for_cal)(struct phy *phy, u8 lane); 117 + int (*wait_for_cdr)(struct phy *phy, u8 lane); 115 118 }; 116 119 117 120 struct samsung_ufs_phy { ··· 142 139 phy->isol.mask, isol ? 0 : phy->isol.en); 143 140 } 144 141 142 + int samsung_ufs_phy_wait_for_lock_acq(struct phy *phy, u8 lane); 143 + 145 144 extern const struct samsung_ufs_phy_drvdata exynos7_ufs_phy; 146 145 extern const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy; 147 146 extern const struct samsung_ufs_phy_drvdata fsd_ufs_phy; 147 + extern const struct samsung_ufs_phy_drvdata tensor_gs101_ufs_phy; 148 148 149 149 #endif /* _PHY_SAMSUNG_UFS_ */
+2 -4
drivers/phy/xilinx/phy-zynqmp.c
··· 995 995 return 0; 996 996 } 997 997 998 - static int xpsgtr_remove(struct platform_device *pdev) 998 + static void xpsgtr_remove(struct platform_device *pdev) 999 999 { 1000 1000 struct xpsgtr_dev *gtr_dev = platform_get_drvdata(pdev); 1001 1001 1002 1002 pm_runtime_disable(gtr_dev->dev); 1003 1003 pm_runtime_put_noidle(gtr_dev->dev); 1004 1004 pm_runtime_set_suspended(gtr_dev->dev); 1005 - 1006 - return 0; 1007 1005 } 1008 1006 1009 1007 static const struct of_device_id xpsgtr_of_match[] = { ··· 1013 1015 1014 1016 static struct platform_driver xpsgtr_driver = { 1015 1017 .probe = xpsgtr_probe, 1016 - .remove = xpsgtr_remove, 1018 + .remove_new = xpsgtr_remove, 1017 1019 .driver = { 1018 1020 .name = "xilinx-psgtr", 1019 1021 .of_match_table = xpsgtr_of_match,
+4
include/dt-bindings/phy/phy-qcom-qmp.h
··· 17 17 #define QMP_USB43DP_USB3_PHY 0 18 18 #define QMP_USB43DP_DP_PHY 1 19 19 20 + /* QMP PCIE PHYs */ 21 + #define QMP_PCIE_PIPE_CLK 0 22 + #define QMP_PCIE_PHY_AUX_CLK 1 23 + 20 24 #endif /* _DT_BINDINGS_PHY_QMP */