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

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

Pull phy updates from Vinod Koul:
"A fairly moderate sized request for the generic phy subsystem with
some new device and driver support along with driver updates with
Samsung and Qualcomm ones being major ones.

New HW Support:

- Qualcomm X1P42100 PCIe Gen4x4, QCS615 qmp usbc, PCIe UNIPHY 28LP
driver, SM8750 QMP UFS PHY

- Rockchip rk3576 hdptx, rk3562 naneng-combo support

- Samsung MIPI D-/C-PHY driver, ExynosAutov920 ufs phy driver

Updates:

- Samsung USB3 Type-C lane orientation detection and configuration
for Google gs101

- Qualcomm support for dual lane PHY support for QCS8300 SoC"

* tag 'phy-for-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (47 commits)
phy: rockchip-naneng-combo: Support rk3562
dt-bindings: phy: rockchip: Add rk3562 naneng-combophy compatible
phy: rockchip: Add Samsung MIPI D-/C-PHY driver
dt-bindings: phy: Add Rockchip MIPI C-/D-PHY schema
phy: qcom: uniphy-28lp: add COMMON_CLK dependency
phy: rockchip: usbdp: Remove unnecessary bool conversion
phy: rockchip: usbdp: Avoid call hpd_event_trigger in dp_phy_init
phy: rockchip: usbdp: Only verify link rates/lanes/voltage when the corresponding set flags are set
phy: qcom-qmp-pcie: add dual lane PHY support for QCS8300
dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Document the QCS8300 QMP PCIe PHY Gen4 x2
phy: qcom-qmp-ufs: Add PHY Configuration support for sm8750
dt-bindings: phy: qcom,sc8280xp-qmp-ufs-phy: document the SM8750 QMP UFS PHY
phy: qcom: Introduce PCIe UNIPHY 28LP driver
dt-bindings: phy: qcom,uniphy-pcie: Document PCIe uniphy
phy: qcom: qmp-usbc: Add qmp configuration for QCS615
phy: freescale: imx8m-pcie: assert phy reset and perst in power off
phy: freescale: imx8m-pcie: cleanup reset logic
phy: core: Remove unused phy_pm_runtime_(allow|forbid)
dt-bindings: phy: document Allwinner A523 USB-2.0 PHY
phy: phy-rockchip-samsung-hdptx: Add support for RK3576
...

+4439 -279
+3 -1
Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml
··· 20 20 - allwinner,sun20i-d1-usb-phy 21 21 - allwinner,sun50i-a64-usb-phy 22 22 - items: 23 - - const: allwinner,sun50i-a100-usb-phy 23 + - enum: 24 + - allwinner,sun50i-a100-usb-phy 25 + - allwinner,sun55i-a523-usb-phy 24 26 - const: allwinner,sun20i-d1-usb-phy 25 27 26 28 reg:
+1
Documentation/devicetree/bindings/phy/phy-rockchip-naneng-combphy.yaml
··· 12 12 properties: 13 13 compatible: 14 14 enum: 15 + - rockchip,rk3562-naneng-combphy 15 16 - rockchip,rk3568-naneng-combphy 16 17 - rockchip,rk3576-naneng-combphy 17 18 - rockchip,rk3588-naneng-combphy
+76
Documentation/devicetree/bindings/phy/qcom,ipq5332-uniphy-pcie-phy.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/phy/qcom,ipq5332-uniphy-pcie-phy.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm UNIPHY PCIe 28LP PHY 8 + 9 + maintainers: 10 + - Nitheesh Sekar <quic_nsekar@quicinc.com> 11 + - Varadarajan Narayanan <quic_varada@quicinc.com> 12 + 13 + description: 14 + PCIe and USB combo PHY found in Qualcomm IPQ5332 SoC 15 + 16 + properties: 17 + compatible: 18 + enum: 19 + - qcom,ipq5332-uniphy-pcie-phy 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + clocks: 25 + items: 26 + - description: pcie pipe clock 27 + - description: pcie ahb clock 28 + 29 + resets: 30 + items: 31 + - description: phy reset 32 + - description: ahb reset 33 + - description: cfg reset 34 + 35 + "#phy-cells": 36 + const: 0 37 + 38 + "#clock-cells": 39 + const: 0 40 + 41 + num-lanes: 42 + $ref: /schemas/types.yaml#/definitions/uint32 43 + enum: [1, 2] 44 + 45 + required: 46 + - compatible 47 + - reg 48 + - clocks 49 + - resets 50 + - "#phy-cells" 51 + - "#clock-cells" 52 + - num-lanes 53 + 54 + additionalProperties: false 55 + 56 + examples: 57 + - | 58 + #include <dt-bindings/clock/qcom,ipq5332-gcc.h> 59 + 60 + pcie0_phy: phy@4b0000 { 61 + compatible = "qcom,ipq5332-uniphy-pcie-phy"; 62 + reg = <0x004b0000 0x800>; 63 + 64 + clocks = <&gcc GCC_PCIE3X1_0_PIPE_CLK>, 65 + <&gcc GCC_PCIE3X1_PHY_AHB_CLK>; 66 + 67 + resets = <&gcc GCC_PCIE3X1_0_PHY_BCR>, 68 + <&gcc GCC_PCIE3X1_PHY_AHB_CLK_ARES>, 69 + <&gcc GCC_PCIE3X1_0_PHY_PHY_BCR>; 70 + 71 + #clock-cells = <0>; 72 + 73 + #phy-cells = <0>; 74 + 75 + num-lanes = <1>; 76 + };
+5 -6
Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
··· 17 17 compatible: 18 18 enum: 19 19 - qcom,qcs615-qmp-gen3x1-pcie-phy 20 + - qcom,qcs8300-qmp-gen4x2-pcie-phy 20 21 - qcom,sa8775p-qmp-gen4x2-pcie-phy 21 22 - qcom,sa8775p-qmp-gen4x4-pcie-phy 22 23 - qcom,sar2130p-qmp-gen3x2-pcie-phy ··· 46 45 - qcom,x1e80100-qmp-gen4x2-pcie-phy 47 46 - qcom,x1e80100-qmp-gen4x4-pcie-phy 48 47 - qcom,x1e80100-qmp-gen4x8-pcie-phy 48 + - qcom,x1p42100-qmp-gen4x4-pcie-phy 49 49 50 50 reg: 51 51 minItems: 1 ··· 126 124 enum: 127 125 - qcom,sc8280xp-qmp-gen3x4-pcie-phy 128 126 - qcom,x1e80100-qmp-gen4x4-pcie-phy 127 + - qcom,x1p42100-qmp-gen4x4-pcie-phy 129 128 then: 130 129 properties: 131 130 reg: ··· 183 180 - qcom,x1e80100-qmp-gen4x2-pcie-phy 184 181 - qcom,x1e80100-qmp-gen4x4-pcie-phy 185 182 - qcom,x1e80100-qmp-gen4x8-pcie-phy 183 + - qcom,x1p42100-qmp-gen4x4-pcie-phy 186 184 then: 187 185 properties: 188 186 clocks: ··· 196 192 compatible: 197 193 contains: 198 194 enum: 195 + - qcom,qcs8300-qmp-gen4x2-pcie-phy 199 196 - qcom,sa8775p-qmp-gen4x2-pcie-phy 200 197 - qcom,sa8775p-qmp-gen4x4-pcie-phy 201 198 then: ··· 222 217 minItems: 2 223 218 reset-names: 224 219 minItems: 2 225 - else: 226 - properties: 227 - resets: 228 - maxItems: 1 229 - reset-names: 230 - maxItems: 1 231 220 232 221 - if: 233 222 properties:
+2
Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
··· 44 44 - qcom,sm8475-qmp-ufs-phy 45 45 - qcom,sm8550-qmp-ufs-phy 46 46 - qcom,sm8650-qmp-ufs-phy 47 + - qcom,sm8750-qmp-ufs-phy 47 48 48 49 reg: 49 50 maxItems: 1 ··· 112 111 - qcom,sm8475-qmp-ufs-phy 113 112 - qcom,sm8550-qmp-ufs-phy 114 113 - qcom,sm8650-qmp-ufs-phy 114 + - qcom,sm8750-qmp-ufs-phy 115 115 then: 116 116 properties: 117 117 clocks:
+44 -18
Documentation/devicetree/bindings/phy/rockchip,rk3588-hdptx-phy.yaml
··· 11 11 12 12 properties: 13 13 compatible: 14 - enum: 15 - - rockchip,rk3588-hdptx-phy 14 + oneOf: 15 + - enum: 16 + - rockchip,rk3588-hdptx-phy 17 + - items: 18 + - enum: 19 + - rockchip,rk3576-hdptx-phy 20 + - const: rockchip,rk3588-hdptx-phy 16 21 17 22 reg: 18 23 maxItems: 1 ··· 39 34 const: 0 40 35 41 36 resets: 42 - items: 43 - - description: PHY reset line 44 - - description: APB reset line 45 - - description: INIT reset line 46 - - description: CMN reset line 47 - - description: LANE reset line 48 - - description: ROPLL reset line 49 - - description: LCPLL reset line 37 + minItems: 4 38 + maxItems: 7 50 39 51 40 reset-names: 52 - items: 53 - - const: phy 54 - - const: apb 55 - - const: init 56 - - const: cmn 57 - - const: lane 58 - - const: ropll 59 - - const: lcpll 41 + minItems: 4 42 + maxItems: 7 60 43 61 44 rockchip,grf: 62 45 $ref: /schemas/types.yaml#/definitions/phandle ··· 59 66 - resets 60 67 - reset-names 61 68 - rockchip,grf 69 + 70 + allOf: 71 + - if: 72 + properties: 73 + compatible: 74 + contains: 75 + enum: 76 + - rockchip,rk3576-hdptx-phy 77 + then: 78 + properties: 79 + resets: 80 + minItems: 4 81 + maxItems: 4 82 + reset-names: 83 + items: 84 + - const: apb 85 + - const: init 86 + - const: cmn 87 + - const: lane 88 + else: 89 + properties: 90 + resets: 91 + minItems: 7 92 + maxItems: 7 93 + reset-names: 94 + items: 95 + - const: phy 96 + - const: apb 97 + - const: init 98 + - const: cmn 99 + - const: lane 100 + - const: ropll 101 + - const: lcpll 62 102 63 103 additionalProperties: false 64 104
+87
Documentation/devicetree/bindings/phy/rockchip,rk3588-mipi-dcphy.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/rockchip,rk3588-mipi-dcphy.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Rockchip MIPI D-/C-PHY with Samsung IP block 8 + 9 + maintainers: 10 + - Guochun Huang <hero.huang@rock-chips.com> 11 + - Heiko Stuebner <heiko@sntech.de> 12 + 13 + properties: 14 + compatible: 15 + enum: 16 + - rockchip,rk3576-mipi-dcphy 17 + - rockchip,rk3588-mipi-dcphy 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + "#phy-cells": 23 + const: 1 24 + description: | 25 + Argument is mode to operate in. Supported modes are: 26 + - PHY_TYPE_DPHY 27 + - PHY_TYPE_CPHY 28 + See include/dt-bindings/phy/phy.h for constants. 29 + 30 + clocks: 31 + maxItems: 2 32 + 33 + clock-names: 34 + items: 35 + - const: pclk 36 + - const: ref 37 + 38 + resets: 39 + maxItems: 4 40 + 41 + reset-names: 42 + items: 43 + - const: m_phy 44 + - const: apb 45 + - const: grf 46 + - const: s_phy 47 + 48 + rockchip,grf: 49 + $ref: /schemas/types.yaml#/definitions/phandle 50 + description: 51 + Phandle to the syscon managing the 'mipi dcphy general register files'. 52 + 53 + required: 54 + - compatible 55 + - reg 56 + - clocks 57 + - clock-names 58 + - resets 59 + - reset-names 60 + - "#phy-cells" 61 + 62 + additionalProperties: false 63 + 64 + examples: 65 + - | 66 + #include <dt-bindings/clock/rockchip,rk3588-cru.h> 67 + #include <dt-bindings/reset/rockchip,rk3588-cru.h> 68 + 69 + soc { 70 + #address-cells = <2>; 71 + #size-cells = <2>; 72 + 73 + phy@feda0000 { 74 + compatible = "rockchip,rk3588-mipi-dcphy"; 75 + reg = <0x0 0xfeda0000 0x0 0x10000>; 76 + clocks = <&cru PCLK_MIPI_DCPHY0>, 77 + <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>; 78 + clock-names = "pclk", "ref"; 79 + resets = <&cru SRST_M_MIPI_DCPHY0>, 80 + <&cru SRST_P_MIPI_DCPHY0>, 81 + <&cru SRST_P_MIPI_DCPHY0_GRF>, 82 + <&cru SRST_S_MIPI_DCPHY0>; 83 + reset-names = "m_phy", "apb", "grf", "s_phy"; 84 + rockchip,grf = <&mipidcphy0_grf>; 85 + #phy-cells = <1>; 86 + }; 87 + };
+1
Documentation/devicetree/bindings/phy/samsung,ufs-phy.yaml
··· 18 18 - google,gs101-ufs-phy 19 19 - samsung,exynos7-ufs-phy 20 20 - samsung,exynosautov9-ufs-phy 21 + - samsung,exynosautov920-ufs-phy 21 22 - tesla,fsd-ufs-phy 22 23 23 24 reg:
+20 -1
Documentation/devicetree/bindings/phy/samsung,usb3-drd-phy.yaml
··· 83 83 84 84 pll-supply: 85 85 description: Power supply for the USB PLL. 86 + 86 87 dvdd-usb20-supply: 87 88 description: DVDD power supply for the USB 2.0 phy. 89 + 88 90 vddh-usb20-supply: 89 91 description: VDDh power supply for the USB 2.0 phy. 92 + 90 93 vdd33-usb20-supply: 91 94 description: 3.3V power supply for the USB 2.0 phy. 95 + 92 96 vdda-usbdp-supply: 93 97 description: VDDa power supply for the USB DP phy. 98 + 94 99 vddh-usbdp-supply: 95 100 description: VDDh power supply for the USB DP phy. 96 101 ··· 114 109 contains: 115 110 const: google,gs101-usb31drd-phy 116 111 then: 112 + $ref: /schemas/usb/usb-switch.yaml# 113 + 117 114 properties: 118 115 clocks: 119 116 items: ··· 124 117 - description: Gate of control interface AXI clock 125 118 - description: Gate of control interface APB clock 126 119 - description: Gate of SCL APB clock 120 + 127 121 clock-names: 128 122 items: 129 123 - const: phy ··· 132 124 - const: ctrl_aclk 133 125 - const: ctrl_pclk 134 126 - const: scl_pclk 127 + 135 128 reg: 136 129 minItems: 3 130 + 137 131 reg-names: 138 132 minItems: 3 133 + 139 134 required: 140 135 - reg-names 136 + - orientation-switch 137 + - port 141 138 - pll-supply 142 139 - dvdd-usb20-supply 143 140 - vddh-usb20-supply ··· 162 149 clocks: 163 150 minItems: 5 164 151 maxItems: 5 152 + 165 153 clock-names: 166 154 items: 167 155 - const: phy ··· 170 156 - const: phy_utmi 171 157 - const: phy_pipe 172 158 - const: itp 159 + 173 160 reg: 174 161 maxItems: 1 162 + 175 163 reg-names: 176 164 maxItems: 1 177 165 ··· 190 174 clocks: 191 175 minItems: 2 192 176 maxItems: 2 177 + 193 178 clock-names: 194 179 items: 195 180 - const: phy 196 181 - const: ref 182 + 197 183 reg: 198 184 maxItems: 1 185 + 199 186 reg-names: 200 187 maxItems: 1 201 188 202 - additionalProperties: false 189 + unevaluatedProperties: false 203 190 204 191 examples: 205 192 - |
+1 -2
Documentation/driver-api/phy/phy.rst
··· 198 198 It should also be noted that phy_power_on and phy_power_off performs 199 199 phy_pm_runtime_get_sync and phy_pm_runtime_put respectively. 200 200 There are exported APIs like phy_pm_runtime_get, phy_pm_runtime_get_sync, 201 - phy_pm_runtime_put, phy_pm_runtime_put_sync, phy_pm_runtime_allow and 202 - phy_pm_runtime_forbid for performing PM operations. 201 + phy_pm_runtime_put and phy_pm_runtime_put_sync for performing PM operations. 203 202 204 203 PHY Mappings 205 204 ============
+1
drivers/phy/freescale/Kconfig
··· 5 5 config PHY_FSL_IMX8MQ_USB 6 6 tristate "Freescale i.MX8M USB3 PHY" 7 7 depends on OF && HAS_IOMEM 8 + depends on TYPEC || TYPEC=n 8 9 select GENERIC_PHY 9 10 default ARCH_MXC && ARM64 10 11
+14 -9
drivers/phy/freescale/phy-fsl-imx8m-pcie.c
··· 141 141 IMX8MM_GPR_PCIE_REF_CLK_PLL); 142 142 usleep_range(100, 200); 143 143 144 - switch (imx8_phy->drvdata->variant) { 145 - case IMX8MP: 146 - reset_control_deassert(imx8_phy->perst); 147 - fallthrough; 148 - case IMX8MM: 149 - reset_control_deassert(imx8_phy->reset); 150 - usleep_range(200, 500); 151 - break; 152 - } 144 + reset_control_deassert(imx8_phy->perst); 145 + reset_control_deassert(imx8_phy->reset); 146 + usleep_range(200, 500); 153 147 154 148 /* Do the PHY common block reset */ 155 149 regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14, ··· 154 160 ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG075, 155 161 val, val == ANA_PLL_DONE, 10, 20000); 156 162 return ret; 163 + } 164 + 165 + static int imx8_pcie_phy_power_off(struct phy *phy) 166 + { 167 + struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy); 168 + 169 + reset_control_assert(imx8_phy->reset); 170 + reset_control_assert(imx8_phy->perst); 171 + 172 + return 0; 157 173 } 158 174 159 175 static int imx8_pcie_phy_init(struct phy *phy) ··· 186 182 .init = imx8_pcie_phy_init, 187 183 .exit = imx8_pcie_phy_exit, 188 184 .power_on = imx8_pcie_phy_power_on, 185 + .power_off = imx8_pcie_phy_power_off, 189 186 .owner = THIS_MODULE, 190 187 }; 191 188
+240
drivers/phy/freescale/phy-fsl-imx8mq-usb.c
··· 10 10 #include <linux/phy/phy.h> 11 11 #include <linux/platform_device.h> 12 12 #include <linux/regulator/consumer.h> 13 + #include <linux/usb/typec_mux.h> 13 14 14 15 #define PHY_CTRL0 0x0 15 16 #define PHY_CTRL0_REF_SSP_EN BIT(2) ··· 51 50 52 51 #define PHY_TUNE_DEFAULT 0xffffffff 53 52 53 + #define TCA_CLK_RST 0x00 54 + #define TCA_CLK_RST_SW BIT(9) 55 + #define TCA_CLK_RST_REF_CLK_EN BIT(1) 56 + #define TCA_CLK_RST_SUSPEND_CLK_EN BIT(0) 57 + 58 + #define TCA_INTR_EN 0x04 59 + #define TCA_INTR_STS 0x08 60 + 61 + #define TCA_GCFG 0x10 62 + #define TCA_GCFG_ROLE_HSTDEV BIT(4) 63 + #define TCA_GCFG_OP_MODE GENMASK(1, 0) 64 + #define TCA_GCFG_OP_MODE_SYSMODE 0 65 + #define TCA_GCFG_OP_MODE_SYNCMODE 1 66 + 67 + #define TCA_TCPC 0x14 68 + #define TCA_TCPC_VALID BIT(4) 69 + #define TCA_TCPC_LOW_POWER_EN BIT(3) 70 + #define TCA_TCPC_ORIENTATION_NORMAL BIT(2) 71 + #define TCA_TCPC_MUX_CONTRL GENMASK(1, 0) 72 + #define TCA_TCPC_MUX_CONTRL_NO_CONN 0 73 + #define TCA_TCPC_MUX_CONTRL_USB_CONN 1 74 + 75 + #define TCA_SYSMODE_CFG 0x18 76 + #define TCA_SYSMODE_TCPC_DISABLE BIT(3) 77 + #define TCA_SYSMODE_TCPC_FLIP BIT(2) 78 + 79 + #define TCA_CTRLSYNCMODE_CFG0 0x20 80 + #define TCA_CTRLSYNCMODE_CFG1 0x20 81 + 82 + #define TCA_PSTATE 0x30 83 + #define TCA_PSTATE_CM_STS BIT(4) 84 + #define TCA_PSTATE_TX_STS BIT(3) 85 + #define TCA_PSTATE_RX_PLL_STS BIT(2) 86 + #define TCA_PSTATE_PIPE0_POWER_DOWN GENMASK(1, 0) 87 + 88 + #define TCA_GEN_STATUS 0x34 89 + #define TCA_GEN_DEV_POR BIT(12) 90 + #define TCA_GEN_REF_CLK_SEL BIT(8) 91 + #define TCA_GEN_TYPEC_FLIP_INVERT BIT(4) 92 + #define TCA_GEN_PHY_TYPEC_DISABLE BIT(3) 93 + #define TCA_GEN_PHY_TYPEC_FLIP BIT(2) 94 + 95 + #define TCA_VBUS_CTRL 0x40 96 + #define TCA_VBUS_STATUS 0x44 97 + 98 + #define TCA_INFO 0xfc 99 + 100 + struct tca_blk { 101 + struct typec_switch_dev *sw; 102 + void __iomem *base; 103 + struct mutex mutex; 104 + enum typec_orientation orientation; 105 + }; 106 + 54 107 struct imx8mq_usb_phy { 55 108 struct phy *phy; 56 109 struct clk *clk; 57 110 void __iomem *base; 58 111 struct regulator *vbus; 112 + struct tca_blk *tca; 59 113 u32 pcs_tx_swing_full; 60 114 u32 pcs_tx_deemph_3p5db; 61 115 u32 tx_vref_tune; ··· 119 63 u32 tx_vboost_level; 120 64 u32 comp_dis_tune; 121 65 }; 66 + 67 + 68 + static void tca_blk_orientation_set(struct tca_blk *tca, 69 + enum typec_orientation orientation); 70 + 71 + #ifdef CONFIG_TYPEC 72 + 73 + static int tca_blk_typec_switch_set(struct typec_switch_dev *sw, 74 + enum typec_orientation orientation) 75 + { 76 + struct imx8mq_usb_phy *imx_phy = typec_switch_get_drvdata(sw); 77 + struct tca_blk *tca = imx_phy->tca; 78 + int ret; 79 + 80 + if (tca->orientation == orientation) 81 + return 0; 82 + 83 + ret = clk_prepare_enable(imx_phy->clk); 84 + if (ret) 85 + return ret; 86 + 87 + tca_blk_orientation_set(tca, orientation); 88 + clk_disable_unprepare(imx_phy->clk); 89 + 90 + return 0; 91 + } 92 + 93 + static struct typec_switch_dev *tca_blk_get_typec_switch(struct platform_device *pdev, 94 + struct imx8mq_usb_phy *imx_phy) 95 + { 96 + struct device *dev = &pdev->dev; 97 + struct typec_switch_dev *sw; 98 + struct typec_switch_desc sw_desc = { }; 99 + 100 + sw_desc.drvdata = imx_phy; 101 + sw_desc.fwnode = dev->fwnode; 102 + sw_desc.set = tca_blk_typec_switch_set; 103 + sw_desc.name = NULL; 104 + 105 + sw = typec_switch_register(dev, &sw_desc); 106 + if (IS_ERR(sw)) { 107 + dev_err(dev, "Error register tca orientation switch: %ld", 108 + PTR_ERR(sw)); 109 + return NULL; 110 + } 111 + 112 + return sw; 113 + } 114 + 115 + static void tca_blk_put_typec_switch(struct typec_switch_dev *sw) 116 + { 117 + typec_switch_unregister(sw); 118 + } 119 + 120 + #else 121 + 122 + static struct typec_switch_dev *tca_blk_get_typec_switch(struct platform_device *pdev, 123 + struct imx8mq_usb_phy *imx_phy) 124 + { 125 + return NULL; 126 + } 127 + 128 + static void tca_blk_put_typec_switch(struct typec_switch_dev *sw) {} 129 + 130 + #endif /* CONFIG_TYPEC */ 131 + 132 + static void tca_blk_orientation_set(struct tca_blk *tca, 133 + enum typec_orientation orientation) 134 + { 135 + u32 val; 136 + 137 + mutex_lock(&tca->mutex); 138 + 139 + if (orientation == TYPEC_ORIENTATION_NONE) { 140 + /* 141 + * use Controller Synced Mode for TCA low power enable and 142 + * put PHY to USB safe state. 143 + */ 144 + val = FIELD_PREP(TCA_GCFG_OP_MODE, TCA_GCFG_OP_MODE_SYNCMODE); 145 + writel(val, tca->base + TCA_GCFG); 146 + 147 + val = TCA_TCPC_VALID | TCA_TCPC_LOW_POWER_EN; 148 + writel(val, tca->base + TCA_TCPC); 149 + 150 + goto out; 151 + } 152 + 153 + /* use System Configuration Mode for TCA mux control. */ 154 + val = FIELD_PREP(TCA_GCFG_OP_MODE, TCA_GCFG_OP_MODE_SYSMODE); 155 + writel(val, tca->base + TCA_GCFG); 156 + 157 + /* Disable TCA module */ 158 + val = readl(tca->base + TCA_SYSMODE_CFG); 159 + val |= TCA_SYSMODE_TCPC_DISABLE; 160 + writel(val, tca->base + TCA_SYSMODE_CFG); 161 + 162 + if (orientation == TYPEC_ORIENTATION_REVERSE) 163 + val |= TCA_SYSMODE_TCPC_FLIP; 164 + else if (orientation == TYPEC_ORIENTATION_NORMAL) 165 + val &= ~TCA_SYSMODE_TCPC_FLIP; 166 + 167 + writel(val, tca->base + TCA_SYSMODE_CFG); 168 + 169 + /* Enable TCA module */ 170 + val &= ~TCA_SYSMODE_TCPC_DISABLE; 171 + writel(val, tca->base + TCA_SYSMODE_CFG); 172 + 173 + out: 174 + tca->orientation = orientation; 175 + mutex_unlock(&tca->mutex); 176 + } 177 + 178 + static void tca_blk_init(struct tca_blk *tca) 179 + { 180 + u32 val; 181 + 182 + /* reset XBar block */ 183 + val = readl(tca->base + TCA_CLK_RST); 184 + val &= ~TCA_CLK_RST_SW; 185 + writel(val, tca->base + TCA_CLK_RST); 186 + 187 + udelay(100); 188 + 189 + /* clear reset */ 190 + val |= TCA_CLK_RST_SW; 191 + writel(val, tca->base + TCA_CLK_RST); 192 + 193 + tca_blk_orientation_set(tca, tca->orientation); 194 + } 195 + 196 + static struct tca_blk *imx95_usb_phy_get_tca(struct platform_device *pdev, 197 + struct imx8mq_usb_phy *imx_phy) 198 + { 199 + struct device *dev = &pdev->dev; 200 + struct resource *res; 201 + struct tca_blk *tca; 202 + 203 + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 204 + if (!res) 205 + return NULL; 206 + 207 + tca = devm_kzalloc(dev, sizeof(*tca), GFP_KERNEL); 208 + if (!tca) 209 + return ERR_PTR(-ENOMEM); 210 + 211 + tca->base = devm_ioremap_resource(&pdev->dev, res); 212 + if (IS_ERR(tca->base)) 213 + return ERR_CAST(tca->base); 214 + 215 + mutex_init(&tca->mutex); 216 + 217 + tca->orientation = TYPEC_ORIENTATION_NORMAL; 218 + tca->sw = tca_blk_get_typec_switch(pdev, imx_phy); 219 + 220 + return tca; 221 + } 222 + 223 + static void imx95_usb_phy_put_tca(struct imx8mq_usb_phy *imx_phy) 224 + { 225 + struct tca_blk *tca = imx_phy->tca; 226 + 227 + if (!tca) 228 + return; 229 + 230 + tca_blk_put_typec_switch(tca->sw); 231 + } 122 232 123 233 static u32 phy_tx_vref_tune_from_property(u32 percent) 124 234 { ··· 537 315 538 316 imx8m_phy_tune(imx_phy); 539 317 318 + if (imx_phy->tca) 319 + tca_blk_init(imx_phy->tca); 320 + 540 321 return 0; 541 322 } 542 323 ··· 584 359 .data = &imx8mq_usb_phy_ops,}, 585 360 {.compatible = "fsl,imx8mp-usb-phy", 586 361 .data = &imx8mp_usb_phy_ops,}, 362 + {.compatible = "fsl,imx95-usb-phy", 363 + .data = &imx8mp_usb_phy_ops,}, 587 364 { } 588 365 }; 589 366 MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match); ··· 625 398 626 399 phy_set_drvdata(imx_phy->phy, imx_phy); 627 400 401 + imx_phy->tca = imx95_usb_phy_get_tca(pdev, imx_phy); 402 + if (IS_ERR(imx_phy->tca)) 403 + return dev_err_probe(dev, PTR_ERR(imx_phy->tca), 404 + "failed to get tca\n"); 405 + 628 406 imx8m_get_phy_tuning_data(imx_phy); 629 407 630 408 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ··· 637 405 return PTR_ERR_OR_ZERO(phy_provider); 638 406 } 639 407 408 + static void imx8mq_usb_phy_remove(struct platform_device *pdev) 409 + { 410 + struct imx8mq_usb_phy *imx_phy = platform_get_drvdata(pdev); 411 + 412 + imx95_usb_phy_put_tca(imx_phy); 413 + } 414 + 640 415 static struct platform_driver imx8mq_usb_phy_driver = { 641 416 .probe = imx8mq_usb_phy_probe, 417 + .remove = imx8mq_usb_phy_remove, 642 418 .driver = { 643 419 .name = "imx8mq-usb-phy", 644 420 .of_match_table = imx8mq_usb_phy_of_match,
+1 -9
drivers/phy/freescale/phy-fsl-samsung-hdmi.c
··· 668 668 if (IS_ERR(phy->regs)) 669 669 return PTR_ERR(phy->regs); 670 670 671 - phy->apbclk = devm_clk_get(phy->dev, "apb"); 671 + phy->apbclk = devm_clk_get_enabled(phy->dev, "apb"); 672 672 if (IS_ERR(phy->apbclk)) 673 673 return dev_err_probe(phy->dev, PTR_ERR(phy->apbclk), 674 674 "failed to get apb clk\n"); ··· 677 677 if (IS_ERR(phy->refclk)) 678 678 return dev_err_probe(phy->dev, PTR_ERR(phy->refclk), 679 679 "failed to get ref clk\n"); 680 - 681 - ret = clk_prepare_enable(phy->apbclk); 682 - if (ret) { 683 - dev_err(phy->dev, "failed to enable apbclk\n"); 684 - return ret; 685 - } 686 680 687 681 pm_runtime_get_noresume(phy->dev); 688 682 pm_runtime_set_active(phy->dev); ··· 693 699 return 0; 694 700 695 701 register_clk_failed: 696 - clk_disable_unprepare(phy->apbclk); 697 - 698 702 return ret; 699 703 } 700 704
+2 -2
drivers/phy/mediatek/phy-mtk-tphy.c
··· 1195 1195 int ret; 1196 1196 1197 1197 /* type switch function is optional */ 1198 - if (!of_property_read_bool(dn, "mediatek,syscon-type")) 1198 + if (!of_property_present(dn, "mediatek,syscon-type")) 1199 1199 return 0; 1200 1200 1201 1201 ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type", ··· 1258 1258 } 1259 1259 1260 1260 /* software efuse is optional */ 1261 - instance->efuse_sw_en = device_property_read_bool(dev, "nvmem-cells"); 1261 + instance->efuse_sw_en = device_property_present(dev, "nvmem-cells"); 1262 1262 if (!instance->efuse_sw_en) 1263 1263 return 0; 1264 1264
+1
drivers/phy/microchip/Kconfig
··· 15 15 config PHY_LAN966X_SERDES 16 16 tristate "SerDes PHY driver for Microchip LAN966X" 17 17 select GENERIC_PHY 18 + depends on SOC_LAN966 || MCHP_LAN966X_PCI || COMPILE_TEST 18 19 depends on OF 19 20 depends on MFD_SYSCON 20 21 help
+6 -7
drivers/phy/phy-can-transceiver.c
··· 103 103 struct phy *phy; 104 104 struct gpio_desc *standby_gpio; 105 105 struct gpio_desc *enable_gpio; 106 + struct mux_state *mux_state; 106 107 u32 max_bitrate = 0; 107 108 int err; 108 109 ··· 114 113 match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node); 115 114 drvdata = match->data; 116 115 117 - if (of_property_read_bool(dev->of_node, "mux-states")) { 118 - struct mux_state *mux_state; 119 - 120 - mux_state = devm_mux_state_get(dev, NULL); 121 - if (IS_ERR(mux_state)) 122 - return dev_err_probe(&pdev->dev, PTR_ERR(mux_state), 123 - "failed to get mux\n"); 116 + mux_state = devm_mux_state_get(dev, NULL); 117 + if (IS_ERR(mux_state)) { 118 + if (PTR_ERR(mux_state) == -EPROBE_DEFER) 119 + return PTR_ERR(mux_state); 120 + } else { 124 121 can_transceiver_phy->mux_state = mux_state; 125 122 } 126 123
+4 -27
drivers/phy/phy-core.c
··· 214 214 } 215 215 EXPORT_SYMBOL_GPL(phy_pm_runtime_put_sync); 216 216 217 - void phy_pm_runtime_allow(struct phy *phy) 218 - { 219 - if (!phy) 220 - return; 221 - 222 - if (!pm_runtime_enabled(&phy->dev)) 223 - return; 224 - 225 - pm_runtime_allow(&phy->dev); 226 - } 227 - EXPORT_SYMBOL_GPL(phy_pm_runtime_allow); 228 - 229 - void phy_pm_runtime_forbid(struct phy *phy) 230 - { 231 - if (!phy) 232 - return; 233 - 234 - if (!pm_runtime_enabled(&phy->dev)) 235 - return; 236 - 237 - pm_runtime_forbid(&phy->dev); 238 - } 239 - EXPORT_SYMBOL_GPL(phy_pm_runtime_forbid); 240 - 241 217 /** 242 218 * phy_init - phy internal initialization before phy operation 243 219 * @phy: the phy returned by phy_get() ··· 381 405 382 406 int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode) 383 407 { 384 - int ret; 408 + int ret = 0; 385 409 386 - if (!phy || !phy->ops->set_mode) 410 + if (!phy) 387 411 return 0; 388 412 389 413 mutex_lock(&phy->mutex); 390 - ret = phy->ops->set_mode(phy, mode, submode); 414 + if (phy->ops->set_mode) 415 + ret = phy->ops->set_mode(phy, mode, submode); 391 416 if (!ret) 392 417 phy->attrs.mode = mode; 393 418 mutex_unlock(&phy->mutex);
+13
drivers/phy/qualcomm/Kconfig
··· 154 154 management. This driver is required even for peripheral only or 155 155 host only mode configurations. 156 156 157 + config PHY_QCOM_UNIPHY_PCIE_28LP 158 + bool "PCIE UNIPHY 28LP PHY driver" 159 + depends on ARCH_QCOM 160 + depends on COMMON_CLK 161 + depends on HAS_IOMEM 162 + depends on OF 163 + select GENERIC_PHY 164 + help 165 + Enable this to support the PCIe UNIPHY 28LP phy transceiver that 166 + is used with PCIe controllers on Qualcomm IPQ5332 chips. It 167 + handles PHY initialization, clock management required after 168 + resetting the hardware and power management. 169 + 157 170 config PHY_QCOM_USB_HS 158 171 tristate "Qualcomm USB HS PHY module" 159 172 depends on USB_ULPI_BUS
+1
drivers/phy/qualcomm/Makefile
··· 17 17 obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o 18 18 obj-$(CONFIG_PHY_QCOM_SNPS_EUSB2) += phy-qcom-snps-eusb2.o 19 19 obj-$(CONFIG_PHY_QCOM_EUSB2_REPEATER) += phy-qcom-eusb2-repeater.o 20 + obj-$(CONFIG_PHY_QCOM_UNIPHY_PCIE_28LP) += phy-qcom-uniphy-pcie-28lp.o 20 21 obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o 21 22 obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o 22 23 obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o
+107
drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
··· 805 805 QMP_PHY_INIT_CFG(QPHY_V2_PCS_TXDEEMPH_M3P5DB_V0, 0xe), 806 806 }; 807 807 808 + static const struct qmp_phy_init_tbl qcs8300_qmp_gen4x2_pcie_rx_alt_tbl[] = { 809 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_PI_CONTROLS, 0x16), 810 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), 811 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B0, 0x9b), 812 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B1, 0xb0), 813 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B2, 0xd2), 814 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B3, 0xf0), 815 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B4, 0x42), 816 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B5, 0x00), 817 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B6, 0x20), 818 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B0, 0x9b), 819 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B1, 0xfb), 820 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B2, 0xd2), 821 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B3, 0xec), 822 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B4, 0x43), 823 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B5, 0xdd), 824 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B6, 0x0d), 825 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B0, 0xf3), 826 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B1, 0xf8), 827 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B2, 0xec), 828 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B3, 0xd6), 829 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B4, 0x83), 830 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B5, 0xf5), 831 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B6, 0x5e), 832 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_PHPRE_CTRL, 0x20), 833 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_0_1, 0x3f), 834 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_2_3, 0x37), 835 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_3, 0x00), 836 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE3, 0x1f), 837 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE3, 0x1f), 838 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE3, 0x1f), 839 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH4_RATE3, 0x1f), 840 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH5_RATE3, 0x1f), 841 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH6_RATE3, 0x1f), 842 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE210, 0x1f), 843 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE210, 0x1f), 844 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE210, 0x1f), 845 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x09), 846 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE2, 0x0c), 847 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE3, 0x08), 848 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_SO_GAIN_RATE3, 0x04), 849 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_VGA_CAL_CNTRL1, 0x04), 850 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_VGA_CAL_MAN_VAL, 0x08), 851 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0b), 852 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x7c), 853 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_IDAC_SAOFFSET, 0x10), 854 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_DAC_ENABLE1, 0x00), 855 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_GM_CAL, 0x05), 856 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH1, 0x00), 857 + QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH2, 0x1f), 858 + }; 859 + 808 860 static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = { 809 861 QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), 810 862 QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ··· 3388 3336 .phy_status = PHYSTATUS, 3389 3337 }; 3390 3338 3339 + static const struct qmp_phy_cfg qcs8300_qmp_gen4x2_pciephy_cfg = { 3340 + .lanes = 2, 3341 + .offsets = &qmp_pcie_offsets_v5_20, 3342 + 3343 + .tbls = { 3344 + .serdes = sa8775p_qmp_gen4x2_pcie_serdes_alt_tbl, 3345 + .serdes_num = ARRAY_SIZE(sa8775p_qmp_gen4x2_pcie_serdes_alt_tbl), 3346 + .tx = sa8775p_qmp_gen4_pcie_tx_tbl, 3347 + .tx_num = ARRAY_SIZE(sa8775p_qmp_gen4_pcie_tx_tbl), 3348 + .rx = qcs8300_qmp_gen4x2_pcie_rx_alt_tbl, 3349 + .rx_num = ARRAY_SIZE(qcs8300_qmp_gen4x2_pcie_rx_alt_tbl), 3350 + .pcs = sa8775p_qmp_gen4x2_pcie_pcs_alt_tbl, 3351 + .pcs_num = ARRAY_SIZE(sa8775p_qmp_gen4x2_pcie_pcs_alt_tbl), 3352 + .pcs_misc = sa8775p_qmp_gen4_pcie_pcs_misc_tbl, 3353 + .pcs_misc_num = ARRAY_SIZE(sa8775p_qmp_gen4_pcie_pcs_misc_tbl), 3354 + }, 3355 + 3356 + .tbls_rc = &(const struct qmp_phy_cfg_tbls) { 3357 + .serdes = sa8775p_qmp_gen4x2_pcie_rc_serdes_alt_tbl, 3358 + .serdes_num = ARRAY_SIZE(sa8775p_qmp_gen4x2_pcie_rc_serdes_alt_tbl), 3359 + .pcs_misc = sa8775p_qmp_gen4_pcie_rc_pcs_misc_tbl, 3360 + .pcs_misc_num = ARRAY_SIZE(sa8775p_qmp_gen4_pcie_rc_pcs_misc_tbl), 3361 + }, 3362 + 3363 + .reset_list = sdm845_pciephy_reset_l, 3364 + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), 3365 + .vreg_list = qmp_phy_vreg_l, 3366 + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 3367 + .regs = pciephy_v5_regs_layout, 3368 + 3369 + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, 3370 + .phy_status = PHYSTATUS_4_20, 3371 + }; 3372 + 3391 3373 static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { 3392 3374 .lanes = 1, 3393 3375 ··· 4242 4156 .has_nocsr_reset = true, 4243 4157 }; 4244 4158 4159 + static const struct qmp_phy_cfg qmp_v6_gen4x4_pciephy_cfg = { 4160 + .lanes = 4, 4161 + 4162 + .offsets = &qmp_pcie_offsets_v6_20, 4163 + 4164 + .reset_list = sdm845_pciephy_reset_l, 4165 + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), 4166 + .vreg_list = qmp_phy_vreg_l, 4167 + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 4168 + .regs = pciephy_v6_regs_layout, 4169 + 4170 + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, 4171 + .phy_status = PHYSTATUS_4_20, 4172 + }; 4173 + 4245 4174 static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls) 4246 4175 { 4247 4176 const struct qmp_phy_cfg *cfg = qmp->cfg; ··· 4978 4877 .compatible = "qcom,qcs615-qmp-gen3x1-pcie-phy", 4979 4878 .data = &qcs615_pciephy_cfg, 4980 4879 }, { 4880 + .compatible = "qcom,qcs8300-qmp-gen4x2-pcie-phy", 4881 + .data = &qcs8300_qmp_gen4x2_pciephy_cfg, 4882 + }, { 4981 4883 .compatible = "qcom,sa8775p-qmp-gen4x2-pcie-phy", 4982 4884 .data = &sa8775p_qmp_gen4x2_pciephy_cfg, 4983 4885 }, { ··· 5064 4960 }, { 5065 4961 .compatible = "qcom,x1e80100-qmp-gen4x8-pcie-phy", 5066 4962 .data = &x1e80100_qmp_gen4x8_pciephy_cfg, 4963 + }, { 4964 + .compatible = "qcom,x1p42100-qmp-gen4x4-pcie-phy", 4965 + .data = &qmp_v6_gen4x4_pciephy_cfg, 5067 4966 }, 5068 4967 { }, 5069 4968 };
+7
drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v6.h
··· 86 86 #define QSERDES_V6_COM_CMN_STATUS 0x1d0 87 87 #define QSERDES_V6_COM_C_READY_STATUS 0x1f8 88 88 89 + #define QSERDES_V6_COM_ADAPTIVE_ANALOG_CONFIG 0x268 90 + #define QSERDES_V6_COM_CP_CTRL_ADAPTIVE_MODE0 0x26c 91 + #define QSERDES_V6_COM_PLL_RCCTRL_ADAPTIVE_MODE0 0x270 92 + #define QSERDES_V6_COM_PLL_CCTRL_ADAPTIVE_MODE0 0x274 93 + #define QSERDES_V6_COM_CP_CTRL_ADAPTIVE_MODE1 0x278 94 + #define QSERDES_V6_COM_PLL_RCCTRL_ADAPTIVE_MODE1 0x27c 95 + #define QSERDES_V6_COM_PLL_CCTRL_ADAPTIVE_MODE1 0x280 89 96 #endif
+67
drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-ufs-v7.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2024, Linaro Limited 4 + */ 5 + 6 + #ifndef QCOM_PHY_QMP_QSERDES_TXRX_UFS_V7_H_ 7 + #define QCOM_PHY_QMP_QSERDES_TXRX_UFS_V7_H_ 8 + 9 + #define QSERDES_UFS_V7_TX_RES_CODE_LANE_TX 0x28 10 + #define QSERDES_UFS_V7_TX_RES_CODE_LANE_RX 0x2c 11 + #define QSERDES_UFS_V7_TX_RES_CODE_LANE_OFFSET_TX 0x30 12 + #define QSERDES_UFS_V7_TX_RES_CODE_LANE_OFFSET_RX 0x34 13 + #define QSERDES_UFS_V7_TX_LANE_MODE_1 0x7c 14 + #define QSERDES_UFS_V7_TX_FR_DCC_CTRL 0x108 15 + 16 + #define QSERDES_UFS_V7_RX_UCDR_FASTLOCK_FO_GAIN_RATE4 0x10 17 + #define QSERDES_UFS_V7_RX_UCDR_FASTLOCK_SO_GAIN_RATE4 0x24 18 + #define QSERDES_UFS_V7_RX_UCDR_SO_SATURATION 0x28 19 + #define QSERDES_UFS_V7_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4 0x54 20 + #define QSERDES_UFS_V7_RX_UCDR_PI_CTRL1 0x58 21 + #define QSERDES_UFS_V7_RX_TERM_BW_CTRL0 0xc4 22 + #define QSERDES_UFS_V7_RX_UCDR_FO_GAIN_RATE2 0xd4 23 + #define QSERDES_UFS_V7_RX_UCDR_FO_GAIN_RATE4 0xdc 24 + #define QSERDES_UFS_V7_RX_UCDR_SO_GAIN_RATE4 0xf0 25 + #define QSERDES_UFS_V7_RX_UCDR_PI_CONTROLS 0xf4 26 + #define QSERDES_UFS_V7_RX_VGA_CAL_MAN_VAL 0x178 27 + #define QSERDES_UFS_V7_RX_EQU_ADAPTOR_CNTRL4 0x1b4 28 + #define QSERDES_UFS_V7_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x1cc 29 + #define QSERDES_UFS_V7_RX_OFFSET_ADAPTOR_CNTRL3 0x1d4 30 + #define QSERDES_UFS_V7_RX_INTERFACE_MODE 0x1f0 31 + #define QSERDES_UFS_V7_RX_MODE_RATE_0_1_B0 0x218 32 + #define QSERDES_UFS_V7_RX_MODE_RATE_0_1_B1 0x21C 33 + #define QSERDES_UFS_V7_RX_MODE_RATE_0_1_B2 0x220 34 + #define QSERDES_UFS_V7_RX_MODE_RATE_0_1_B3 0x224 35 + #define QSERDES_UFS_V7_RX_MODE_RATE_0_1_B4 0x228 36 + #define QSERDES_UFS_V7_RX_MODE_RATE_0_1_B6 0x230 37 + #define QSERDES_UFS_V7_RX_MODE_RATE_0_1_B7 0x234 38 + #define QSERDES_UFS_V7_RX_MODE_RATE2_B3 0x248 39 + #define QSERDES_UFS_V7_RX_MODE_RATE2_B6 0x254 40 + #define QSERDES_UFS_V7_RX_MODE_RATE2_B7 0x258 41 + #define QSERDES_UFS_V7_RX_MODE_RATE3_B0 0x260 42 + #define QSERDES_UFS_V7_RX_MODE_RATE3_B1 0x264 43 + #define QSERDES_UFS_V7_RX_MODE_RATE3_B2 0x268 44 + #define QSERDES_UFS_V7_RX_MODE_RATE3_B3 0x26c 45 + #define QSERDES_UFS_V7_RX_MODE_RATE3_B4 0x270 46 + #define QSERDES_UFS_V7_RX_MODE_RATE3_B5 0x274 47 + #define QSERDES_UFS_V7_RX_MODE_RATE3_B7 0x27c 48 + #define QSERDES_UFS_V7_RX_MODE_RATE3_B8 0x280 49 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SA_B0 0x284 50 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SA_B1 0x288 51 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SA_B2 0x28c 52 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SA_B3 0x290 53 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SA_B4 0x294 54 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SA_B5 0x298 55 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SA_B6 0x29c 56 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SA_B7 0x2a0 57 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SB_B0 0x2a8 58 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SB_B1 0x2ac 59 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SB_B2 0x2b0 60 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SB_B3 0x2b4 61 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SB_B4 0x2b8 62 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SB_B5 0x2bc 63 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SB_B6 0x2c0 64 + #define QSERDES_UFS_V7_RX_MODE_RATE4_SB_B7 0x2c4 65 + #define QSERDES_UFS_V7_RX_DLL0_FTUNE_CTRL 0x348 66 + #define QSERDES_UFS_V7_RX_SIGDET_CAL_TRIM 0x380 67 + #endif
+172 -8
drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
··· 31 31 #include "phy-qcom-qmp-pcs-ufs-v6.h" 32 32 33 33 #include "phy-qcom-qmp-qserdes-txrx-ufs-v6.h" 34 + #include "phy-qcom-qmp-qserdes-txrx-ufs-v7.h" 34 35 35 36 /* QPHY_PCS_READY_STATUS bit */ 36 37 #define PCS_READY BIT(0) ··· 950 949 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME, 0x9e), 951 950 }; 952 951 952 + static const struct qmp_phy_init_tbl sm8750_ufsphy_serdes[] = { 953 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9), 954 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16), 955 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11), 956 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00), 957 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01), 958 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_CFG, 0x60), 959 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x1f), 960 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO_MODE1, 0x1f), 961 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IETRIM, 0x07), 962 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IPTRIM, 0x20), 963 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04), 964 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_CTRL, 0x40), 965 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_ADAPTIVE_ANALOG_CONFIG, 0x06), 966 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41), 967 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06), 968 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18), 969 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x14), 970 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_ADAPTIVE_MODE0, 0x06), 971 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCCTRL_ADAPTIVE_MODE0, 0x18), 972 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_ADAPTIVE_MODE0, 0x14), 973 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x7f), 974 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x06), 975 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x92), 976 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), 977 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x4c), 978 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06), 979 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18), 980 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x14), 981 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_ADAPTIVE_MODE1, 0x06), 982 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCCTRL_ADAPTIVE_MODE1, 0x18), 983 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_ADAPTIVE_MODE1, 0x14), 984 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x99), 985 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x07), 986 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xbe), 987 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), 988 + }; 989 + 990 + static const struct qmp_phy_init_tbl sm8750_ufsphy_tx[] = { 991 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_TX_LANE_MODE_1, 0x00), 992 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_TX_RES_CODE_LANE_OFFSET_TX, 0x07), 993 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_TX_RES_CODE_LANE_OFFSET_RX, 0x17), 994 + }; 995 + 996 + static const struct qmp_phy_init_tbl sm8750_ufsphy_rx[] = { 997 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_FO_GAIN_RATE2, 0x0c), 998 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_FO_GAIN_RATE4, 0x0c), 999 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_SO_GAIN_RATE4, 0x04), 1000 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14), 1001 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_PI_CONTROLS, 0x07), 1002 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_OFFSET_ADAPTOR_CNTRL3, 0x0e), 1003 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4, 0x02), 1004 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_FASTLOCK_FO_GAIN_RATE4, 0x1c), 1005 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_FASTLOCK_SO_GAIN_RATE4, 0x06), 1006 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_VGA_CAL_MAN_VAL, 0x8e), 1007 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_EQU_ADAPTOR_CNTRL4, 0x0f), 1008 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B0, 0xce), 1009 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B1, 0xce), 1010 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B2, 0x18), 1011 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B3, 0x1a), 1012 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B4, 0x0f), 1013 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B6, 0x60), 1014 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B7, 0x62), 1015 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE2_B3, 0x9a), 1016 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE2_B6, 0xe2), 1017 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE2_B7, 0x06), 1018 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B0, 0x1b), 1019 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B1, 0x1b), 1020 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B2, 0x98), 1021 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B3, 0x9b), 1022 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B4, 0x2a), 1023 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B5, 0x12), 1024 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B7, 0x06), 1025 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B8, 0x01), 1026 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B0, 0x93), 1027 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B1, 0x93), 1028 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B2, 0x60), 1029 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B3, 0x99), 1030 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B4, 0x5f), 1031 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B5, 0x92), 1032 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B6, 0xe3), 1033 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B7, 0x06), 1034 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B0, 0x9b), 1035 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B1, 0x9b), 1036 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B2, 0x60), 1037 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B3, 0x99), 1038 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B4, 0x5f), 1039 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B5, 0x92), 1040 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B6, 0xfb), 1041 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B7, 0x06), 1042 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_SO_SATURATION, 0x1f), 1043 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_PI_CTRL1, 0x94), 1044 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_TERM_BW_CTRL0, 0xfa), 1045 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_DLL0_FTUNE_CTRL, 0x30), 1046 + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_SIGDET_CAL_TRIM, 0x77), 1047 + }; 1048 + 1049 + static const struct qmp_phy_init_tbl sm8750_ufsphy_pcs[] = { 1050 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02), 1051 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), 1052 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PCS_CTRL1, 0x40), 1053 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f), 1054 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x68), 1055 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4, 0x0e), 1056 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S5, 0x12), 1057 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S6, 0x15), 1058 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S7, 0x19), 1059 + }; 1060 + 1061 + static const struct qmp_phy_init_tbl sm8750_ufsphy_g4_pcs[] = { 1062 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04), 1063 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04), 1064 + }; 1065 + 1066 + static const struct qmp_phy_init_tbl sm8750_ufsphy_hs_b_pcs[] = { 1067 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PCS_CTRL1, 0x41), 1068 + }; 1069 + 953 1070 struct qmp_ufs_offsets { 954 1071 u16 serdes; 955 1072 u16 pcs; ··· 1642 1523 .regs = ufsphy_v6_regs_layout, 1643 1524 }; 1644 1525 1526 + static const struct qmp_phy_cfg sm8750_ufsphy_cfg = { 1527 + .lanes = 2, 1528 + 1529 + .offsets = &qmp_ufs_offsets_v6, 1530 + .max_supported_gear = UFS_HS_G5, 1531 + 1532 + .tbls = { 1533 + .serdes = sm8750_ufsphy_serdes, 1534 + .serdes_num = ARRAY_SIZE(sm8750_ufsphy_serdes), 1535 + .tx = sm8750_ufsphy_tx, 1536 + .tx_num = ARRAY_SIZE(sm8750_ufsphy_tx), 1537 + .rx = sm8750_ufsphy_rx, 1538 + .rx_num = ARRAY_SIZE(sm8750_ufsphy_rx), 1539 + .pcs = sm8750_ufsphy_pcs, 1540 + .pcs_num = ARRAY_SIZE(sm8750_ufsphy_pcs), 1541 + }, 1542 + 1543 + .tbls_hs_b = { 1544 + .pcs = sm8750_ufsphy_hs_b_pcs, 1545 + .pcs_num = ARRAY_SIZE(sm8750_ufsphy_hs_b_pcs), 1546 + }, 1547 + 1548 + .tbls_hs_overlay[0] = { 1549 + .pcs = sm8750_ufsphy_g4_pcs, 1550 + .pcs_num = ARRAY_SIZE(sm8750_ufsphy_g4_pcs), 1551 + .max_gear = UFS_HS_G4, 1552 + }, 1553 + .tbls_hs_overlay[1] = { 1554 + .pcs = sm8650_ufsphy_g5_pcs, 1555 + .pcs_num = ARRAY_SIZE(sm8650_ufsphy_g5_pcs), 1556 + .max_gear = UFS_HS_G5, 1557 + }, 1558 + 1559 + .vreg_list = qmp_phy_vreg_l, 1560 + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 1561 + .regs = ufsphy_v6_regs_layout, 1562 + 1563 + }; 1564 + 1645 1565 static void qmp_ufs_serdes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbls *tbls) 1646 1566 { 1647 1567 void __iomem *serdes = qmp->serdes; ··· 1736 1578 return ret; 1737 1579 } 1738 1580 1581 + static void qmp_ufs_init_all(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbls *tbls) 1582 + { 1583 + qmp_ufs_serdes_init(qmp, tbls); 1584 + qmp_ufs_lanes_init(qmp, tbls); 1585 + qmp_ufs_pcs_init(qmp, tbls); 1586 + } 1587 + 1739 1588 static void qmp_ufs_init_registers(struct qmp_ufs *qmp, const struct qmp_phy_cfg *cfg) 1740 1589 { 1741 1590 int i; 1742 1591 1743 - qmp_ufs_serdes_init(qmp, &cfg->tbls); 1744 - qmp_ufs_lanes_init(qmp, &cfg->tbls); 1745 - qmp_ufs_pcs_init(qmp, &cfg->tbls); 1592 + qmp_ufs_init_all(qmp, &cfg->tbls); 1746 1593 1747 1594 i = qmp_ufs_get_gear_overlay(qmp, cfg); 1748 1595 if (i >= 0) { 1749 - qmp_ufs_serdes_init(qmp, &cfg->tbls_hs_overlay[i]); 1750 - qmp_ufs_lanes_init(qmp, &cfg->tbls_hs_overlay[i]); 1751 - qmp_ufs_pcs_init(qmp, &cfg->tbls_hs_overlay[i]); 1596 + qmp_ufs_init_all(qmp, &cfg->tbls_hs_overlay[i]); 1752 1597 } 1753 1598 1754 - if (qmp->mode == PHY_MODE_UFS_HS_B) 1755 - qmp_ufs_serdes_init(qmp, &cfg->tbls_hs_b); 1599 + qmp_ufs_init_all(qmp, &cfg->tbls_hs_b); 1756 1600 } 1757 1601 1758 1602 static int qmp_ufs_com_init(struct qmp_ufs *qmp) ··· 2221 2061 }, { 2222 2062 .compatible = "qcom,sm8650-qmp-ufs-phy", 2223 2063 .data = &sm8650_ufsphy_cfg, 2064 + }, { 2065 + .compatible = "qcom,sm8750-qmp-ufs-phy", 2066 + .data = &sm8750_ufsphy_cfg, 2224 2067 }, 2068 + 2225 2069 { }, 2226 2070 }; 2227 2071 MODULE_DEVICE_TABLE(of, qmp_ufs_of_match_table);
+3
drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
··· 1125 1125 .compatible = "qcom,qcm2290-qmp-usb3-phy", 1126 1126 .data = &qcm2290_usb3phy_cfg, 1127 1127 }, { 1128 + .compatible = "qcom,qcs615-qmp-usb3-phy", 1129 + .data = &qcm2290_usb3phy_cfg, 1130 + }, { 1128 1131 .compatible = "qcom,sdm660-qmp-usb3-phy", 1129 1132 .data = &sdm660_usb3phy_cfg, 1130 1133 }, {
+286
drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (c) 2025, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #include <linux/clk.h> 7 + #include <linux/clk-provider.h> 8 + #include <linux/delay.h> 9 + #include <linux/err.h> 10 + #include <linux/io.h> 11 + #include <linux/mfd/syscon.h> 12 + #include <linux/module.h> 13 + #include <linux/of_device.h> 14 + #include <linux/of.h> 15 + #include <linux/phy/phy.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/regmap.h> 18 + #include <linux/reset.h> 19 + #include <linux/units.h> 20 + 21 + #define RST_ASSERT_DELAY_MIN_US 100 22 + #define RST_ASSERT_DELAY_MAX_US 150 23 + #define PIPE_CLK_DELAY_MIN_US 5000 24 + #define PIPE_CLK_DELAY_MAX_US 5100 25 + #define CLK_EN_DELAY_MIN_US 30 26 + #define CLK_EN_DELAY_MAX_US 50 27 + #define CDR_CTRL_REG_1 0x80 28 + #define CDR_CTRL_REG_2 0x84 29 + #define CDR_CTRL_REG_3 0x88 30 + #define CDR_CTRL_REG_4 0x8c 31 + #define CDR_CTRL_REG_5 0x90 32 + #define CDR_CTRL_REG_6 0x94 33 + #define CDR_CTRL_REG_7 0x98 34 + #define SSCG_CTRL_REG_1 0x9c 35 + #define SSCG_CTRL_REG_2 0xa0 36 + #define SSCG_CTRL_REG_3 0xa4 37 + #define SSCG_CTRL_REG_4 0xa8 38 + #define SSCG_CTRL_REG_5 0xac 39 + #define SSCG_CTRL_REG_6 0xb0 40 + #define PCS_INTERNAL_CONTROL_2 0x2d8 41 + 42 + #define PHY_CFG_PLLCFG 0x220 43 + #define PHY_CFG_EIOS_DTCT_REG 0x3e4 44 + #define PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME 0x3e8 45 + 46 + enum qcom_uniphy_pcie_type { 47 + PHY_TYPE_PCIE = 1, 48 + PHY_TYPE_PCIE_GEN2, 49 + PHY_TYPE_PCIE_GEN3, 50 + }; 51 + 52 + struct qcom_uniphy_pcie_regs { 53 + u32 offset; 54 + u32 val; 55 + }; 56 + 57 + struct qcom_uniphy_pcie_data { 58 + int lane_offset; /* offset between the lane register bases */ 59 + u32 phy_type; 60 + const struct qcom_uniphy_pcie_regs *init_seq; 61 + u32 init_seq_num; 62 + u32 pipe_clk_rate; 63 + }; 64 + 65 + struct qcom_uniphy_pcie { 66 + struct phy phy; 67 + struct device *dev; 68 + const struct qcom_uniphy_pcie_data *data; 69 + struct clk_bulk_data *clks; 70 + int num_clks; 71 + struct reset_control *resets; 72 + void __iomem *base; 73 + int lanes; 74 + }; 75 + 76 + #define phy_to_dw_phy(x) container_of((x), struct qca_uni_pcie_phy, phy) 77 + 78 + static const struct qcom_uniphy_pcie_regs ipq5332_regs[] = { 79 + { 80 + .offset = PHY_CFG_PLLCFG, 81 + .val = 0x30, 82 + }, { 83 + .offset = PHY_CFG_EIOS_DTCT_REG, 84 + .val = 0x53ef, 85 + }, { 86 + .offset = PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME, 87 + .val = 0xcf, 88 + }, 89 + }; 90 + 91 + static const struct qcom_uniphy_pcie_data ipq5332_data = { 92 + .lane_offset = 0x800, 93 + .phy_type = PHY_TYPE_PCIE_GEN3, 94 + .init_seq = ipq5332_regs, 95 + .init_seq_num = ARRAY_SIZE(ipq5332_regs), 96 + .pipe_clk_rate = 250 * MEGA, 97 + }; 98 + 99 + static void qcom_uniphy_pcie_init(struct qcom_uniphy_pcie *phy) 100 + { 101 + const struct qcom_uniphy_pcie_data *data = phy->data; 102 + const struct qcom_uniphy_pcie_regs *init_seq; 103 + void __iomem *base = phy->base; 104 + int lane, i; 105 + 106 + for (lane = 0; lane < phy->lanes; lane++) { 107 + init_seq = data->init_seq; 108 + 109 + for (i = 0; i < data->init_seq_num; i++) 110 + writel(init_seq[i].val, base + init_seq[i].offset); 111 + 112 + base += data->lane_offset; 113 + } 114 + } 115 + 116 + static int qcom_uniphy_pcie_power_off(struct phy *x) 117 + { 118 + struct qcom_uniphy_pcie *phy = phy_get_drvdata(x); 119 + 120 + clk_bulk_disable_unprepare(phy->num_clks, phy->clks); 121 + 122 + return reset_control_assert(phy->resets); 123 + } 124 + 125 + static int qcom_uniphy_pcie_power_on(struct phy *x) 126 + { 127 + struct qcom_uniphy_pcie *phy = phy_get_drvdata(x); 128 + int ret; 129 + 130 + ret = reset_control_assert(phy->resets); 131 + if (ret) { 132 + dev_err(phy->dev, "reset assert failed (%d)\n", ret); 133 + return ret; 134 + } 135 + 136 + usleep_range(RST_ASSERT_DELAY_MIN_US, RST_ASSERT_DELAY_MAX_US); 137 + 138 + ret = reset_control_deassert(phy->resets); 139 + if (ret) { 140 + dev_err(phy->dev, "reset deassert failed (%d)\n", ret); 141 + return ret; 142 + } 143 + 144 + usleep_range(PIPE_CLK_DELAY_MIN_US, PIPE_CLK_DELAY_MAX_US); 145 + 146 + ret = clk_bulk_prepare_enable(phy->num_clks, phy->clks); 147 + if (ret) { 148 + dev_err(phy->dev, "clk prepare and enable failed %d\n", ret); 149 + return ret; 150 + } 151 + 152 + usleep_range(CLK_EN_DELAY_MIN_US, CLK_EN_DELAY_MAX_US); 153 + 154 + qcom_uniphy_pcie_init(phy); 155 + 156 + return 0; 157 + } 158 + 159 + static inline int qcom_uniphy_pcie_get_resources(struct platform_device *pdev, 160 + struct qcom_uniphy_pcie *phy) 161 + { 162 + struct resource *res; 163 + 164 + phy->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 165 + if (IS_ERR(phy->base)) 166 + return PTR_ERR(phy->base); 167 + 168 + phy->num_clks = devm_clk_bulk_get_all(phy->dev, &phy->clks); 169 + if (phy->num_clks < 0) 170 + return phy->num_clks; 171 + 172 + phy->resets = devm_reset_control_array_get_exclusive(phy->dev); 173 + if (IS_ERR(phy->resets)) 174 + return PTR_ERR(phy->resets); 175 + 176 + return 0; 177 + } 178 + 179 + /* 180 + * Register a fixed rate pipe clock. 181 + * 182 + * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate 183 + * controls it. The <s>_pipe_clk coming out of the GCC is requested 184 + * by the PHY driver for its operations. 185 + * We register the <s>_pipe_clksrc here. The gcc driver takes care 186 + * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk. 187 + * Below picture shows this relationship. 188 + * 189 + * +---------------+ 190 + * | PHY block |<<---------------------------------------+ 191 + * | | | 192 + * | +-------+ | +-----+ | 193 + * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ 194 + * clk | +-------+ | +-----+ 195 + * +---------------+ 196 + */ 197 + static inline int phy_pipe_clk_register(struct qcom_uniphy_pcie *phy, int id) 198 + { 199 + const struct qcom_uniphy_pcie_data *data = phy->data; 200 + struct clk_hw *hw; 201 + char name[64]; 202 + 203 + snprintf(name, sizeof(name), "phy%d_pipe_clk_src", id); 204 + hw = devm_clk_hw_register_fixed_rate(phy->dev, name, NULL, 0, 205 + data->pipe_clk_rate); 206 + if (IS_ERR(hw)) 207 + return dev_err_probe(phy->dev, PTR_ERR(hw), 208 + "Unable to register %s\n", name); 209 + 210 + return devm_of_clk_add_hw_provider(phy->dev, of_clk_hw_simple_get, hw); 211 + } 212 + 213 + static const struct of_device_id qcom_uniphy_pcie_id_table[] = { 214 + { 215 + .compatible = "qcom,ipq5332-uniphy-pcie-phy", 216 + .data = &ipq5332_data, 217 + }, { 218 + /* Sentinel */ 219 + }, 220 + }; 221 + MODULE_DEVICE_TABLE(of, qcom_uniphy_pcie_id_table); 222 + 223 + static const struct phy_ops pcie_ops = { 224 + .power_on = qcom_uniphy_pcie_power_on, 225 + .power_off = qcom_uniphy_pcie_power_off, 226 + .owner = THIS_MODULE, 227 + }; 228 + 229 + static int qcom_uniphy_pcie_probe(struct platform_device *pdev) 230 + { 231 + struct phy_provider *phy_provider; 232 + struct device *dev = &pdev->dev; 233 + struct qcom_uniphy_pcie *phy; 234 + struct phy *generic_phy; 235 + int ret; 236 + 237 + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); 238 + if (!phy) 239 + return -ENOMEM; 240 + 241 + platform_set_drvdata(pdev, phy); 242 + phy->dev = &pdev->dev; 243 + 244 + phy->data = of_device_get_match_data(dev); 245 + if (!phy->data) 246 + return -EINVAL; 247 + 248 + ret = of_property_read_u32(dev_of_node(dev), "num-lanes", &phy->lanes); 249 + if (ret) 250 + return dev_err_probe(dev, ret, "Couldn't read num-lanes\n"); 251 + 252 + ret = qcom_uniphy_pcie_get_resources(pdev, phy); 253 + if (ret < 0) 254 + return dev_err_probe(&pdev->dev, ret, 255 + "failed to get resources: %d\n", ret); 256 + 257 + generic_phy = devm_phy_create(phy->dev, NULL, &pcie_ops); 258 + if (IS_ERR(generic_phy)) 259 + return PTR_ERR(generic_phy); 260 + 261 + phy_set_drvdata(generic_phy, phy); 262 + 263 + ret = phy_pipe_clk_register(phy, generic_phy->id); 264 + if (ret) 265 + dev_err(&pdev->dev, "failed to register phy pipe clk\n"); 266 + 267 + phy_provider = devm_of_phy_provider_register(phy->dev, 268 + of_phy_simple_xlate); 269 + if (IS_ERR(phy_provider)) 270 + return PTR_ERR(phy_provider); 271 + 272 + return 0; 273 + } 274 + 275 + static struct platform_driver qcom_uniphy_pcie_driver = { 276 + .probe = qcom_uniphy_pcie_probe, 277 + .driver = { 278 + .name = "qcom-uniphy-pcie", 279 + .of_match_table = qcom_uniphy_pcie_id_table, 280 + }, 281 + }; 282 + 283 + module_platform_driver(qcom_uniphy_pcie_driver); 284 + 285 + MODULE_DESCRIPTION("PCIE QCOM UNIPHY driver"); 286 + MODULE_LICENSE("GPL");
+12
drivers/phy/rockchip/Kconfig
··· 83 83 help 84 84 Enable this to support the Rockchip PCIe PHY. 85 85 86 + config PHY_ROCKCHIP_SAMSUNG_DCPHY 87 + tristate "Rockchip Samsung MIPI DCPHY driver" 88 + depends on (ARCH_ROCKCHIP || COMPILE_TEST) 89 + select GENERIC_PHY 90 + select GENERIC_PHY_MIPI_DPHY 91 + help 92 + Enable this to support the Rockchip MIPI DCPHY with 93 + Samsung IP block. 94 + 95 + To compile this driver as a module, choose M here: the module 96 + will be called phy-rockchip-samsung-dcphy 97 + 86 98 config PHY_ROCKCHIP_SAMSUNG_HDPTX 87 99 tristate "Rockchip Samsung HDMI/eDP Combo PHY driver" 88 100 depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
+1
drivers/phy/rockchip/Makefile
··· 8 8 obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o 9 9 obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o 10 10 obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o 11 + obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_DCPHY) += phy-rockchip-samsung-dcphy.o 11 12 obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX) += phy-rockchip-samsung-hdptx.o 12 13 obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o 13 14 obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
+2 -2
drivers/phy/rockchip/phy-rockchip-inno-usb2.c
··· 440 440 struct extcon_dev *edev; 441 441 int ret; 442 442 443 - if (of_property_read_bool(node, "extcon")) { 443 + if (of_property_present(node, "extcon")) { 444 444 edev = extcon_get_edev_by_phandle(rphy->dev, 0); 445 445 if (IS_ERR(edev)) 446 446 return dev_err_probe(rphy->dev, PTR_ERR(edev), ··· 1323 1323 goto out; 1324 1324 } 1325 1325 1326 - if (!of_property_read_bool(rphy->dev->of_node, "extcon")) { 1326 + if (!of_property_present(rphy->dev->of_node, "extcon")) { 1327 1327 /* do initial sync of usb state */ 1328 1328 id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); 1329 1329 extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id);
+152
drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
··· 396 396 return PTR_ERR_OR_ZERO(phy_provider); 397 397 } 398 398 399 + static int rk3562_combphy_cfg(struct rockchip_combphy_priv *priv) 400 + { 401 + const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; 402 + unsigned long rate; 403 + u32 val; 404 + 405 + switch (priv->type) { 406 + case PHY_TYPE_PCIE: 407 + /* Set SSC downward spread spectrum */ 408 + rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, 409 + PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, 410 + PHYREG32); 411 + 412 + rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true); 413 + rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true); 414 + rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true); 415 + rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true); 416 + break; 417 + case PHY_TYPE_USB3: 418 + /* Set SSC downward spread spectrum */ 419 + rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, 420 + PHYREG32_SSC_DOWNWARD << PHYREG32_SSC_DIR_SHIFT, 421 + PHYREG32); 422 + 423 + /* Enable adaptive CTLE for USB3.0 Rx */ 424 + rockchip_combphy_updatel(priv, PHYREG15_CTLE_EN, 425 + PHYREG15_CTLE_EN, PHYREG15); 426 + 427 + /* Set PLL KVCO fine tuning signals */ 428 + rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, BIT(3), PHYREG33); 429 + 430 + /* Set PLL LPF R1 to su_trim[10:7]=1001 */ 431 + writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12); 432 + 433 + /* Set PLL input clock divider 1/2 */ 434 + val = FIELD_PREP(PHYREG6_PLL_DIV_MASK, PHYREG6_PLL_DIV_2); 435 + rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, val, PHYREG6); 436 + 437 + /* Set PLL loop divider */ 438 + writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18); 439 + 440 + /* Set PLL KVCO to min and set PLL charge pump current to max */ 441 + writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11); 442 + 443 + rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); 444 + rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); 445 + rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); 446 + rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true); 447 + break; 448 + default: 449 + dev_err(priv->dev, "incompatible PHY type\n"); 450 + return -EINVAL; 451 + } 452 + 453 + rate = clk_get_rate(priv->refclk); 454 + 455 + switch (rate) { 456 + case REF_CLOCK_24MHz: 457 + if (priv->type == PHY_TYPE_USB3) { 458 + /* Set ssc_cnt[9:0]=0101111101 & 31.5KHz */ 459 + val = FIELD_PREP(PHYREG15_SSC_CNT_MASK, PHYREG15_SSC_CNT_VALUE); 460 + rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK, 461 + val, PHYREG15); 462 + 463 + writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16); 464 + } 465 + break; 466 + case REF_CLOCK_25MHz: 467 + rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true); 468 + break; 469 + case REF_CLOCK_100MHz: 470 + rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); 471 + if (priv->type == PHY_TYPE_PCIE) { 472 + /* PLL KVCO tuning fine */ 473 + val = FIELD_PREP(PHYREG33_PLL_KVCO_MASK, PHYREG33_PLL_KVCO_VALUE); 474 + rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, 475 + val, PHYREG33); 476 + 477 + /* Enable controlling random jitter, aka RMJ */ 478 + writel(0x4, priv->mmio + PHYREG12); 479 + 480 + val = PHYREG6_PLL_DIV_2 << PHYREG6_PLL_DIV_SHIFT; 481 + rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, 482 + val, PHYREG6); 483 + 484 + writel(0x32, priv->mmio + PHYREG18); 485 + writel(0xf0, priv->mmio + PHYREG11); 486 + } 487 + break; 488 + default: 489 + dev_err(priv->dev, "Unsupported rate: %lu\n", rate); 490 + return -EINVAL; 491 + } 492 + 493 + if (priv->ext_refclk) { 494 + rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true); 495 + if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) { 496 + val = PHYREG13_RESISTER_HIGH_Z << PHYREG13_RESISTER_SHIFT; 497 + val |= PHYREG13_CKRCV_AMP0; 498 + rockchip_combphy_updatel(priv, PHYREG13_RESISTER_MASK, val, PHYREG13); 499 + 500 + val = readl(priv->mmio + PHYREG14); 501 + val |= PHYREG14_CKRCV_AMP1; 502 + writel(val, priv->mmio + PHYREG14); 503 + } 504 + } 505 + 506 + if (priv->enable_ssc) { 507 + val = readl(priv->mmio + PHYREG8); 508 + val |= PHYREG8_SSC_EN; 509 + writel(val, priv->mmio + PHYREG8); 510 + } 511 + 512 + return 0; 513 + } 514 + 515 + static const struct rockchip_combphy_grfcfg rk3562_combphy_grfcfgs = { 516 + /* pipe-phy-grf */ 517 + .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, 518 + .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, 519 + .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, 520 + .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, 521 + .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, 522 + .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, 523 + .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, 524 + .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 }, 525 + .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 }, 526 + .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, 527 + .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, 528 + .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, 529 + .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, 530 + .pipe_sel_usb = { 0x000c, 14, 13, 0x00, 0x01 }, 531 + .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, 532 + .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, 533 + .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, 534 + .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, 535 + .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, 536 + }; 537 + 538 + static const struct rockchip_combphy_cfg rk3562_combphy_cfgs = { 539 + .num_phys = 1, 540 + .phy_ids = { 541 + 0xff750000 542 + }, 543 + .grfcfg = &rk3562_combphy_grfcfgs, 544 + .combphy_cfg = rk3562_combphy_cfg, 545 + }; 546 + 399 547 static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) 400 548 { 401 549 const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; ··· 1197 1049 }; 1198 1050 1199 1051 static const struct of_device_id rockchip_combphy_of_match[] = { 1052 + { 1053 + .compatible = "rockchip,rk3562-naneng-combphy", 1054 + .data = &rk3562_combphy_cfgs, 1055 + }, 1200 1056 { 1201 1057 .compatible = "rockchip,rk3568-naneng-combphy", 1202 1058 .data = &rk3568_combphy_cfgs,
+1719
drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (C) 2025 Rockchip Electronics Co.Ltd 4 + * Author: 5 + * Guochun Huang <hero.huang@rock-chips.com> 6 + */ 7 + 8 + #include <dt-bindings/phy/phy.h> 9 + #include <linux/bitfield.h> 10 + #include <linux/clk.h> 11 + #include <linux/init.h> 12 + #include <linux/kernel.h> 13 + #include <linux/mfd/syscon.h> 14 + #include <linux/module.h> 15 + #include <linux/mod_devicetable.h> 16 + #include <linux/of.h> 17 + #include <linux/phy/phy.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/pm_runtime.h> 20 + #include <linux/regmap.h> 21 + #include <linux/reset.h> 22 + 23 + #define FIELD_PREP_HIWORD(_mask, _val) \ 24 + ( \ 25 + FIELD_PREP((_mask), (_val)) | \ 26 + ((_mask) << 16) \ 27 + ) 28 + 29 + #define BIAS_CON0 0x0000 30 + #define I_RES_CNTL_MASK GENMASK(6, 4) 31 + #define I_RES_CNTL(x) FIELD_PREP(I_RES_CNTL_MASK, x) 32 + #define I_RES_059_2UA I_RES_CNTL(0) 33 + #define I_RES_100_2UA I_RES_CNTL(1) 34 + #define I_RES_094_2UA I_RES_CNTL(2) 35 + #define I_RES_113_8UA I_RES_CNTL(3) 36 + #define I_RES_089_7UA I_RES_CNTL(4) 37 + #define I_RES_111_8UA I_RES_CNTL(5) 38 + #define I_RES_108_2UA I_RES_CNTL(6) 39 + #define I_RES_120_8UA I_RES_CNTL(7) 40 + #define I_DEV_SEL_MASK GENMASK(1, 0) 41 + #define I_DEV_SEL(x) FIELD_PREP(I_DEV_SEL_MASK, x) 42 + #define I_DEV_DIV_6 I_DEV_SEL(0) 43 + #define I_DEV_DIV_12 I_DEV_SEL(1) 44 + #define I_DEV_DIV_20 I_DEV_SEL(2) 45 + #define I_DEV_DIV_40 I_DEV_SEL(3) 46 + 47 + #define BIAS_CON1 0x0004 48 + #define I_VBG_SEL_MASK GENMASK(9, 8) 49 + #define I_VBG_SEL(x) FIELD_PREP(I_VBG_SEL_MASK, x) 50 + #define I_VBG_SEL_780MV I_VBG_SEL(0) 51 + #define I_VBG_SEL_820MV I_VBG_SEL(1) 52 + #define I_VBG_SEL_860MV I_VBG_SEL(2) 53 + #define I_VBG_SEL_900MV I_VBG_SEL(3) 54 + #define I_BGR_VREF_SEL_MASK GENMASK(5, 4) 55 + #define I_BGR_VREF_SEL(x) FIELD_PREP(I_BGR_VREF_SEL_MASK, x) 56 + #define I_BGR_VREF_810MV I_BGR_VREF_SEL(0) 57 + #define I_BGR_VREF_820MV I_BGR_VREF_SEL(1) 58 + #define I_BGR_VREF_830MV I_BGR_VREF_SEL(2) 59 + #define I_BGR_VREF_840MV I_BGR_VREF_SEL(3) 60 + #define I_LADDER_SEL_MASK GENMASK(2, 0) 61 + #define I_LADDER_SEL(x) FIELD_PREP(I_LADDER_SEL_MASK, x) 62 + #define I_LADDER_1_00V I_LADDER_SEL(0) 63 + #define I_LADDER_0_96V I_LADDER_SEL(1) 64 + #define I_LADDER_0_92V I_LADDER_SEL(2) 65 + #define I_LADDER_0_88V I_LADDER_SEL(3) 66 + #define I_LADDER_0_84V I_LADDER_SEL(4) 67 + #define I_LADDER_0_80V I_LADDER_SEL(5) 68 + #define I_LADDER_0_76V I_LADDER_SEL(6) 69 + #define I_LADDER_0_72V I_LADDER_SEL(7) 70 + 71 + /* 72 + * Voltage corrections around reference voltages 73 + * The selection between the 400-based or 200-based values for REG_400M 74 + * is done by the hw depending on I_MUX below being 400MV or 200MV. 75 + */ 76 + #define BIAS_CON2 0x0008 77 + #define REG_325M_MASK GENMASK(14, 12) 78 + #define REG_325M(x) FIELD_PREP(REG_325M_MASK, x) 79 + #define REG_325M_295MV REG_325M(0) 80 + #define REG_325M_305MV REG_325M(1) 81 + #define REG_325M_315MV REG_325M(2) 82 + #define REG_325M_325MV REG_325M(3) 83 + #define REG_325M_335MV REG_325M(4) 84 + #define REG_325M_345MV REG_325M(5) 85 + #define REG_325M_355MV REG_325M(6) 86 + #define REG_325M_365MV REG_325M(7) 87 + #define REG_LP_400M_MASK GENMASK(10, 8) 88 + #define REG_LP_400M(x) FIELD_PREP(REG_LP_400M_MASK, x) 89 + #define REG_LP_400M_380MV REG_LP_400M(0) 90 + #define REG_LP_400M_390MV REG_LP_400M(1) 91 + #define REG_LP_400M_400MV REG_LP_400M(2) 92 + #define REG_LP_400M_410MV REG_LP_400M(3) 93 + #define REG_LP_400M_420MV REG_LP_400M(4) 94 + #define REG_LP_400M_430MV REG_LP_400M(5) 95 + #define REG_LP_400M_440MV REG_LP_400M(6) 96 + #define REG_LP_400M_450MV REG_LP_400M(7) 97 + #define REG_400M_MASK GENMASK(6, 4) 98 + #define REG_400M(x) FIELD_PREP(REG_400M_MASK, x) 99 + #define REG_400M_380MV REG_400M(0) 100 + #define REG_400M_390MV REG_400M(1) 101 + #define REG_400M_400MV REG_400M(2) 102 + #define REG_400M_410MV REG_400M(3) 103 + #define REG_400M_420MV REG_400M(4) 104 + #define REG_400M_430MV REG_400M(5) 105 + #define REG_400M_440MV REG_400M(6) 106 + #define REG_400M_450MV REG_400M(7) 107 + #define REG_400M_230MV REG_400M(0) 108 + #define REG_400M_220MV REG_400M(1) 109 + #define REG_400M_210MV REG_400M(2) 110 + #define REG_400M_200MV REG_400M(3) 111 + #define REG_400M_190MV REG_400M(4) 112 + #define REG_400M_180MV REG_400M(5) 113 + #define REG_400M_170MV REG_400M(6) 114 + #define REG_400M_160MV REG_400M(7) 115 + #define REG_645M_MASK GENMASK(2, 0) 116 + #define REG_645M(x) FIELD_PREP(REG_645M_MASK, x) 117 + #define REG_645M_605MV REG_645M(0) 118 + #define REG_645M_625MV REG_645M(1) 119 + #define REG_645M_635MV REG_645M(2) 120 + #define REG_645M_645MV REG_645M(3) 121 + #define REG_645M_655MV REG_645M(4) 122 + #define REG_645M_665MV REG_645M(5) 123 + #define REG_645M_685MV REG_645M(6) 124 + #define REG_645M_725MV REG_645M(7) 125 + 126 + #define BIAS_CON4 0x0010 127 + #define I_MUX_SEL_MASK GENMASK(6, 5) 128 + #define I_MUX_SEL(x) FIELD_PREP(I_MUX_SEL_MASK, x) 129 + #define I_MUX_400MV I_MUX_SEL(0) 130 + #define I_MUX_200MV I_MUX_SEL(1) 131 + #define I_MUX_530MV I_MUX_SEL(2) 132 + 133 + #define PLL_CON0 0x0100 134 + #define PLL_EN BIT(12) 135 + #define S_MASK GENMASK(10, 8) 136 + #define S(x) FIELD_PREP(S_MASK, x) 137 + #define P_MASK GENMASK(5, 0) 138 + #define P(x) FIELD_PREP(P_MASK, x) 139 + #define PLL_CON1 0x0104 140 + #define PLL_CON2 0x0108 141 + #define M_MASK GENMASK(9, 0) 142 + #define M(x) FIELD_PREP(M_MASK, x) 143 + #define PLL_CON3 0x010c 144 + #define MRR_MASK GENMASK(13, 8) 145 + #define MRR(x) FIELD_PREP(MRR_MASK, x) 146 + #define MFR_MASK GENMASK(7, 0) 147 + #define MFR(x) FIELD_PREP(MFR_MASK, x) 148 + #define PLL_CON4 0x0110 149 + #define SSCG_EN BIT(11) 150 + #define PLL_CON5 0x0114 151 + #define RESET_N_SEL BIT(10) 152 + #define PLL_ENABLE_SEL BIT(8) 153 + #define PLL_CON6 0x0118 154 + #define PLL_CON7 0x011c 155 + #define PLL_LOCK_CNT(x) FIELD_PREP(GENMASK(15, 0), x) 156 + #define PLL_CON8 0x0120 157 + #define PLL_STB_CNT(x) FIELD_PREP(GENMASK(15, 0), x) 158 + #define PLL_STAT0 0x0140 159 + #define PLL_LOCK BIT(0) 160 + 161 + #define DPHY_MC_GNR_CON0 0x0300 162 + #define PHY_READY BIT(1) 163 + #define PHY_ENABLE BIT(0) 164 + #define DPHY_MC_GNR_CON1 0x0304 165 + #define T_PHY_READY(x) FIELD_PREP(GENMASK(15, 0), x) 166 + #define DPHY_MC_ANA_CON0 0x0308 167 + #define EDGE_CON(x) FIELD_PREP(GENMASK(14, 12), x) 168 + #define EDGE_CON_DIR(x) FIELD_PREP(BIT(9), x) 169 + #define EDGE_CON_EN BIT(8) 170 + #define RES_UP(x) FIELD_PREP(GENMASK(7, 4), x) 171 + #define RES_DN(x) FIELD_PREP(GENMASK(3, 0), x) 172 + #define DPHY_MC_ANA_CON1 0x030c 173 + #define DPHY_MC_ANA_CON2 0x0310 174 + #define HS_VREG_AMP_ICON(x) FIELD_PREP(GENMASK(1, 0), x) 175 + #define DPHY_MC_TIME_CON0 0x0330 176 + #define HSTX_CLK_SEL BIT(12) 177 + #define T_LPX(x) FIELD_PREP(GENMASK(11, 4), x) 178 + #define DPHY_MC_TIME_CON1 0x0334 179 + #define T_CLK_ZERO(x) FIELD_PREP(GENMASK(15, 8), x) 180 + #define T_CLK_PREPARE(x) FIELD_PREP(GENMASK(7, 0), x) 181 + #define DPHY_MC_TIME_CON2 0x0338 182 + #define T_HS_EXIT(x) FIELD_PREP(GENMASK(15, 8), x) 183 + #define T_CLK_TRAIL(x) FIELD_PREP(GENMASK(7, 0), x) 184 + #define DPHY_MC_TIME_CON3 0x033c 185 + #define T_CLK_POST(x) FIELD_PREP(GENMASK(7, 0), x) 186 + #define DPHY_MC_TIME_CON4 0x0340 187 + #define T_ULPS_EXIT(x) FIELD_PREP(GENMASK(9, 0), x) 188 + #define DPHY_MC_DESKEW_CON0 0x0350 189 + #define SKEW_CAL_RUN_TIME(x) FIELD_PREP(GENMASK(15, 12), x) 190 + 191 + #define SKEW_CAL_INIT_RUN_TIME(x) FIELD_PREP(GENMASK(11, 8), x) 192 + #define SKEW_CAL_INIT_WAIT_TIME(x) FIELD_PREP(GENMASK(7, 4), x) 193 + #define SKEW_CAL_EN BIT(0) 194 + 195 + #define COMBO_MD0_GNR_CON0 0x0400 196 + #define COMBO_MD0_GNR_CON1 0x0404 197 + #define COMBO_MD0_ANA_CON0 0x0408 198 + #define COMBO_MD0_ANA_CON1 0x040c 199 + #define COMBO_MD0_ANA_CON2 0x0410 200 + 201 + #define COMBO_MD0_TIME_CON0 0x0430 202 + #define COMBO_MD0_TIME_CON1 0x0434 203 + #define COMBO_MD0_TIME_CON2 0x0438 204 + #define COMBO_MD0_TIME_CON3 0x043c 205 + #define COMBO_MD0_TIME_CON4 0x0440 206 + #define COMBO_MD0_DATA_CON0 0x0444 207 + 208 + #define COMBO_MD1_GNR_CON0 0x0500 209 + #define COMBO_MD1_GNR_CON1 0x0504 210 + #define COMBO_MD1_ANA_CON0 0x0508 211 + #define COMBO_MD1_ANA_CON1 0x050c 212 + #define COMBO_MD1_ANA_CON2 0x0510 213 + #define COMBO_MD1_TIME_CON0 0x0530 214 + #define COMBO_MD1_TIME_CON1 0x0534 215 + #define COMBO_MD1_TIME_CON2 0x0538 216 + #define COMBO_MD1_TIME_CON3 0x053c 217 + #define COMBO_MD1_TIME_CON4 0x0540 218 + #define COMBO_MD1_DATA_CON0 0x0544 219 + 220 + #define COMBO_MD2_GNR_CON0 0x0600 221 + #define COMBO_MD2_GNR_CON1 0x0604 222 + #define COMBO_MD2_ANA_CON0 0X0608 223 + #define COMBO_MD2_ANA_CON1 0X060c 224 + #define COMBO_MD2_ANA_CON2 0X0610 225 + #define COMBO_MD2_TIME_CON0 0x0630 226 + #define COMBO_MD2_TIME_CON1 0x0634 227 + #define COMBO_MD2_TIME_CON2 0x0638 228 + #define COMBO_MD2_TIME_CON3 0x063c 229 + #define COMBO_MD2_TIME_CON4 0x0640 230 + #define COMBO_MD2_DATA_CON0 0x0644 231 + 232 + #define DPHY_MD3_GNR_CON0 0x0700 233 + #define DPHY_MD3_GNR_CON1 0x0704 234 + #define DPHY_MD3_ANA_CON0 0X0708 235 + #define DPHY_MD3_ANA_CON1 0X070c 236 + #define DPHY_MD3_ANA_CON2 0X0710 237 + #define DPHY_MD3_TIME_CON0 0x0730 238 + #define DPHY_MD3_TIME_CON1 0x0734 239 + #define DPHY_MD3_TIME_CON2 0x0738 240 + #define DPHY_MD3_TIME_CON3 0x073c 241 + #define DPHY_MD3_TIME_CON4 0x0740 242 + #define DPHY_MD3_DATA_CON0 0x0744 243 + 244 + #define T_LP_EXIT_SKEW(x) FIELD_PREP(GENMASK(3, 2), x) 245 + #define T_LP_ENTRY_SKEW(x) FIELD_PREP(GENMASK(1, 0), x) 246 + #define T_HS_ZERO(x) FIELD_PREP(GENMASK(15, 8), x) 247 + #define T_HS_PREPARE(x) FIELD_PREP(GENMASK(7, 0), x) 248 + #define T_HS_EXIT(x) FIELD_PREP(GENMASK(15, 8), x) 249 + #define T_HS_TRAIL(x) FIELD_PREP(GENMASK(7, 0), x) 250 + #define T_TA_GET(x) FIELD_PREP(GENMASK(7, 4), x) 251 + #define T_TA_GO(x) FIELD_PREP(GENMASK(3, 0), x) 252 + 253 + /* MIPI_CDPHY_GRF registers */ 254 + #define MIPI_DCPHY_GRF_CON0 0x0000 255 + #define S_CPHY_MODE FIELD_PREP_HIWORD(BIT(3), 1) 256 + #define M_CPHY_MODE FIELD_PREP_HIWORD(BIT(0), 1) 257 + 258 + enum hs_drv_res_ohm { 259 + STRENGTH_30_OHM = 0x8, 260 + STRENGTH_31_2_OHM, 261 + STRENGTH_32_5_OHM, 262 + STRENGTH_34_OHM, 263 + STRENGTH_35_5_OHM, 264 + STRENGTH_37_OHM, 265 + STRENGTH_39_OHM, 266 + STRENGTH_41_OHM, 267 + STRENGTH_43_OHM = 0x0, 268 + STRENGTH_46_OHM, 269 + STRENGTH_49_OHM, 270 + STRENGTH_52_OHM, 271 + STRENGTH_56_OHM, 272 + STRENGTH_60_OHM, 273 + STRENGTH_66_OHM, 274 + STRENGTH_73_OHM, 275 + }; 276 + 277 + struct hs_drv_res_cfg { 278 + enum hs_drv_res_ohm clk_hs_drv_up_ohm; 279 + enum hs_drv_res_ohm clk_hs_drv_down_ohm; 280 + enum hs_drv_res_ohm data_hs_drv_up_ohm; 281 + enum hs_drv_res_ohm data_hs_drv_down_ohm; 282 + }; 283 + 284 + struct samsung_mipi_dcphy_plat_data { 285 + const struct hs_drv_res_cfg *dphy_hs_drv_res_cfg; 286 + u32 dphy_tx_max_lane_kbps; 287 + }; 288 + 289 + struct samsung_mipi_dcphy { 290 + struct device *dev; 291 + struct clk *ref_clk; 292 + struct clk *pclk; 293 + struct regmap *regmap; 294 + struct regmap *grf_regmap; 295 + struct reset_control *m_phy_rst; 296 + struct reset_control *s_phy_rst; 297 + struct reset_control *apb_rst; 298 + struct reset_control *grf_apb_rst; 299 + unsigned int lanes; 300 + struct phy *phy; 301 + u8 type; 302 + 303 + const struct samsung_mipi_dcphy_plat_data *pdata; 304 + struct { 305 + unsigned long long rate; 306 + u8 prediv; 307 + u16 fbdiv; 308 + long dsm; 309 + u8 scaler; 310 + 311 + bool ssc_en; 312 + u8 mfr; 313 + u8 mrr; 314 + } pll; 315 + }; 316 + 317 + struct samsung_mipi_dphy_timing { 318 + unsigned int max_lane_mbps; 319 + u8 clk_prepare; 320 + u8 clk_zero; 321 + u8 clk_post; 322 + u8 clk_trail_eot; 323 + u8 hs_prepare; 324 + u8 hs_zero; 325 + u8 hs_trail_eot; 326 + u8 lpx; 327 + u8 hs_exit; 328 + u8 hs_settle; 329 + }; 330 + 331 + /* 332 + * Timing values taken from rk3588 vendor kernel. 333 + * Not documented in hw documentation. 334 + */ 335 + static const 336 + struct samsung_mipi_dphy_timing samsung_mipi_dphy_timing_table[] = { 337 + {6500, 32, 117, 31, 28, 30, 56, 27, 24, 44, 37}, 338 + {6490, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37}, 339 + {6480, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37}, 340 + {6470, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37}, 341 + {6460, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37}, 342 + {6450, 32, 115, 31, 28, 30, 56, 27, 24, 44, 37}, 343 + {6440, 32, 115, 31, 28, 30, 56, 27, 24, 44, 37}, 344 + {6430, 31, 116, 31, 28, 30, 55, 27, 24, 44, 37}, 345 + {6420, 31, 116, 31, 28, 30, 55, 27, 24, 44, 37}, 346 + {6410, 31, 116, 31, 27, 30, 55, 27, 24, 44, 37}, 347 + {6400, 31, 115, 30, 27, 30, 55, 27, 23, 43, 36}, 348 + {6390, 31, 115, 30, 27, 30, 55, 27, 23, 43, 36}, 349 + {6380, 31, 115, 30, 27, 30, 55, 27, 23, 43, 36}, 350 + {6370, 31, 115, 30, 27, 30, 55, 26, 23, 43, 36}, 351 + {6360, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36}, 352 + {6350, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36}, 353 + {6340, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36}, 354 + {6330, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36}, 355 + {6320, 31, 113, 30, 27, 30, 54, 26, 23, 43, 36}, 356 + {6310, 31, 113, 30, 27, 30, 54, 26, 23, 43, 36}, 357 + {6300, 31, 113, 30, 27, 30, 54, 26, 23, 43, 36}, 358 + {6290, 31, 113, 30, 27, 29, 54, 26, 23, 43, 36}, 359 + {6280, 31, 112, 30, 27, 29, 54, 26, 23, 43, 36}, 360 + {6270, 31, 112, 30, 27, 29, 54, 26, 23, 43, 36}, 361 + {6260, 31, 112, 30, 27, 29, 54, 26, 23, 43, 36}, 362 + {6250, 31, 112, 30, 27, 29, 54, 26, 23, 42, 36}, 363 + {6240, 30, 113, 30, 27, 29, 54, 26, 23, 42, 36}, 364 + {6230, 30, 112, 30, 27, 29, 54, 26, 23, 42, 35}, 365 + {6220, 30, 112, 30, 27, 29, 53, 26, 23, 42, 35}, 366 + {6210, 30, 112, 30, 27, 29, 53, 26, 23, 42, 35}, 367 + {6200, 30, 112, 29, 27, 29, 53, 26, 23, 42, 35}, 368 + {6190, 30, 111, 29, 27, 29, 53, 26, 23, 42, 35}, 369 + {6180, 30, 111, 29, 27, 29, 53, 26, 23, 42, 35}, 370 + {6170, 30, 111, 29, 26, 29, 53, 26, 23, 42, 35}, 371 + {6160, 30, 111, 29, 26, 29, 53, 26, 23, 42, 35}, 372 + {6150, 30, 110, 29, 26, 29, 53, 26, 23, 42, 35}, 373 + {6140, 30, 110, 29, 26, 29, 52, 26, 23, 42, 35}, 374 + {6130, 30, 110, 29, 26, 29, 52, 25, 22, 42, 35}, 375 + {6120, 30, 110, 29, 26, 29, 52, 25, 22, 42, 35}, 376 + {6110, 30, 110, 29, 26, 29, 52, 25, 22, 42, 35}, 377 + {6100, 30, 109, 29, 26, 29, 52, 25, 22, 41, 35}, 378 + {6090, 30, 109, 29, 26, 29, 52, 25, 22, 41, 35}, 379 + {6080, 30, 109, 29, 26, 28, 53, 25, 22, 41, 35}, 380 + {6070, 30, 109, 29, 26, 28, 52, 25, 22, 41, 34}, 381 + {6060, 30, 108, 29, 26, 28, 52, 25, 22, 41, 34}, 382 + {6050, 30, 108, 29, 26, 28, 52, 25, 22, 41, 34}, 383 + {6040, 29, 109, 29, 26, 28, 52, 25, 22, 41, 34}, 384 + {6030, 29, 109, 29, 26, 28, 52, 25, 22, 41, 34}, 385 + {6020, 29, 108, 29, 26, 28, 52, 25, 22, 41, 34}, 386 + {6010, 29, 108, 29, 26, 28, 52, 25, 22, 41, 34}, 387 + {6000, 29, 108, 28, 26, 28, 51, 25, 22, 41, 34}, 388 + {5990, 29, 108, 28, 26, 28, 51, 25, 22, 41, 34}, 389 + {5980, 29, 107, 28, 26, 28, 51, 25, 22, 41, 34}, 390 + {5970, 29, 107, 28, 26, 28, 51, 25, 22, 41, 34}, 391 + {5960, 29, 107, 28, 26, 28, 51, 25, 22, 40, 34}, 392 + {5950, 29, 107, 28, 26, 28, 51, 25, 22, 40, 34}, 393 + {5940, 29, 107, 28, 25, 28, 51, 25, 22, 40, 34}, 394 + {5930, 29, 106, 28, 25, 28, 50, 25, 22, 40, 34}, 395 + {5920, 29, 106, 28, 25, 28, 50, 25, 22, 40, 34}, 396 + {5910, 29, 106, 28, 25, 28, 50, 25, 22, 40, 34}, 397 + {5900, 29, 106, 28, 25, 28, 50, 24, 22, 40, 33}, 398 + {5890, 29, 105, 28, 25, 28, 50, 24, 22, 40, 33}, 399 + {5880, 29, 105, 28, 25, 28, 50, 24, 22, 40, 33}, 400 + {5870, 29, 105, 28, 25, 27, 51, 24, 22, 40, 33}, 401 + {5860, 29, 105, 28, 25, 27, 51, 24, 21, 40, 33}, 402 + {5850, 29, 104, 28, 25, 27, 50, 24, 21, 40, 33}, 403 + {5840, 28, 105, 28, 25, 27, 50, 24, 21, 40, 33}, 404 + {5830, 28, 105, 28, 25, 27, 50, 24, 21, 40, 33}, 405 + {5820, 28, 105, 28, 25, 27, 50, 24, 21, 40, 33}, 406 + {5810, 28, 104, 28, 25, 27, 50, 24, 21, 39, 33}, 407 + {5800, 28, 104, 27, 25, 27, 50, 24, 21, 39, 33}, 408 + {5790, 28, 104, 27, 25, 27, 50, 24, 21, 39, 33}, 409 + {5780, 28, 104, 27, 25, 27, 49, 24, 21, 39, 33}, 410 + {5770, 28, 104, 27, 25, 27, 49, 24, 21, 39, 33}, 411 + {5760, 28, 103, 27, 25, 27, 49, 24, 21, 39, 33}, 412 + {5750, 28, 103, 27, 25, 27, 49, 24, 21, 39, 33}, 413 + {5740, 28, 103, 27, 25, 27, 49, 24, 21, 39, 33}, 414 + {5730, 28, 103, 27, 25, 27, 49, 24, 21, 39, 32}, 415 + {5720, 28, 102, 27, 25, 27, 49, 24, 21, 39, 32}, 416 + {5710, 28, 102, 27, 25, 27, 48, 24, 21, 39, 32}, 417 + {5700, 28, 102, 27, 24, 27, 48, 24, 21, 39, 32}, 418 + {5690, 28, 102, 27, 24, 27, 48, 24, 21, 39, 32}, 419 + {5680, 28, 101, 27, 24, 27, 48, 24, 21, 39, 32}, 420 + {5670, 28, 101, 27, 24, 27, 48, 23, 21, 38, 32}, 421 + {5660, 28, 101, 27, 24, 26, 49, 23, 21, 38, 32}, 422 + {5650, 28, 101, 27, 24, 26, 49, 23, 21, 38, 32}, 423 + {5640, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32}, 424 + {5630, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32}, 425 + {5620, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32}, 426 + {5610, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32}, 427 + {5600, 27, 101, 26, 24, 26, 48, 23, 20, 38, 32}, 428 + {5590, 27, 100, 26, 24, 26, 48, 23, 20, 38, 32}, 429 + {5580, 27, 100, 26, 24, 26, 48, 23, 20, 38, 32}, 430 + {5570, 27, 100, 26, 24, 26, 48, 23, 20, 38, 31}, 431 + {5560, 27, 100, 26, 24, 26, 47, 23, 20, 38, 31}, 432 + {5550, 27, 99, 26, 24, 26, 47, 23, 20, 38, 31}, 433 + {5540, 27, 99, 26, 24, 26, 47, 23, 20, 38, 31}, 434 + {5530, 27, 99, 26, 24, 26, 47, 23, 20, 38, 31}, 435 + {5520, 27, 99, 26, 24, 26, 47, 23, 20, 37, 31}, 436 + {5510, 27, 98, 26, 24, 26, 47, 23, 20, 37, 31}, 437 + {5500, 27, 98, 26, 24, 26, 47, 23, 20, 37, 31}, 438 + {5490, 27, 98, 26, 24, 26, 46, 23, 20, 37, 31}, 439 + {5480, 27, 98, 26, 24, 26, 46, 23, 20, 37, 31}, 440 + {5470, 27, 97, 26, 23, 26, 46, 23, 20, 37, 31}, 441 + {5460, 27, 97, 26, 23, 26, 46, 23, 20, 37, 31}, 442 + {5450, 27, 97, 26, 23, 25, 47, 23, 20, 37, 31}, 443 + {5440, 26, 98, 26, 23, 25, 47, 23, 20, 37, 31}, 444 + {5430, 26, 98, 26, 23, 25, 47, 22, 20, 37, 31}, 445 + {5420, 26, 97, 26, 23, 25, 46, 22, 20, 37, 31}, 446 + {5410, 26, 97, 26, 23, 25, 46, 22, 20, 37, 31}, 447 + {5400, 26, 97, 25, 23, 25, 46, 22, 20, 37, 30}, 448 + {5390, 26, 97, 25, 23, 25, 46, 22, 20, 37, 30}, 449 + {5380, 26, 96, 25, 23, 25, 46, 22, 20, 36, 30}, 450 + {5370, 26, 96, 25, 23, 25, 46, 22, 20, 36, 30}, 451 + {5360, 26, 96, 25, 23, 25, 46, 22, 20, 36, 30}, 452 + {5350, 26, 96, 25, 23, 25, 46, 22, 20, 36, 30}, 453 + {5340, 26, 95, 25, 23, 25, 45, 22, 20, 36, 30}, 454 + {5330, 26, 95, 25, 23, 25, 45, 22, 19, 36, 30}, 455 + {5320, 26, 95, 25, 23, 25, 45, 22, 19, 36, 30}, 456 + {5310, 26, 95, 25, 23, 25, 45, 22, 19, 36, 30}, 457 + {5300, 26, 95, 25, 23, 25, 45, 22, 19, 36, 30}, 458 + {5290, 26, 94, 25, 23, 25, 45, 22, 19, 36, 30}, 459 + {5280, 26, 94, 25, 23, 25, 45, 22, 19, 36, 30}, 460 + {5270, 26, 94, 25, 23, 25, 44, 22, 19, 36, 30}, 461 + {5260, 26, 94, 25, 23, 25, 44, 22, 19, 36, 30}, 462 + {5250, 25, 94, 25, 23, 24, 45, 22, 19, 36, 30}, 463 + {5240, 25, 94, 25, 23, 24, 45, 22, 19, 36, 29}, 464 + {5230, 25, 94, 25, 22, 24, 45, 22, 19, 35, 29}, 465 + {5220, 25, 94, 25, 22, 24, 45, 22, 19, 35, 29}, 466 + {5210, 25, 93, 25, 22, 24, 45, 22, 19, 35, 29}, 467 + {5200, 25, 93, 24, 22, 24, 44, 21, 19, 35, 29}, 468 + {5190, 25, 93, 24, 22, 24, 44, 21, 19, 35, 29}, 469 + {5180, 25, 93, 24, 22, 24, 44, 21, 19, 35, 29}, 470 + {5170, 25, 92, 24, 22, 24, 44, 21, 19, 35, 29}, 471 + {5160, 25, 92, 24, 22, 24, 44, 21, 19, 35, 29}, 472 + {5150, 25, 92, 24, 22, 24, 44, 21, 19, 35, 29}, 473 + {5140, 25, 92, 24, 22, 24, 44, 21, 19, 35, 29}, 474 + {5130, 25, 92, 24, 22, 24, 43, 21, 19, 35, 29}, 475 + {5120, 25, 91, 24, 22, 24, 43, 21, 19, 35, 29}, 476 + {5110, 25, 91, 24, 22, 24, 43, 21, 19, 35, 29}, 477 + {5100, 25, 91, 24, 22, 24, 43, 21, 19, 35, 29}, 478 + {5090, 25, 91, 24, 22, 24, 43, 21, 19, 34, 29}, 479 + {5080, 25, 90, 24, 22, 24, 43, 21, 19, 34, 29}, 480 + {5070, 25, 90, 24, 22, 24, 43, 21, 19, 34, 28}, 481 + {5060, 25, 90, 24, 22, 24, 43, 21, 18, 34, 28}, 482 + {5050, 24, 91, 24, 22, 24, 42, 21, 18, 34, 28}, 483 + {5040, 24, 90, 24, 22, 23, 43, 21, 18, 34, 28}, 484 + {5030, 24, 90, 24, 22, 23, 43, 21, 18, 34, 28}, 485 + {5020, 24, 90, 24, 22, 23, 43, 21, 18, 34, 28}, 486 + {5010, 24, 90, 24, 22, 23, 43, 21, 18, 34, 28}, 487 + {5000, 24, 89, 23, 21, 23, 43, 21, 18, 34, 28}, 488 + {4990, 24, 89, 23, 21, 23, 43, 21, 18, 34, 28}, 489 + {4980, 24, 89, 23, 21, 23, 42, 21, 18, 34, 28}, 490 + {4970, 24, 89, 23, 21, 23, 42, 21, 18, 34, 28}, 491 + {4960, 24, 89, 23, 21, 23, 42, 20, 18, 34, 28}, 492 + {4950, 24, 88, 23, 21, 23, 42, 20, 18, 34, 28}, 493 + {4940, 24, 88, 23, 21, 23, 42, 20, 18, 33, 28}, 494 + {4930, 24, 88, 23, 21, 23, 42, 20, 18, 33, 28}, 495 + {4920, 24, 88, 23, 21, 23, 42, 20, 18, 33, 28}, 496 + {4910, 24, 87, 23, 21, 23, 41, 20, 18, 33, 28}, 497 + {4900, 24, 87, 23, 21, 23, 41, 20, 18, 33, 27}, 498 + {4890, 24, 87, 23, 21, 23, 41, 20, 18, 33, 27}, 499 + {4880, 24, 87, 23, 21, 23, 41, 20, 18, 33, 27}, 500 + {4870, 24, 86, 23, 21, 23, 41, 20, 18, 33, 27}, 501 + {4860, 24, 86, 23, 21, 23, 41, 20, 18, 33, 27}, 502 + {4850, 23, 87, 23, 21, 23, 41, 20, 18, 33, 27}, 503 + {4840, 23, 87, 23, 21, 23, 40, 20, 18, 33, 27}, 504 + {4830, 23, 86, 23, 21, 22, 41, 20, 18, 33, 27}, 505 + {4820, 23, 86, 23, 21, 22, 41, 20, 18, 33, 27}, 506 + {4810, 23, 86, 23, 21, 22, 41, 20, 18, 33, 27}, 507 + {4800, 23, 86, 22, 21, 22, 41, 20, 17, 32, 27}, 508 + {4790, 23, 86, 22, 21, 22, 41, 20, 17, 32, 27}, 509 + {4780, 23, 85, 22, 21, 22, 41, 20, 17, 32, 27}, 510 + {4770, 23, 85, 22, 21, 22, 41, 20, 17, 32, 27}, 511 + {4760, 23, 85, 22, 20, 22, 40, 20, 17, 32, 27}, 512 + {4750, 23, 85, 22, 20, 22, 40, 20, 17, 32, 27}, 513 + {4740, 23, 84, 22, 20, 22, 40, 20, 17, 32, 26}, 514 + {4730, 23, 84, 22, 20, 22, 40, 19, 17, 32, 26}, 515 + {4720, 23, 84, 22, 20, 22, 40, 19, 17, 32, 26}, 516 + {4710, 23, 84, 22, 20, 22, 40, 19, 17, 32, 26}, 517 + {4700, 23, 83, 22, 20, 22, 40, 19, 17, 32, 26}, 518 + {4690, 23, 83, 22, 20, 22, 39, 19, 17, 32, 26}, 519 + {4680, 23, 83, 22, 20, 22, 39, 19, 17, 32, 26}, 520 + {4670, 23, 83, 22, 20, 22, 39, 19, 17, 32, 26}, 521 + {4660, 23, 82, 22, 20, 22, 39, 19, 17, 32, 26}, 522 + {4650, 22, 83, 22, 20, 22, 39, 19, 17, 31, 26}, 523 + {4640, 22, 83, 22, 20, 22, 39, 19, 17, 31, 26}, 524 + {4630, 22, 83, 22, 20, 22, 39, 19, 17, 31, 26}, 525 + {4620, 22, 83, 22, 20, 21, 39, 19, 17, 31, 26}, 526 + {4610, 22, 82, 22, 20, 21, 39, 19, 17, 31, 26}, 527 + {4600, 22, 82, 21, 20, 21, 39, 19, 17, 31, 26}, 528 + {4590, 22, 82, 21, 20, 21, 39, 19, 17, 31, 26}, 529 + {4580, 22, 82, 21, 20, 21, 39, 19, 17, 31, 26}, 530 + {4570, 22, 81, 21, 20, 21, 39, 19, 17, 31, 25}, 531 + {4560, 22, 81, 21, 20, 21, 39, 19, 17, 31, 25}, 532 + {4550, 22, 81, 21, 20, 21, 38, 19, 17, 31, 25}, 533 + {4540, 22, 81, 21, 20, 21, 38, 19, 17, 31, 25}, 534 + {4530, 22, 80, 21, 19, 21, 38, 19, 16, 31, 25}, 535 + {4520, 22, 80, 21, 19, 21, 38, 19, 16, 31, 25}, 536 + {4510, 22, 80, 21, 19, 21, 38, 19, 16, 31, 25}, 537 + {4500, 22, 80, 21, 19, 21, 38, 19, 16, 30, 25}, 538 + {4490, 22, 80, 21, 19, 21, 38, 18, 16, 30, 25}, 539 + {4480, 22, 79, 21, 19, 21, 38, 18, 16, 30, 25}, 540 + {4470, 22, 79, 21, 19, 21, 37, 18, 16, 30, 25}, 541 + {4460, 22, 79, 21, 19, 21, 37, 18, 16, 30, 25}, 542 + {4450, 21, 80, 21, 19, 21, 37, 18, 16, 30, 25}, 543 + {4440, 21, 79, 21, 19, 21, 37, 18, 16, 30, 25}, 544 + {4430, 21, 79, 21, 19, 21, 37, 18, 16, 30, 25}, 545 + {4420, 21, 79, 21, 19, 21, 37, 18, 16, 30, 25}, 546 + {4410, 21, 79, 21, 19, 20, 38, 18, 16, 30, 25}, 547 + {4400, 21, 78, 20, 19, 20, 37, 18, 16, 30, 24}, 548 + {4390, 21, 78, 20, 19, 20, 37, 18, 16, 30, 24}, 549 + {4380, 21, 78, 20, 19, 20, 37, 18, 16, 30, 24}, 550 + {4370, 21, 78, 20, 19, 20, 37, 18, 16, 30, 24}, 551 + {4360, 21, 77, 20, 19, 20, 37, 18, 16, 29, 24}, 552 + {4350, 21, 77, 20, 19, 20, 37, 18, 16, 29, 24}, 553 + {4340, 21, 77, 20, 19, 20, 37, 18, 16, 29, 24}, 554 + {4330, 21, 77, 20, 19, 20, 36, 18, 16, 29, 24}, 555 + {4320, 21, 77, 20, 19, 20, 36, 18, 16, 29, 24}, 556 + {4310, 21, 76, 20, 19, 20, 36, 18, 16, 29, 24}, 557 + {4300, 21, 76, 20, 18, 20, 36, 18, 16, 29, 24}, 558 + {4290, 21, 76, 20, 18, 20, 36, 18, 16, 29, 24}, 559 + {4280, 21, 76, 20, 18, 20, 36, 18, 16, 29, 24}, 560 + {4270, 21, 75, 20, 18, 20, 36, 18, 16, 29, 24}, 561 + {4260, 21, 75, 20, 18, 20, 35, 17, 15, 29, 24}, 562 + {4250, 20, 76, 20, 18, 20, 35, 17, 15, 29, 24}, 563 + {4240, 20, 76, 20, 18, 20, 35, 17, 15, 29, 23}, 564 + {4230, 20, 75, 20, 18, 20, 35, 17, 15, 29, 23}, 565 + {4220, 20, 75, 20, 18, 20, 35, 17, 15, 29, 23}, 566 + {4210, 20, 75, 20, 18, 20, 35, 17, 15, 28, 23}, 567 + {4200, 20, 75, 19, 18, 19, 36, 17, 15, 28, 23}, 568 + {4190, 20, 74, 19, 18, 19, 36, 17, 15, 28, 23}, 569 + {4180, 20, 74, 19, 18, 19, 35, 17, 15, 28, 23}, 570 + {4170, 20, 74, 19, 18, 19, 35, 17, 15, 28, 23}, 571 + {4160, 20, 74, 19, 18, 19, 35, 17, 15, 28, 23}, 572 + {4150, 20, 74, 19, 18, 19, 35, 17, 15, 28, 23}, 573 + {4140, 20, 73, 19, 18, 19, 35, 17, 15, 28, 23}, 574 + {4130, 20, 73, 19, 18, 19, 35, 17, 15, 28, 23}, 575 + {4120, 20, 73, 19, 18, 19, 35, 17, 15, 28, 23}, 576 + {4110, 20, 73, 19, 18, 19, 34, 17, 15, 28, 23}, 577 + {4100, 20, 72, 19, 18, 19, 34, 17, 15, 28, 23}, 578 + {4090, 20, 72, 19, 18, 19, 34, 17, 15, 28, 23}, 579 + {4080, 20, 72, 19, 18, 19, 34, 17, 15, 28, 23}, 580 + {4070, 20, 72, 19, 18, 19, 34, 17, 15, 27, 22}, 581 + {4060, 19, 72, 19, 17, 19, 34, 17, 15, 27, 22}, 582 + {4050, 19, 72, 19, 17, 19, 34, 17, 15, 27, 22}, 583 + {4040, 19, 72, 19, 17, 19, 33, 17, 15, 27, 22}, 584 + {4030, 19, 72, 19, 17, 19, 33, 17, 15, 27, 22}, 585 + {4020, 19, 71, 19, 17, 19, 33, 16, 15, 27, 22}, 586 + {4010, 19, 71, 19, 17, 19, 33, 16, 15, 27, 22}, 587 + {4000, 19, 71, 18, 17, 19, 33, 16, 14, 27, 22}, 588 + {3990, 19, 71, 18, 17, 18, 34, 16, 14, 27, 22}, 589 + {3980, 19, 71, 18, 17, 18, 34, 16, 14, 27, 22}, 590 + {3970, 19, 70, 18, 17, 18, 33, 16, 14, 27, 22}, 591 + {3960, 19, 70, 18, 17, 18, 33, 16, 14, 27, 22}, 592 + {3950, 19, 70, 18, 17, 18, 33, 16, 14, 27, 22}, 593 + {3940, 19, 70, 18, 17, 18, 33, 16, 14, 27, 22}, 594 + {3930, 19, 69, 18, 17, 18, 33, 16, 14, 27, 22}, 595 + {3920, 19, 69, 18, 17, 18, 33, 16, 14, 26, 22}, 596 + {3910, 19, 69, 18, 17, 18, 33, 16, 14, 26, 22}, 597 + {3900, 19, 69, 18, 17, 18, 33, 16, 14, 26, 21}, 598 + {3890, 19, 68, 18, 17, 18, 32, 16, 14, 26, 21}, 599 + {3880, 19, 68, 18, 17, 18, 32, 16, 14, 26, 21}, 600 + {3870, 19, 68, 18, 17, 18, 32, 16, 14, 26, 21}, 601 + {3860, 18, 69, 18, 17, 18, 32, 16, 14, 26, 21}, 602 + {3850, 18, 68, 18, 17, 18, 32, 16, 14, 26, 21}, 603 + {3840, 18, 68, 18, 17, 18, 32, 16, 14, 26, 21}, 604 + {3830, 18, 68, 18, 16, 18, 32, 16, 14, 26, 21}, 605 + {3820, 18, 68, 18, 16, 18, 31, 16, 14, 26, 21}, 606 + {3810, 18, 68, 18, 16, 18, 31, 16, 14, 26, 21}, 607 + {3800, 18, 67, 17, 16, 18, 31, 16, 14, 26, 21}, 608 + {3790, 18, 67, 17, 16, 17, 32, 15, 14, 26, 21}, 609 + {3780, 18, 67, 17, 16, 17, 32, 15, 14, 25, 21}, 610 + {3770, 18, 67, 17, 16, 17, 32, 15, 14, 25, 21}, 611 + {3760, 18, 66, 17, 16, 17, 32, 15, 14, 25, 21}, 612 + {3750, 18, 66, 17, 16, 17, 31, 15, 14, 25, 21}, 613 + {3740, 18, 66, 17, 16, 17, 31, 15, 14, 25, 20}, 614 + {3730, 18, 66, 17, 16, 17, 31, 15, 13, 25, 20}, 615 + {3720, 18, 65, 17, 16, 17, 31, 15, 13, 25, 20}, 616 + {3710, 18, 65, 17, 16, 17, 31, 15, 13, 25, 20}, 617 + {3700, 18, 65, 17, 16, 17, 31, 15, 13, 25, 20}, 618 + {3690, 18, 65, 17, 16, 17, 31, 15, 13, 25, 20}, 619 + {3680, 18, 64, 17, 16, 17, 31, 15, 13, 25, 20}, 620 + {3670, 18, 64, 17, 16, 17, 30, 15, 13, 25, 20}, 621 + {3660, 17, 65, 17, 16, 17, 30, 15, 13, 25, 20}, 622 + {3650, 17, 65, 17, 16, 17, 30, 15, 13, 25, 20}, 623 + {3640, 17, 65, 17, 16, 17, 30, 15, 13, 25, 20}, 624 + {3630, 17, 64, 17, 16, 17, 30, 15, 13, 24, 20}, 625 + {3620, 17, 64, 17, 16, 17, 30, 15, 13, 24, 20}, 626 + {3610, 17, 64, 17, 16, 17, 30, 15, 13, 24, 20}, 627 + {3600, 17, 64, 16, 16, 17, 29, 15, 13, 24, 20}, 628 + {3590, 17, 63, 16, 15, 17, 29, 15, 13, 24, 20}, 629 + {3580, 17, 63, 16, 15, 16, 30, 15, 13, 24, 20}, 630 + {3570, 17, 63, 16, 15, 16, 30, 15, 13, 24, 19}, 631 + {3560, 17, 63, 16, 15, 16, 30, 14, 13, 24, 19}, 632 + {3550, 17, 62, 16, 15, 16, 30, 14, 13, 24, 19}, 633 + {3540, 17, 62, 16, 15, 16, 30, 14, 13, 24, 19}, 634 + {3530, 17, 62, 16, 15, 16, 29, 14, 13, 24, 19}, 635 + {3520, 17, 62, 16, 15, 16, 29, 14, 13, 24, 19}, 636 + {3510, 17, 62, 16, 15, 16, 29, 14, 13, 24, 19}, 637 + {3500, 17, 61, 16, 15, 16, 29, 14, 13, 24, 19}, 638 + {3490, 17, 61, 16, 15, 16, 29, 14, 13, 23, 19}, 639 + {3480, 17, 61, 16, 15, 16, 29, 14, 13, 23, 19}, 640 + {3470, 17, 61, 16, 15, 16, 29, 14, 13, 23, 19}, 641 + {3460, 16, 61, 16, 15, 16, 28, 14, 12, 23, 19}, 642 + {3450, 16, 61, 16, 15, 16, 28, 14, 12, 23, 19}, 643 + {3440, 16, 61, 16, 15, 16, 28, 14, 12, 23, 19}, 644 + {3430, 16, 61, 16, 15, 16, 28, 14, 12, 23, 19}, 645 + {3420, 16, 60, 16, 15, 16, 28, 14, 12, 23, 19}, 646 + {3410, 16, 60, 16, 15, 16, 28, 14, 12, 23, 18}, 647 + {3400, 16, 60, 15, 15, 16, 28, 14, 12, 23, 18}, 648 + {3390, 16, 60, 15, 15, 16, 28, 14, 12, 23, 18}, 649 + {3380, 16, 59, 15, 15, 16, 27, 14, 12, 23, 18}, 650 + {3370, 16, 59, 15, 15, 15, 28, 14, 12, 23, 18}, 651 + {3360, 16, 59, 15, 14, 15, 28, 14, 12, 23, 18}, 652 + {3350, 16, 59, 15, 14, 15, 28, 14, 12, 23, 18}, 653 + {3340, 16, 59, 15, 14, 15, 28, 14, 12, 22, 18}, 654 + {3330, 16, 58, 15, 14, 15, 28, 14, 12, 22, 18}, 655 + {3320, 16, 58, 15, 14, 15, 28, 13, 12, 22, 18}, 656 + {3310, 16, 58, 15, 14, 15, 27, 13, 12, 22, 18}, 657 + {3300, 16, 58, 15, 14, 15, 27, 13, 12, 22, 18}, 658 + {3290, 16, 57, 15, 14, 15, 27, 13, 12, 22, 18}, 659 + {3280, 16, 57, 15, 14, 15, 27, 13, 12, 22, 18}, 660 + {3270, 16, 57, 15, 14, 15, 27, 13, 12, 22, 18}, 661 + {3260, 15, 58, 15, 14, 15, 27, 13, 12, 22, 18}, 662 + {3250, 15, 57, 15, 14, 15, 27, 13, 12, 22, 18}, 663 + {3240, 15, 57, 15, 14, 15, 26, 13, 12, 22, 17}, 664 + {3230, 15, 57, 15, 14, 15, 26, 13, 12, 22, 17}, 665 + {3220, 15, 57, 15, 14, 15, 26, 13, 12, 22, 17}, 666 + {3210, 15, 56, 15, 14, 15, 26, 13, 12, 22, 17}, 667 + {3200, 15, 56, 14, 14, 15, 26, 13, 11, 21, 17}, 668 + {3190, 15, 56, 14, 14, 15, 26, 13, 11, 21, 17}, 669 + {3180, 15, 56, 14, 14, 15, 26, 13, 11, 21, 17}, 670 + {3170, 15, 56, 14, 14, 15, 25, 13, 11, 21, 17}, 671 + {3160, 15, 55, 14, 14, 14, 26, 13, 11, 21, 17}, 672 + {3150, 15, 55, 14, 14, 14, 26, 13, 11, 21, 17}, 673 + {3140, 15, 55, 14, 14, 14, 26, 13, 11, 21, 17}, 674 + {3130, 15, 55, 14, 14, 14, 26, 13, 11, 21, 17}, 675 + {3120, 15, 54, 14, 13, 14, 26, 13, 11, 21, 17}, 676 + {3110, 15, 54, 14, 13, 14, 26, 13, 11, 21, 17}, 677 + {3100, 15, 54, 14, 13, 14, 26, 13, 11, 21, 17}, 678 + {3090, 15, 54, 14, 13, 14, 25, 12, 11, 21, 17}, 679 + {3080, 15, 53, 14, 13, 14, 25, 12, 11, 21, 17}, 680 + {3070, 14, 54, 14, 13, 14, 25, 12, 11, 21, 16}, 681 + {3060, 14, 54, 14, 13, 14, 25, 12, 11, 21, 16}, 682 + {3050, 14, 54, 14, 13, 14, 25, 12, 11, 20, 16}, 683 + {3040, 14, 53, 14, 13, 14, 25, 12, 11, 20, 16}, 684 + {3030, 14, 53, 14, 13, 14, 25, 12, 11, 20, 16}, 685 + {3020, 14, 53, 14, 13, 14, 24, 12, 11, 20, 16}, 686 + {3010, 14, 53, 14, 13, 14, 24, 12, 11, 20, 16}, 687 + {3000, 14, 53, 13, 13, 14, 24, 12, 11, 20, 16}, 688 + {2990, 14, 52, 13, 13, 14, 24, 12, 11, 20, 16}, 689 + {2980, 14, 52, 13, 13, 14, 24, 12, 11, 20, 16}, 690 + {2970, 14, 52, 13, 13, 14, 24, 12, 11, 20, 16}, 691 + {2960, 14, 52, 13, 13, 14, 24, 12, 11, 20, 16}, 692 + {2950, 14, 51, 13, 13, 13, 24, 12, 11, 20, 16}, 693 + {2940, 14, 51, 13, 13, 13, 24, 12, 11, 20, 16}, 694 + {2930, 14, 51, 13, 13, 13, 24, 12, 10, 20, 16}, 695 + {2920, 14, 51, 13, 13, 13, 24, 12, 10, 20, 16}, 696 + {2910, 14, 50, 13, 13, 13, 24, 12, 10, 20, 15}, 697 + {2900, 14, 50, 13, 13, 13, 24, 12, 10, 19, 15}, 698 + {2890, 14, 50, 13, 12, 13, 24, 12, 10, 19, 15}, 699 + {2880, 14, 50, 13, 12, 13, 23, 12, 10, 19, 15}, 700 + {2870, 13, 50, 13, 12, 13, 23, 12, 10, 19, 15}, 701 + {2860, 13, 50, 13, 12, 13, 23, 12, 10, 19, 15}, 702 + {2850, 13, 50, 13, 12, 13, 23, 11, 10, 19, 15}, 703 + {2840, 13, 50, 13, 12, 13, 23, 11, 10, 19, 15}, 704 + {2830, 13, 50, 13, 12, 13, 23, 11, 10, 19, 15}, 705 + {2820, 13, 49, 13, 12, 13, 23, 11, 10, 19, 15}, 706 + {2810, 13, 49, 13, 12, 13, 23, 11, 10, 19, 15}, 707 + {2800, 13, 49, 12, 12, 13, 22, 11, 10, 19, 15}, 708 + {2790, 13, 49, 12, 12, 13, 22, 11, 10, 19, 15}, 709 + {2780, 13, 48, 12, 12, 13, 22, 11, 10, 19, 15}, 710 + {2770, 13, 48, 12, 12, 13, 22, 11, 10, 19, 15}, 711 + {2760, 13, 48, 12, 12, 13, 22, 11, 10, 18, 15}, 712 + {2750, 13, 48, 12, 12, 13, 22, 11, 10, 18, 15}, 713 + {2740, 13, 47, 12, 12, 12, 23, 11, 10, 18, 14}, 714 + {2730, 13, 47, 12, 12, 12, 22, 11, 10, 18, 14}, 715 + {2720, 13, 47, 12, 12, 12, 22, 11, 10, 18, 14}, 716 + {2710, 13, 47, 12, 12, 12, 22, 11, 10, 18, 14}, 717 + {2700, 13, 47, 12, 12, 12, 22, 11, 10, 18, 14}, 718 + {2690, 13, 46, 12, 12, 12, 22, 11, 10, 18, 14}, 719 + {2680, 13, 46, 12, 12, 12, 22, 11, 10, 18, 14}, 720 + {2670, 12, 47, 12, 12, 12, 22, 11, 10, 18, 14}, 721 + {2660, 12, 47, 12, 12, 12, 21, 11, 9, 18, 14}, 722 + {2650, 12, 46, 12, 11, 12, 21, 11, 9, 18, 14}, 723 + {2640, 12, 46, 12, 11, 12, 21, 11, 9, 18, 14}, 724 + {2630, 12, 46, 12, 11, 12, 21, 11, 9, 18, 14}, 725 + {2620, 12, 46, 12, 11, 12, 21, 10, 9, 18, 14}, 726 + {2610, 12, 45, 12, 11, 12, 21, 10, 9, 17, 14}, 727 + {2600, 12, 45, 11, 11, 12, 21, 10, 9, 17, 14}, 728 + {2590, 12, 45, 11, 11, 12, 20, 10, 9, 17, 14}, 729 + {2580, 12, 45, 11, 11, 12, 20, 10, 9, 17, 14}, 730 + {2570, 12, 44, 11, 11, 12, 20, 10, 9, 17, 13}, 731 + {2560, 12, 44, 11, 11, 12, 20, 10, 9, 17, 13}, 732 + {2550, 12, 44, 11, 11, 12, 20, 10, 9, 17, 13}, 733 + {2540, 12, 44, 11, 11, 11, 21, 10, 9, 17, 13}, 734 + {2530, 12, 44, 11, 11, 11, 21, 10, 9, 17, 13}, 735 + {2520, 12, 43, 11, 11, 11, 21, 10, 9, 17, 13}, 736 + {2510, 12, 43, 11, 11, 11, 20, 10, 9, 17, 13}, 737 + {2500, 12, 43, 11, 11, 11, 20, 10, 9, 17, 13}, 738 + {2490, 12, 43, 11, 11, 11, 20, 10, 9, 17, 13}, 739 + {2480, 12, 42, 11, 11, 11, 20, 10, 9, 17, 13}, 740 + {2470, 11, 43, 11, 11, 11, 20, 10, 9, 16, 13}, 741 + {2460, 11, 43, 11, 11, 11, 20, 10, 9, 16, 13}, 742 + {2450, 11, 43, 11, 11, 11, 20, 10, 9, 16, 13}, 743 + {2440, 11, 42, 11, 11, 11, 19, 10, 9, 16, 13}, 744 + {2430, 11, 42, 11, 11, 11, 19, 10, 9, 16, 13}, 745 + {2420, 11, 42, 11, 10, 11, 19, 10, 9, 16, 13}, 746 + {2410, 11, 42, 11, 10, 11, 19, 10, 9, 16, 12}, 747 + {2400, 11, 41, 10, 10, 11, 19, 10, 8, 16, 12}, 748 + {2390, 11, 41, 10, 10, 11, 19, 10, 8, 16, 12}, 749 + {2380, 11, 41, 10, 10, 11, 19, 9, 8, 16, 12}, 750 + {2370, 11, 41, 10, 10, 11, 18, 9, 8, 16, 12}, 751 + {2360, 11, 41, 10, 10, 11, 18, 9, 8, 16, 12}, 752 + {2350, 11, 40, 10, 10, 11, 18, 9, 8, 16, 12}, 753 + {2340, 11, 40, 10, 10, 11, 18, 9, 8, 16, 12}, 754 + {2330, 11, 40, 10, 10, 10, 19, 9, 8, 16, 12}, 755 + {2320, 11, 40, 10, 10, 10, 19, 9, 8, 15, 12}, 756 + {2310, 11, 39, 10, 10, 10, 19, 9, 8, 15, 12}, 757 + {2300, 11, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 758 + {2290, 11, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 759 + {2280, 11, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 760 + {2270, 10, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 761 + {2260, 10, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 762 + {2250, 10, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 763 + {2240, 10, 39, 10, 10, 10, 18, 9, 8, 15, 11}, 764 + {2230, 10, 38, 10, 10, 10, 18, 9, 8, 15, 11}, 765 + {2220, 10, 38, 10, 10, 10, 17, 9, 8, 15, 11}, 766 + {2210, 10, 38, 10, 10, 10, 17, 9, 8, 15, 11}, 767 + {2200, 10, 38, 9, 10, 10, 17, 9, 8, 15, 11}, 768 + {2190, 10, 38, 9, 9, 10, 17, 9, 8, 15, 11}, 769 + {2180, 10, 37, 9, 9, 10, 17, 9, 8, 14, 11}, 770 + {2170, 10, 37, 9, 9, 10, 17, 9, 8, 14, 11}, 771 + {2160, 10, 37, 9, 9, 10, 17, 9, 8, 14, 11}, 772 + {2150, 10, 37, 9, 9, 10, 16, 8, 8, 14, 11}, 773 + {2140, 10, 36, 9, 9, 10, 16, 8, 8, 14, 11}, 774 + {2130, 10, 36, 9, 9, 10, 16, 8, 7, 14, 11}, 775 + {2120, 10, 36, 9, 9, 9, 17, 8, 7, 14, 11}, 776 + {2110, 10, 36, 9, 9, 9, 17, 8, 7, 14, 11}, 777 + {2100, 10, 35, 9, 9, 9, 17, 8, 7, 14, 11}, 778 + {2090, 10, 35, 9, 9, 9, 17, 8, 7, 14, 11}, 779 + {2080, 9, 36, 9, 9, 9, 16, 8, 7, 14, 11}, 780 + {2070, 9, 36, 9, 9, 9, 16, 8, 7, 14, 10}, 781 + {2060, 9, 35, 9, 9, 9, 16, 8, 7, 14, 10}, 782 + {2050, 9, 35, 9, 9, 9, 16, 8, 7, 14, 10}, 783 + {2040, 9, 35, 9, 9, 9, 16, 8, 7, 14, 10}, 784 + {2030, 9, 35, 9, 9, 9, 16, 8, 7, 13, 10}, 785 + {2020, 9, 35, 9, 9, 9, 16, 8, 7, 13, 10}, 786 + {2010, 9, 34, 9, 9, 9, 15, 8, 7, 13, 10}, 787 + {2000, 9, 34, 8, 9, 9, 15, 8, 7, 13, 10}, 788 + {1990, 9, 34, 8, 9, 9, 15, 8, 7, 13, 10}, 789 + {1980, 9, 34, 8, 9, 9, 15, 8, 7, 13, 10}, 790 + {1970, 9, 33, 8, 9, 9, 15, 8, 7, 13, 10}, 791 + {1960, 9, 33, 8, 9, 9, 15, 8, 7, 13, 10}, 792 + {1950, 9, 33, 8, 8, 9, 15, 8, 7, 13, 10}, 793 + {1940, 9, 33, 8, 8, 9, 15, 8, 7, 13, 10}, 794 + {1930, 9, 32, 8, 8, 9, 14, 8, 7, 13, 10}, 795 + {1920, 9, 32, 8, 8, 9, 14, 8, 7, 13, 10}, 796 + {1910, 9, 32, 8, 8, 8, 15, 7, 7, 13, 9}, 797 + {1900, 9, 32, 8, 8, 8, 15, 7, 7, 13, 9}, 798 + {1890, 9, 31, 8, 8, 8, 15, 7, 7, 12, 9}, 799 + {1880, 8, 32, 8, 8, 8, 15, 7, 7, 12, 9}, 800 + {1870, 8, 32, 8, 8, 8, 15, 7, 7, 12, 9}, 801 + {1860, 8, 32, 8, 8, 8, 14, 7, 6, 12, 9}, 802 + {1850, 8, 32, 8, 8, 8, 14, 7, 6, 12, 9}, 803 + {1840, 8, 31, 8, 8, 8, 14, 7, 6, 12, 9}, 804 + {1830, 8, 31, 8, 8, 8, 14, 7, 6, 12, 9}, 805 + {1820, 8, 31, 8, 8, 8, 14, 7, 6, 12, 9}, 806 + {1810, 8, 31, 8, 8, 8, 14, 7, 6, 12, 9}, 807 + {1800, 8, 30, 7, 8, 8, 14, 7, 6, 12, 9}, 808 + {1790, 8, 30, 7, 8, 8, 13, 7, 6, 12, 9}, 809 + {1780, 8, 30, 7, 8, 8, 13, 7, 6, 12, 9}, 810 + {1770, 8, 30, 7, 8, 8, 13, 7, 6, 12, 9}, 811 + {1760, 8, 29, 7, 8, 8, 13, 7, 6, 12, 9}, 812 + {1750, 8, 29, 7, 8, 8, 13, 7, 6, 12, 9}, 813 + {1740, 8, 29, 7, 8, 8, 13, 7, 6, 11, 8}, 814 + {1730, 8, 29, 7, 8, 8, 13, 7, 6, 11, 8}, 815 + {1720, 8, 29, 7, 7, 8, 13, 7, 6, 11, 8}, 816 + {1710, 8, 28, 7, 7, 8, 12, 7, 6, 11, 8}, 817 + {1700, 8, 28, 7, 7, 7, 13, 7, 6, 11, 8}, 818 + {1690, 8, 28, 7, 7, 7, 13, 7, 6, 11, 8}, 819 + {1680, 7, 29, 7, 7, 7, 13, 6, 6, 11, 8}, 820 + {1670, 7, 28, 7, 7, 7, 13, 6, 6, 11, 8}, 821 + {1660, 7, 28, 7, 7, 7, 13, 6, 6, 11, 8}, 822 + {1650, 7, 28, 7, 7, 7, 13, 6, 6, 11, 8}, 823 + {1640, 7, 28, 7, 7, 7, 12, 6, 6, 11, 8}, 824 + {1630, 7, 27, 7, 7, 7, 12, 6, 6, 11, 8}, 825 + {1620, 7, 27, 7, 7, 7, 12, 6, 6, 11, 8}, 826 + {1610, 7, 27, 7, 7, 7, 12, 6, 6, 11, 8}, 827 + {1600, 7, 27, 6, 7, 7, 12, 6, 5, 10, 8}, 828 + {1590, 7, 26, 6, 7, 7, 12, 6, 5, 10, 8}, 829 + {1580, 7, 26, 6, 7, 7, 12, 6, 5, 10, 7}, 830 + {1570, 7, 26, 6, 7, 7, 11, 6, 5, 10, 7}, 831 + {1560, 7, 26, 6, 7, 7, 11, 6, 5, 10, 7}, 832 + {1550, 7, 26, 6, 7, 7, 11, 6, 5, 10, 7}, 833 + {1540, 7, 25, 6, 7, 7, 11, 6, 5, 10, 7}, 834 + {1530, 7, 25, 6, 7, 7, 11, 6, 5, 10, 7}, 835 + {1520, 7, 25, 6, 7, 7, 11, 6, 5, 10, 7}, 836 + {1510, 7, 25, 6, 7, 7, 11, 6, 5, 10, 7}, 837 + {1500, 7, 24, 6, 7, 7, 10, 6, 5, 10, 7}, 838 + {1490, 59, 25, 6, 77, 59, 10, 70, 44, 9, 73}, 839 + {1480, 59, 24, 6, 76, 58, 10, 70, 44, 9, 73}, 840 + {1470, 58, 24, 6, 76, 58, 10, 69, 44, 9, 72}, 841 + {1460, 58, 24, 6, 76, 58, 10, 69, 43, 9, 72}, 842 + {1450, 58, 24, 6, 75, 57, 10, 68, 43, 9, 71}, 843 + {1440, 57, 24, 6, 75, 57, 10, 68, 43, 9, 71}, 844 + {1430, 57, 23, 6, 75, 57, 10, 68, 43, 8, 70}, 845 + {1420, 56, 23, 6, 74, 57, 9, 67, 43, 8, 70}, 846 + {1410, 56, 23, 6, 74, 57, 9, 67, 43, 8, 69}, 847 + {1400, 56, 23, 5, 74, 55, 9, 67, 41, 8, 69}, 848 + {1390, 55, 23, 5, 73, 55, 9, 66, 41, 8, 68}, 849 + {1380, 55, 23, 5, 73, 54, 9, 66, 41, 8, 68}, 850 + {1370, 54, 22, 5, 72, 54, 9, 66, 41, 8, 67}, 851 + {1360, 54, 22, 5, 72, 54, 9, 65, 40, 8, 67}, 852 + {1350, 54, 22, 5, 72, 53, 9, 65, 40, 8, 66}, 853 + {1340, 53, 22, 5, 71, 53, 9, 65, 40, 8, 66}, 854 + {1330, 53, 22, 5, 71, 53, 9, 64, 39, 8, 65}, 855 + {1320, 52, 22, 5, 71, 53, 8, 64, 40, 8, 65}, 856 + {1310, 52, 21, 5, 70, 53, 8, 64, 40, 8, 64}, 857 + {1300, 51, 21, 5, 70, 51, 8, 63, 38, 8, 64}, 858 + {1290, 51, 21, 5, 70, 51, 8, 63, 38, 7, 64}, 859 + {1280, 51, 21, 5, 69, 51, 8, 63, 38, 7, 63}, 860 + {1270, 50, 21, 5, 69, 50, 8, 62, 38, 7, 63}, 861 + {1260, 50, 20, 5, 69, 50, 8, 62, 37, 7, 62}, 862 + {1250, 49, 20, 5, 68, 49, 8, 62, 37, 7, 62}, 863 + {1240, 49, 20, 5, 68, 49, 8, 61, 37, 7, 61}, 864 + {1230, 49, 20, 5, 68, 49, 8, 61, 36, 7, 61}, 865 + {1220, 48, 20, 5, 67, 48, 8, 61, 36, 7, 60}, 866 + {1210, 48, 19, 5, 67, 48, 7, 60, 36, 7, 60}, 867 + {1200, 49, 19, 4, 67, 49, 7, 60, 36, 7, 59}, 868 + {1190, 48, 19, 4, 66, 48, 7, 60, 36, 7, 59}, 869 + {1180, 48, 19, 4, 66, 48, 7, 59, 36, 7, 58}, 870 + {1170, 46, 19, 4, 66, 46, 7, 59, 35, 7, 58}, 871 + {1160, 46, 18, 4, 65, 46, 7, 59, 34, 7, 57}, 872 + {1150, 45, 18, 4, 65, 46, 7, 58, 34, 7, 57}, 873 + {1140, 45, 18, 4, 65, 45, 7, 58, 34, 6, 56}, 874 + {1130, 45, 18, 4, 64, 45, 7, 58, 33, 6, 56}, 875 + {1120, 44, 18, 4, 64, 44, 7, 57, 33, 6, 55}, 876 + {1110, 44, 18, 4, 64, 44, 7, 57, 33, 6, 55}, 877 + {1100, 43, 17, 4, 63, 44, 6, 57, 32, 6, 54}, 878 + {1090, 43, 17, 4, 63, 44, 6, 56, 33, 6, 54}, 879 + {1080, 43, 17, 4, 63, 44, 6, 56, 33, 6, 53}, 880 + {1070, 42, 17, 4, 62, 44, 6, 56, 33, 6, 53}, 881 + {1060, 42, 17, 4, 62, 42, 6, 55, 31, 6, 52}, 882 + {1050, 41, 17, 4, 62, 42, 6, 55, 31, 6, 52}, 883 + {1040, 41, 16, 4, 61, 41, 6, 54, 31, 6, 52}, 884 + {1030, 41, 16, 4, 61, 41, 6, 54, 30, 6, 51}, 885 + {1020, 40, 16, 4, 61, 41, 6, 54, 30, 6, 51}, 886 + {1010, 40, 16, 4, 60, 40, 6, 53, 30, 6, 50}, 887 + {1000, 39, 16, 3, 60, 40, 6, 53, 29, 5, 50}, 888 + { 990, 39, 15, 3, 60, 39, 6, 53, 29, 5, 49}, 889 + { 980, 39, 15, 3, 59, 39, 5, 52, 29, 5, 49}, 890 + { 970, 38, 15, 3, 59, 39, 5, 52, 29, 5, 48}, 891 + { 960, 38, 15, 3, 59, 39, 5, 52, 29, 5, 48}, 892 + { 950, 37, 15, 3, 58, 39, 5, 51, 29, 5, 47}, 893 + { 940, 37, 14, 3, 58, 39, 5, 51, 29, 5, 47}, 894 + { 930, 37, 14, 3, 57, 37, 5, 51, 27, 5, 46}, 895 + { 920, 36, 14, 3, 57, 37, 5, 50, 27, 5, 46}, 896 + { 910, 36, 14, 3, 57, 36, 5, 50, 27, 5, 45}, 897 + { 900, 35, 14, 3, 56, 36, 5, 50, 26, 5, 45}, 898 + { 890, 35, 14, 3, 56, 36, 5, 49, 26, 5, 44}, 899 + { 880, 35, 13, 3, 56, 35, 5, 49, 26, 5, 44}, 900 + { 870, 34, 13, 3, 55, 35, 4, 49, 26, 5, 43}, 901 + { 860, 34, 13, 3, 55, 35, 4, 48, 25, 5, 43}, 902 + { 850, 33, 13, 3, 55, 35, 4, 48, 26, 4, 42}, 903 + { 840, 33, 13, 3, 54, 35, 4, 48, 26, 4, 42}, 904 + { 830, 33, 12, 3, 54, 33, 4, 47, 24, 4, 41}, 905 + { 820, 32, 12, 3, 54, 33, 4, 47, 24, 4, 41}, 906 + { 810, 32, 12, 3, 53, 33, 4, 47, 24, 4, 40}, 907 + { 800, 31, 12, 2, 53, 32, 4, 46, 23, 4, 40}, 908 + { 790, 31, 12, 2, 53, 32, 4, 46, 23, 4, 39}, 909 + { 780, 30, 12, 2, 52, 31, 4, 46, 23, 4, 39}, 910 + { 770, 30, 11, 2, 52, 31, 4, 45, 23, 4, 39}, 911 + { 760, 30, 11, 2, 52, 31, 3, 45, 22, 4, 38}, 912 + { 750, 29, 11, 2, 51, 30, 3, 45, 22, 4, 38}, 913 + { 740, 29, 11, 2, 51, 30, 3, 44, 22, 4, 37}, 914 + { 730, 28, 11, 2, 51, 31, 3, 44, 22, 4, 37}, 915 + { 720, 28, 10, 2, 50, 30, 3, 44, 22, 4, 36}, 916 + { 710, 28, 10, 2, 50, 30, 3, 43, 22, 4, 36}, 917 + { 700, 27, 10, 2, 50, 28, 3, 43, 20, 3, 35}, 918 + { 690, 27, 10, 2, 49, 28, 3, 43, 20, 3, 35}, 919 + { 680, 26, 10, 2, 49, 28, 3, 42, 20, 3, 34}, 920 + { 670, 26, 10, 2, 49, 27, 3, 42, 20, 3, 34}, 921 + { 660, 26, 9, 2, 48, 27, 3, 42, 19, 3, 33}, 922 + { 650, 25, 9, 2, 48, 26, 3, 41, 19, 3, 33}, 923 + { 640, 25, 9, 2, 48, 26, 2, 41, 19, 3, 32}, 924 + { 630, 24, 9, 2, 47, 26, 2, 40, 18, 3, 32}, 925 + { 620, 24, 9, 2, 47, 26, 2, 40, 19, 3, 31}, 926 + { 610, 24, 8, 2, 47, 26, 2, 40, 19, 3, 31}, 927 + { 600, 23, 8, 1, 46, 26, 2, 39, 18, 3, 30}, 928 + { 590, 23, 8, 1, 46, 24, 2, 39, 17, 3, 30}, 929 + { 580, 22, 8, 1, 46, 24, 2, 39, 17, 3, 29}, 930 + { 570, 22, 8, 1, 45, 23, 2, 38, 17, 3, 29}, 931 + { 560, 22, 7, 1, 45, 23, 2, 38, 16, 2, 28}, 932 + { 550, 21, 7, 1, 45, 23, 2, 38, 16, 2, 28}, 933 + { 540, 21, 7, 1, 44, 22, 2, 37, 16, 2, 27}, 934 + { 530, 20, 7, 1, 44, 22, 1, 37, 15, 2, 27}, 935 + { 520, 20, 7, 1, 43, 21, 1, 37, 15, 2, 27}, 936 + { 510, 20, 6, 1, 43, 21, 1, 36, 15, 2, 26}, 937 + { 500, 19, 6, 1, 43, 22, 1, 36, 15, 2, 26}, 938 + { 490, 19, 6, 1, 42, 21, 1, 36, 15, 2, 25}, 939 + { 480, 18, 6, 1, 42, 21, 1, 35, 15, 2, 25}, 940 + { 470, 18, 6, 1, 42, 21, 1, 35, 15, 2, 24}, 941 + { 460, 18, 6, 1, 41, 19, 1, 35, 13, 2, 24}, 942 + { 450, 17, 5, 1, 41, 19, 1, 34, 13, 2, 23}, 943 + { 440, 17, 5, 1, 41, 18, 1, 34, 13, 2, 23}, 944 + { 430, 16, 5, 1, 40, 18, 0, 34, 12, 2, 22}, 945 + { 420, 16, 5, 1, 40, 18, 0, 33, 12, 2, 22}, 946 + { 410, 16, 5, 1, 40, 17, 0, 33, 12, 1, 21}, 947 + { 400, 15, 5, 0, 39, 17, 0, 33, 11, 1, 21}, 948 + { 390, 15, 4, 0, 39, 17, 0, 32, 12, 1, 20}, 949 + { 380, 14, 4, 0, 39, 17, 0, 32, 12, 1, 20}, 950 + { 370, 14, 4, 0, 38, 17, 0, 32, 12, 1, 19}, 951 + { 360, 14, 4, 0, 38, 15, 0, 31, 10, 1, 19}, 952 + { 350, 13, 4, 0, 38, 15, 0, 31, 10, 1, 18}, 953 + { 340, 13, 3, 0, 37, 15, 0, 31, 10, 1, 18}, 954 + { 330, 12, 3, 0, 37, 14, 0, 30, 9, 1, 17}, 955 + { 320, 12, 3, 0, 37, 14, 0, 30, 9, 1, 17}, 956 + { 310, 12, 3, 0, 36, 13, 0, 30, 9, 1, 16}, 957 + { 300, 11, 3, 0, 36, 13, 0, 29, 8, 1, 16}, 958 + { 290, 11, 2, 0, 36, 13, 0, 29, 8, 1, 15}, 959 + { 280, 10, 2, 0, 35, 12, 0, 29, 8, 1, 15}, 960 + { 270, 10, 2, 0, 35, 12, 0, 28, 8, 0, 14}, 961 + { 260, 9, 2, 0, 35, 12, 0, 28, 8, 0, 14}, 962 + { 250, 9, 2, 0, 34, 12, 0, 28, 8, 0, 14}, 963 + { 240, 9, 2, 0, 34, 12, 0, 27, 8, 0, 13}, 964 + { 230, 8, 1, 0, 34, 10, 0, 27, 6, 0, 13}, 965 + { 220, 8, 1, 0, 33, 10, 0, 27, 6, 0, 12}, 966 + { 210, 7, 1, 0, 33, 10, 0, 26, 6, 0, 12}, 967 + { 200, 7, 1, 0, 33, 9, 0, 26, 5, 0, 11}, 968 + { 190, 7, 1, 0, 32, 9, 0, 25, 5, 0, 11}, 969 + { 180, 6, 1, 0, 32, 8, 0, 25, 5, 0, 10}, 970 + { 170, 6, 0, 0, 32, 8, 0, 25, 5, 0, 10}, 971 + { 160, 5, 0, 0, 31, 8, 0, 24, 4, 0, 9}, 972 + { 150, 5, 0, 0, 31, 8, 0, 24, 5, 0, 9}, 973 + { 140, 5, 0, 0, 31, 8, 0, 24, 5, 0, 8}, 974 + { 130, 4, 0, 0, 30, 6, 0, 23, 3, 0, 8}, 975 + { 120, 4, 0, 0, 30, 6, 0, 23, 3, 0, 7}, 976 + { 110, 3, 0, 0, 30, 6, 0, 23, 3, 0, 7}, 977 + { 100, 3, 0, 0, 29, 5, 0, 22, 2, 0, 6}, 978 + { 90, 3, 0, 0, 29, 5, 0, 22, 2, 0, 6}, 979 + { 80, 2, 0, 0, 28, 5, 0, 22, 2, 0, 5}, 980 + }; 981 + 982 + static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *samsung) 983 + { 984 + regmap_write(samsung->regmap, BIAS_CON0, I_DEV_DIV_6 | I_RES_100_2UA); 985 + regmap_write(samsung->regmap, BIAS_CON1, I_VBG_SEL_820MV | I_BGR_VREF_820MV | 986 + I_LADDER_1_00V); 987 + regmap_write(samsung->regmap, BIAS_CON2, REG_325M_325MV | REG_LP_400M_400MV | 988 + REG_400M_400MV | REG_645M_645MV); 989 + 990 + /* default output voltage select: 991 + * dphy: 400mv 992 + * cphy: 530mv 993 + */ 994 + regmap_update_bits(samsung->regmap, BIAS_CON4, 995 + I_MUX_SEL_MASK, I_MUX_400MV); 996 + } 997 + 998 + static void samsung_mipi_dphy_lane_enable(struct samsung_mipi_dcphy *samsung) 999 + { 1000 + regmap_write(samsung->regmap, DPHY_MC_GNR_CON1, T_PHY_READY(0x2000)); 1001 + regmap_update_bits(samsung->regmap, DPHY_MC_GNR_CON0, 1002 + PHY_ENABLE, PHY_ENABLE); 1003 + 1004 + switch (samsung->lanes) { 1005 + case 4: 1006 + regmap_write(samsung->regmap, DPHY_MD3_GNR_CON1, 1007 + T_PHY_READY(0x2000)); 1008 + regmap_update_bits(samsung->regmap, DPHY_MD3_GNR_CON0, 1009 + PHY_ENABLE, PHY_ENABLE); 1010 + fallthrough; 1011 + case 3: 1012 + regmap_write(samsung->regmap, COMBO_MD2_GNR_CON1, 1013 + T_PHY_READY(0x2000)); 1014 + regmap_update_bits(samsung->regmap, COMBO_MD2_GNR_CON0, 1015 + PHY_ENABLE, PHY_ENABLE); 1016 + fallthrough; 1017 + case 2: 1018 + regmap_write(samsung->regmap, COMBO_MD1_GNR_CON1, 1019 + T_PHY_READY(0x2000)); 1020 + regmap_update_bits(samsung->regmap, COMBO_MD1_GNR_CON0, 1021 + PHY_ENABLE, PHY_ENABLE); 1022 + fallthrough; 1023 + case 1: 1024 + default: 1025 + regmap_write(samsung->regmap, COMBO_MD0_GNR_CON1, 1026 + T_PHY_READY(0x2000)); 1027 + regmap_update_bits(samsung->regmap, COMBO_MD0_GNR_CON0, 1028 + PHY_ENABLE, PHY_ENABLE); 1029 + break; 1030 + } 1031 + } 1032 + 1033 + static void samsung_mipi_dphy_lane_disable(struct samsung_mipi_dcphy *samsung) 1034 + { 1035 + switch (samsung->lanes) { 1036 + case 4: 1037 + regmap_update_bits(samsung->regmap, DPHY_MD3_GNR_CON0, 1038 + PHY_ENABLE, 0); 1039 + fallthrough; 1040 + case 3: 1041 + regmap_update_bits(samsung->regmap, COMBO_MD2_GNR_CON0, 1042 + PHY_ENABLE, 0); 1043 + fallthrough; 1044 + case 2: 1045 + regmap_update_bits(samsung->regmap, COMBO_MD1_GNR_CON0, 1046 + PHY_ENABLE, 0); 1047 + fallthrough; 1048 + case 1: 1049 + default: 1050 + regmap_update_bits(samsung->regmap, COMBO_MD0_GNR_CON0, 1051 + PHY_ENABLE, 0); 1052 + break; 1053 + } 1054 + 1055 + regmap_update_bits(samsung->regmap, DPHY_MC_GNR_CON0, PHY_ENABLE, 0); 1056 + } 1057 + 1058 + static void samsung_mipi_dcphy_pll_configure(struct samsung_mipi_dcphy *samsung) 1059 + { 1060 + regmap_update_bits(samsung->regmap, PLL_CON0, S_MASK | P_MASK, 1061 + S(samsung->pll.scaler) | P(samsung->pll.prediv)); 1062 + 1063 + if (samsung->pll.dsm < 0) { 1064 + u16 dsm_tmp; 1065 + 1066 + /* Using opposite number subtraction to find complement */ 1067 + dsm_tmp = abs(samsung->pll.dsm); 1068 + dsm_tmp = dsm_tmp - 1; 1069 + dsm_tmp ^= 0xffff; 1070 + regmap_write(samsung->regmap, PLL_CON1, dsm_tmp); 1071 + } else { 1072 + regmap_write(samsung->regmap, PLL_CON1, samsung->pll.dsm); 1073 + } 1074 + 1075 + regmap_update_bits(samsung->regmap, PLL_CON2, 1076 + M_MASK, M(samsung->pll.fbdiv)); 1077 + 1078 + if (samsung->pll.ssc_en) { 1079 + regmap_write(samsung->regmap, PLL_CON3, 1080 + MRR(samsung->pll.mrr) | MFR(samsung->pll.mfr)); 1081 + regmap_update_bits(samsung->regmap, PLL_CON4, SSCG_EN, SSCG_EN); 1082 + } 1083 + 1084 + regmap_write(samsung->regmap, PLL_CON5, RESET_N_SEL | PLL_ENABLE_SEL); 1085 + regmap_write(samsung->regmap, PLL_CON7, PLL_LOCK_CNT(0xf000)); 1086 + regmap_write(samsung->regmap, PLL_CON8, PLL_STB_CNT(0xf000)); 1087 + } 1088 + 1089 + static int samsung_mipi_dcphy_pll_enable(struct samsung_mipi_dcphy *samsung) 1090 + { 1091 + u32 sts; 1092 + int ret; 1093 + 1094 + regmap_update_bits(samsung->regmap, PLL_CON0, PLL_EN, PLL_EN); 1095 + 1096 + ret = regmap_read_poll_timeout(samsung->regmap, PLL_STAT0, 1097 + sts, (sts & PLL_LOCK), 1000, 20000); 1098 + if (ret < 0) 1099 + dev_err(samsung->dev, "DC-PHY pll failed to lock\n"); 1100 + 1101 + return ret; 1102 + } 1103 + 1104 + static void samsung_mipi_dcphy_pll_disable(struct samsung_mipi_dcphy *samsung) 1105 + { 1106 + regmap_update_bits(samsung->regmap, PLL_CON0, PLL_EN, 0); 1107 + } 1108 + 1109 + static const struct samsung_mipi_dphy_timing * 1110 + samsung_mipi_dphy_get_timing(struct samsung_mipi_dcphy *samsung) 1111 + { 1112 + const struct samsung_mipi_dphy_timing *timings; 1113 + unsigned int num_timings; 1114 + unsigned int lane_mbps = div64_ul(samsung->pll.rate, USEC_PER_SEC); 1115 + unsigned int i; 1116 + 1117 + timings = samsung_mipi_dphy_timing_table; 1118 + num_timings = ARRAY_SIZE(samsung_mipi_dphy_timing_table); 1119 + 1120 + for (i = num_timings; i > 1; i--) 1121 + if (lane_mbps <= timings[i - 1].max_lane_mbps) 1122 + break; 1123 + 1124 + return &timings[i - 1]; 1125 + } 1126 + 1127 + static unsigned long 1128 + samsung_mipi_dcphy_pll_round_rate(struct samsung_mipi_dcphy *samsung, 1129 + unsigned long prate, unsigned long rate, 1130 + u8 *prediv, u16 *fbdiv, int *dsm, u8 *scaler) 1131 + { 1132 + u32 max_fout = samsung->pdata->dphy_tx_max_lane_kbps; 1133 + u64 best_freq = 0; 1134 + u64 fin, fvco, fout; 1135 + u8 min_prediv, max_prediv; 1136 + u8 _prediv, best_prediv = 1; 1137 + u16 _fbdiv, best_fbdiv = 1; 1138 + u8 _scaler, best_scaler = 0; 1139 + u32 min_delta = UINT_MAX; 1140 + long _dsm, best_dsm = 0; 1141 + 1142 + if (!prate) { 1143 + dev_err(samsung->dev, "parent rate of PLL can not be zero\n"); 1144 + return 0; 1145 + } 1146 + 1147 + /* 1148 + * The PLL output frequency can be calculated using a simple formula: 1149 + * Fvco = ((m+k/65536) x 2 x Fin) / p 1150 + * Fout = ((m+k/65536) x 2 x Fin) / (p x 2^s) 1151 + */ 1152 + fin = div64_ul(prate, MSEC_PER_SEC); 1153 + 1154 + while (!best_freq) { 1155 + fout = div64_ul(rate, MSEC_PER_SEC); 1156 + if (fout > max_fout) 1157 + fout = max_fout; 1158 + 1159 + /* 0 ≤ S[2:0] ≤ 6 */ 1160 + for (_scaler = 0; _scaler < 7; _scaler++) { 1161 + fvco = fout << _scaler; 1162 + 1163 + /* 1164 + * 2600MHz ≤ FVCO ≤ 6600MHz 1165 + */ 1166 + if (fvco < 2600 * MSEC_PER_SEC || fvco > 6600 * MSEC_PER_SEC) 1167 + continue; 1168 + 1169 + /* 6MHz ≤ Fref(Fin / p) ≤ 30MHz */ 1170 + min_prediv = DIV_ROUND_UP_ULL(fin, 30 * MSEC_PER_SEC); 1171 + max_prediv = DIV_ROUND_CLOSEST_ULL(fin, 6 * MSEC_PER_SEC); 1172 + 1173 + for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) { 1174 + u64 delta, tmp; 1175 + 1176 + _fbdiv = DIV_ROUND_CLOSEST_ULL(fvco * _prediv, 2 * fin); 1177 + 1178 + /* 64 ≤ M[9:0] ≤ 1023 */ 1179 + if (_fbdiv < 64 || _fbdiv > 1023) 1180 + continue; 1181 + 1182 + /* -32767 ≤ K[15:0] ≤ 32767 */ 1183 + _dsm = ((_prediv * fvco) - (2 * _fbdiv * fin)); 1184 + _dsm = DIV_ROUND_UP_ULL(_dsm << 15, fin); 1185 + if (abs(_dsm) > 32767) 1186 + continue; 1187 + 1188 + tmp = DIV_ROUND_CLOSEST_ULL((_fbdiv * fin * 2 * 1000), _prediv); 1189 + tmp += DIV_ROUND_CLOSEST_ULL((_dsm * fin * 1000), _prediv << 15); 1190 + 1191 + delta = abs(fvco * MSEC_PER_SEC - tmp); 1192 + if (delta < min_delta) { 1193 + best_prediv = _prediv; 1194 + best_fbdiv = _fbdiv; 1195 + best_dsm = _dsm; 1196 + best_scaler = _scaler; 1197 + min_delta = delta; 1198 + best_freq = DIV_ROUND_CLOSEST_ULL(tmp, 1000) * MSEC_PER_SEC; 1199 + } 1200 + } 1201 + } 1202 + 1203 + rate += 100 * MSEC_PER_SEC; 1204 + } 1205 + 1206 + *prediv = best_prediv; 1207 + *fbdiv = best_fbdiv; 1208 + *dsm = (int)best_dsm & 0xffff; 1209 + *scaler = best_scaler; 1210 + dev_dbg(samsung->dev, "p: %d, m: %d, dsm:%ld, scaler: %d\n", 1211 + best_prediv, best_fbdiv, best_dsm, best_scaler); 1212 + 1213 + return best_freq >> best_scaler; 1214 + } 1215 + 1216 + static void 1217 + samsung_mipi_dphy_clk_lane_timing_init(struct samsung_mipi_dcphy *samsung) 1218 + { 1219 + const struct samsung_mipi_dphy_timing *timing; 1220 + unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC); 1221 + u32 val, res_up, res_down; 1222 + 1223 + timing = samsung_mipi_dphy_get_timing(samsung); 1224 + regmap_write(samsung->regmap, DPHY_MC_GNR_CON0, 0xf000); 1225 + 1226 + /* 1227 + * The Drive-Strength / Voltage-Amplitude is adjusted by setting 1228 + * the Driver-Up Resistor and Driver-Down Resistor. 1229 + */ 1230 + res_up = samsung->pdata->dphy_hs_drv_res_cfg->clk_hs_drv_up_ohm; 1231 + res_down = samsung->pdata->dphy_hs_drv_res_cfg->clk_hs_drv_down_ohm; 1232 + val = EDGE_CON(7) | EDGE_CON_DIR(0) | EDGE_CON_EN | 1233 + RES_UP(res_up) | RES_DN(res_down); 1234 + regmap_write(samsung->regmap, DPHY_MC_ANA_CON0, val); 1235 + 1236 + if (lane_hs_rate >= 4500) 1237 + regmap_write(samsung->regmap, DPHY_MC_ANA_CON1, 0x0001); 1238 + 1239 + val = 0; 1240 + /* 1241 + * Divide-by-2 Clock from Serial Clock. Use this when data rate is under 1242 + * 1500Mbps, otherwise divide-by-16 Clock from Serial Clock 1243 + */ 1244 + if (lane_hs_rate < 1500) 1245 + val = HSTX_CLK_SEL; 1246 + 1247 + val |= T_LPX(timing->lpx); 1248 + /* T_LP_EXIT_SKEW/T_LP_ENTRY_SKEW unconfig */ 1249 + regmap_write(samsung->regmap, DPHY_MC_TIME_CON0, val); 1250 + 1251 + val = T_CLK_ZERO(timing->clk_zero) | T_CLK_PREPARE(timing->clk_prepare); 1252 + regmap_write(samsung->regmap, DPHY_MC_TIME_CON1, val); 1253 + 1254 + val = T_HS_EXIT(timing->hs_exit) | T_CLK_TRAIL(timing->clk_trail_eot); 1255 + regmap_write(samsung->regmap, DPHY_MC_TIME_CON2, val); 1256 + 1257 + val = T_CLK_POST(timing->clk_post); 1258 + regmap_write(samsung->regmap, DPHY_MC_TIME_CON3, val); 1259 + 1260 + /* Escape Clock is 20.00MHz */ 1261 + regmap_write(samsung->regmap, DPHY_MC_TIME_CON4, 0x1f4); 1262 + 1263 + /* 1264 + * skew calibration should be off, if the operation data rate is 1265 + * under 1.5Gbps or equal to 1.5Gbps. 1266 + */ 1267 + if (lane_hs_rate > 1500) 1268 + regmap_write(samsung->regmap, DPHY_MC_DESKEW_CON0, 0x9cb1); 1269 + } 1270 + 1271 + static void 1272 + samsung_mipi_dphy_data_lane_timing_init(struct samsung_mipi_dcphy *samsung) 1273 + { 1274 + const struct samsung_mipi_dphy_timing *timing; 1275 + unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC); 1276 + u32 val, res_up, res_down; 1277 + 1278 + timing = samsung_mipi_dphy_get_timing(samsung); 1279 + 1280 + /* 1281 + * The Drive-Strength / Voltage-Amplitude is adjusted by adjusting the 1282 + * Driver-Up Resistor and Driver-Down Resistor. 1283 + */ 1284 + res_up = samsung->pdata->dphy_hs_drv_res_cfg->data_hs_drv_up_ohm; 1285 + res_down = samsung->pdata->dphy_hs_drv_res_cfg->data_hs_drv_down_ohm; 1286 + val = EDGE_CON(7) | EDGE_CON_DIR(0) | EDGE_CON_EN | 1287 + RES_UP(res_up) | RES_DN(res_down); 1288 + regmap_write(samsung->regmap, COMBO_MD0_ANA_CON0, val); 1289 + regmap_write(samsung->regmap, COMBO_MD1_ANA_CON0, val); 1290 + regmap_write(samsung->regmap, COMBO_MD2_ANA_CON0, val); 1291 + regmap_write(samsung->regmap, DPHY_MD3_ANA_CON0, val); 1292 + 1293 + if (lane_hs_rate >= 4500) { 1294 + regmap_write(samsung->regmap, COMBO_MD0_ANA_CON1, 0x0001); 1295 + regmap_write(samsung->regmap, COMBO_MD1_ANA_CON1, 0x0001); 1296 + regmap_write(samsung->regmap, COMBO_MD2_ANA_CON1, 0x0001); 1297 + regmap_write(samsung->regmap, DPHY_MD3_ANA_CON1, 0x0001); 1298 + } 1299 + 1300 + val = 0; 1301 + /* 1302 + * Divide-by-2 Clock from Serial Clock. Use this when data rate is under 1303 + * 1500Mbps, otherwise divide-by-16 Clock from Serial Clock 1304 + */ 1305 + if (lane_hs_rate < 1500) 1306 + val = HSTX_CLK_SEL; 1307 + 1308 + val |= T_LPX(timing->lpx); 1309 + /* T_LP_EXIT_SKEW/T_LP_ENTRY_SKEW unconfig */ 1310 + regmap_write(samsung->regmap, COMBO_MD0_TIME_CON0, val); 1311 + regmap_write(samsung->regmap, COMBO_MD1_TIME_CON0, val); 1312 + regmap_write(samsung->regmap, COMBO_MD2_TIME_CON0, val); 1313 + regmap_write(samsung->regmap, DPHY_MD3_TIME_CON0, val); 1314 + 1315 + val = T_HS_ZERO(timing->hs_zero) | T_HS_PREPARE(timing->hs_prepare); 1316 + regmap_write(samsung->regmap, COMBO_MD0_TIME_CON1, val); 1317 + regmap_write(samsung->regmap, COMBO_MD1_TIME_CON1, val); 1318 + regmap_write(samsung->regmap, COMBO_MD2_TIME_CON1, val); 1319 + regmap_write(samsung->regmap, DPHY_MD3_TIME_CON1, val); 1320 + 1321 + val = T_HS_EXIT(timing->hs_exit) | T_HS_TRAIL(timing->hs_trail_eot); 1322 + regmap_write(samsung->regmap, COMBO_MD0_TIME_CON2, val); 1323 + regmap_write(samsung->regmap, COMBO_MD1_TIME_CON2, val); 1324 + regmap_write(samsung->regmap, COMBO_MD2_TIME_CON2, val); 1325 + regmap_write(samsung->regmap, DPHY_MD3_TIME_CON2, val); 1326 + 1327 + /* TTA-GET/TTA-GO Timing Counter register use default value */ 1328 + val = T_TA_GET(0x3) | T_TA_GO(0x0); 1329 + regmap_write(samsung->regmap, COMBO_MD0_TIME_CON3, val); 1330 + regmap_write(samsung->regmap, COMBO_MD1_TIME_CON3, val); 1331 + regmap_write(samsung->regmap, COMBO_MD2_TIME_CON3, val); 1332 + regmap_write(samsung->regmap, DPHY_MD3_TIME_CON3, val); 1333 + 1334 + /* Escape Clock is 20.00MHz */ 1335 + regmap_write(samsung->regmap, COMBO_MD0_TIME_CON4, 0x1f4); 1336 + regmap_write(samsung->regmap, COMBO_MD1_TIME_CON4, 0x1f4); 1337 + regmap_write(samsung->regmap, COMBO_MD2_TIME_CON4, 0x1f4); 1338 + regmap_write(samsung->regmap, DPHY_MD3_TIME_CON4, 0x1f4); 1339 + } 1340 + 1341 + static int samsung_mipi_dphy_power_on(struct samsung_mipi_dcphy *samsung) 1342 + { 1343 + int ret; 1344 + 1345 + reset_control_assert(samsung->m_phy_rst); 1346 + 1347 + samsung_mipi_dcphy_bias_block_enable(samsung); 1348 + samsung_mipi_dcphy_pll_configure(samsung); 1349 + samsung_mipi_dphy_clk_lane_timing_init(samsung); 1350 + samsung_mipi_dphy_data_lane_timing_init(samsung); 1351 + ret = samsung_mipi_dcphy_pll_enable(samsung); 1352 + if (ret < 0) 1353 + return ret; 1354 + 1355 + samsung_mipi_dphy_lane_enable(samsung); 1356 + 1357 + reset_control_deassert(samsung->m_phy_rst); 1358 + 1359 + /* The TSKEWCAL maximum is 100 µsec 1360 + * at initial calibration. 1361 + */ 1362 + usleep_range(100, 110); 1363 + 1364 + return 0; 1365 + } 1366 + 1367 + static int samsung_mipi_dcphy_power_on(struct phy *phy) 1368 + { 1369 + struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); 1370 + 1371 + reset_control_assert(samsung->apb_rst); 1372 + udelay(1); 1373 + reset_control_deassert(samsung->apb_rst); 1374 + 1375 + switch (samsung->type) { 1376 + case PHY_TYPE_DPHY: 1377 + return samsung_mipi_dphy_power_on(samsung); 1378 + default: 1379 + /* CPHY part to be implemented later */ 1380 + return -EOPNOTSUPP; 1381 + } 1382 + 1383 + return 0; 1384 + } 1385 + 1386 + static int samsung_mipi_dcphy_power_off(struct phy *phy) 1387 + { 1388 + struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); 1389 + 1390 + switch (samsung->type) { 1391 + case PHY_TYPE_DPHY: 1392 + samsung_mipi_dphy_lane_disable(samsung); 1393 + break; 1394 + default: 1395 + /* CPHY part to be implemented later */ 1396 + return -EOPNOTSUPP; 1397 + } 1398 + 1399 + samsung_mipi_dcphy_pll_disable(samsung); 1400 + 1401 + return 0; 1402 + } 1403 + 1404 + static int 1405 + samsung_mipi_dcphy_pll_ssc_modulation_calc(struct samsung_mipi_dcphy *samsung, 1406 + u8 *mfr, u8 *mrr) 1407 + { 1408 + unsigned long fin = div64_ul(clk_get_rate(samsung->ref_clk), MSEC_PER_SEC); 1409 + u16 prediv = samsung->pll.prediv; 1410 + u16 fbdiv = samsung->pll.fbdiv; 1411 + u16 min_mfr, max_mfr; 1412 + u16 _mfr, best_mfr = 0; 1413 + u16 mr, _mrr, best_mrr = 0; 1414 + 1415 + /* 20KHz ≤ MF ≤ 150KHz */ 1416 + max_mfr = DIV_ROUND_UP(fin, (20 * prediv) << 5); 1417 + min_mfr = div64_ul(fin, ((150 * prediv) << 5)); 1418 + /*0 ≤ mfr ≤ 255 */ 1419 + if (max_mfr > 256) 1420 + max_mfr = 256; 1421 + 1422 + for (_mfr = min_mfr; _mfr < max_mfr; _mfr++) { 1423 + /* 1 ≤ mrr ≤ 31 */ 1424 + for (_mrr = 1; _mrr < 32; _mrr++) { 1425 + mr = DIV_ROUND_UP(_mfr * _mrr * 100, fbdiv << 6); 1426 + /* 0 ≤ MR ≤ 5% */ 1427 + if (mr > 5) 1428 + continue; 1429 + 1430 + if (_mfr * _mrr < 513) { 1431 + best_mfr = _mfr; 1432 + best_mrr = _mrr; 1433 + break; 1434 + } 1435 + } 1436 + } 1437 + 1438 + if (best_mrr) { 1439 + *mfr = best_mfr & 0xff; 1440 + *mrr = best_mrr & 0x3f; 1441 + } else { 1442 + dev_err(samsung->dev, "failed to calc ssc parameter mfr and mrr\n"); 1443 + return -EINVAL; 1444 + } 1445 + 1446 + return 0; 1447 + } 1448 + 1449 + static void 1450 + samsung_mipi_dcphy_pll_calc_rate(struct samsung_mipi_dcphy *samsung, 1451 + unsigned long long rate) 1452 + { 1453 + unsigned long prate = clk_get_rate(samsung->ref_clk); 1454 + unsigned long fout; 1455 + u8 scaler = 0, mfr = 0, mrr = 0; 1456 + u16 fbdiv = 0; 1457 + u8 prediv = 1; 1458 + int dsm = 0; 1459 + int ret; 1460 + 1461 + fout = samsung_mipi_dcphy_pll_round_rate(samsung, prate, rate, 1462 + &prediv, &fbdiv, &dsm, 1463 + &scaler); 1464 + 1465 + dev_dbg(samsung->dev, "%s: fin=%lu, req_rate=%llu\n", 1466 + __func__, prate, rate); 1467 + dev_dbg(samsung->dev, "%s: fout=%lu, prediv=%u, fbdiv=%u\n", 1468 + __func__, fout, prediv, fbdiv); 1469 + 1470 + samsung->pll.prediv = prediv; 1471 + samsung->pll.fbdiv = fbdiv; 1472 + samsung->pll.dsm = dsm; 1473 + samsung->pll.scaler = scaler; 1474 + samsung->pll.rate = fout; 1475 + 1476 + /* 1477 + * All DPHY 2.0 compliant Transmitters shall support SSC operating above 1478 + * 2.5 Gbps 1479 + */ 1480 + if (fout > 2500000000LL) { 1481 + ret = samsung_mipi_dcphy_pll_ssc_modulation_calc(samsung, 1482 + &mfr, &mrr); 1483 + if (!ret) { 1484 + samsung->pll.ssc_en = true; 1485 + samsung->pll.mfr = mfr; 1486 + samsung->pll.mrr = mrr; 1487 + } 1488 + } 1489 + } 1490 + 1491 + static int samsung_mipi_dcphy_configure(struct phy *phy, 1492 + union phy_configure_opts *opts) 1493 + { 1494 + struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); 1495 + unsigned long long target_rate = opts->mipi_dphy.hs_clk_rate; 1496 + 1497 + samsung->lanes = opts->mipi_dphy.lanes > 4 ? 4 : opts->mipi_dphy.lanes; 1498 + 1499 + samsung_mipi_dcphy_pll_calc_rate(samsung, target_rate); 1500 + opts->mipi_dphy.hs_clk_rate = samsung->pll.rate; 1501 + 1502 + return 0; 1503 + } 1504 + 1505 + static int samsung_mipi_dcphy_init(struct phy *phy) 1506 + { 1507 + struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); 1508 + 1509 + return pm_runtime_resume_and_get(samsung->dev); 1510 + } 1511 + 1512 + static int samsung_mipi_dcphy_exit(struct phy *phy) 1513 + { 1514 + struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); 1515 + 1516 + return pm_runtime_put(samsung->dev); 1517 + } 1518 + 1519 + static const struct phy_ops samsung_mipi_dcphy_ops = { 1520 + .configure = samsung_mipi_dcphy_configure, 1521 + .power_on = samsung_mipi_dcphy_power_on, 1522 + .power_off = samsung_mipi_dcphy_power_off, 1523 + .init = samsung_mipi_dcphy_init, 1524 + .exit = samsung_mipi_dcphy_exit, 1525 + .owner = THIS_MODULE, 1526 + }; 1527 + 1528 + static const struct regmap_config samsung_mipi_dcphy_regmap_config = { 1529 + .name = "dcphy", 1530 + .reg_bits = 32, 1531 + .val_bits = 32, 1532 + .reg_stride = 4, 1533 + .max_register = 0x10000, 1534 + }; 1535 + 1536 + static struct phy *samsung_mipi_dcphy_xlate(struct device *dev, 1537 + const struct of_phandle_args *args) 1538 + { 1539 + struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev); 1540 + 1541 + if (args->args_count != 1) { 1542 + dev_err(dev, "invalid number of arguments\n"); 1543 + return ERR_PTR(-EINVAL); 1544 + } 1545 + 1546 + if (samsung->type != PHY_NONE && samsung->type != args->args[0]) 1547 + dev_warn(dev, "phy type select %d overwriting type %d\n", 1548 + args->args[0], samsung->type); 1549 + 1550 + samsung->type = args->args[0]; 1551 + 1552 + return samsung->phy; 1553 + } 1554 + 1555 + static int samsung_mipi_dcphy_probe(struct platform_device *pdev) 1556 + { 1557 + struct device *dev = &pdev->dev; 1558 + struct device_node *np = dev->of_node; 1559 + struct samsung_mipi_dcphy *samsung; 1560 + struct phy_provider *phy_provider; 1561 + struct resource *res; 1562 + void __iomem *regs; 1563 + int ret; 1564 + 1565 + samsung = devm_kzalloc(dev, sizeof(*samsung), GFP_KERNEL); 1566 + if (!samsung) 1567 + return -ENOMEM; 1568 + 1569 + samsung->dev = dev; 1570 + samsung->pdata = device_get_match_data(dev); 1571 + platform_set_drvdata(pdev, samsung); 1572 + 1573 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1574 + regs = devm_ioremap_resource(dev, res); 1575 + if (IS_ERR(regs)) 1576 + return PTR_ERR(regs); 1577 + 1578 + samsung->regmap = devm_regmap_init_mmio(dev, regs, 1579 + &samsung_mipi_dcphy_regmap_config); 1580 + if (IS_ERR(samsung->regmap)) 1581 + return dev_err_probe(dev, PTR_ERR(samsung->regmap), "Failed to init regmap\n"); 1582 + 1583 + samsung->grf_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 1584 + if (IS_ERR(samsung->grf_regmap)) 1585 + return dev_err_probe(dev, PTR_ERR(samsung->grf_regmap), 1586 + "Unable to get rockchip,grf\n"); 1587 + 1588 + samsung->ref_clk = devm_clk_get(dev, "ref"); 1589 + if (IS_ERR(samsung->ref_clk)) 1590 + return dev_err_probe(dev, PTR_ERR(samsung->ref_clk), 1591 + "Failed to get reference clock\n"); 1592 + 1593 + samsung->pclk = devm_clk_get(dev, "pclk"); 1594 + if (IS_ERR(samsung->pclk)) 1595 + return dev_err_probe(dev, PTR_ERR(samsung->pclk), "Failed to get pclk\n"); 1596 + 1597 + samsung->m_phy_rst = devm_reset_control_get(dev, "m_phy"); 1598 + if (IS_ERR(samsung->m_phy_rst)) 1599 + return dev_err_probe(dev, PTR_ERR(samsung->m_phy_rst), 1600 + "Failed to get system m_phy_rst control\n"); 1601 + 1602 + samsung->s_phy_rst = devm_reset_control_get(dev, "s_phy"); 1603 + if (IS_ERR(samsung->s_phy_rst)) 1604 + return dev_err_probe(dev, PTR_ERR(samsung->s_phy_rst), 1605 + "Failed to get system s_phy_rst control\n"); 1606 + 1607 + samsung->apb_rst = devm_reset_control_get(dev, "apb"); 1608 + if (IS_ERR(samsung->apb_rst)) 1609 + return dev_err_probe(dev, PTR_ERR(samsung->apb_rst), 1610 + "Failed to get system apb_rst control\n"); 1611 + 1612 + samsung->grf_apb_rst = devm_reset_control_get(dev, "grf"); 1613 + if (IS_ERR(samsung->grf_apb_rst)) 1614 + return dev_err_probe(dev, PTR_ERR(samsung->grf_apb_rst), 1615 + "Failed to get system grf_apb_rst control\n"); 1616 + 1617 + samsung->phy = devm_phy_create(dev, NULL, &samsung_mipi_dcphy_ops); 1618 + if (IS_ERR(samsung->phy)) 1619 + return dev_err_probe(dev, PTR_ERR(samsung->phy), "Failed to create MIPI DC-PHY\n"); 1620 + 1621 + phy_set_drvdata(samsung->phy, samsung); 1622 + 1623 + ret = devm_pm_runtime_enable(dev); 1624 + if (ret) 1625 + return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); 1626 + 1627 + phy_provider = devm_of_phy_provider_register(dev, samsung_mipi_dcphy_xlate); 1628 + if (IS_ERR(phy_provider)) 1629 + return dev_err_probe(dev, PTR_ERR(phy_provider), 1630 + "Failed to register phy provider\n"); 1631 + 1632 + return 0; 1633 + } 1634 + 1635 + static __maybe_unused int samsung_mipi_dcphy_runtime_suspend(struct device *dev) 1636 + { 1637 + struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev); 1638 + 1639 + clk_disable_unprepare(samsung->ref_clk); 1640 + clk_disable_unprepare(samsung->pclk); 1641 + 1642 + return 0; 1643 + } 1644 + 1645 + static __maybe_unused int samsung_mipi_dcphy_runtime_resume(struct device *dev) 1646 + { 1647 + struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev); 1648 + int ret; 1649 + 1650 + ret = clk_prepare_enable(samsung->pclk); 1651 + if (ret) { 1652 + dev_err(samsung->dev, "Failed to enable pclk, %d\n", ret); 1653 + return ret; 1654 + } 1655 + 1656 + clk_prepare_enable(samsung->ref_clk); 1657 + if (ret) { 1658 + dev_err(samsung->dev, "Failed to enable reference clock, %d\n", ret); 1659 + clk_disable_unprepare(samsung->pclk); 1660 + return ret; 1661 + } 1662 + 1663 + return 0; 1664 + } 1665 + 1666 + static const struct dev_pm_ops samsung_mipi_dcphy_pm_ops = { 1667 + SET_RUNTIME_PM_OPS(samsung_mipi_dcphy_runtime_suspend, 1668 + samsung_mipi_dcphy_runtime_resume, NULL) 1669 + }; 1670 + 1671 + static const struct hs_drv_res_cfg rk3576_dphy_hs_drv_res_cfg = { 1672 + .clk_hs_drv_up_ohm = STRENGTH_52_OHM, 1673 + .clk_hs_drv_down_ohm = STRENGTH_52_OHM, 1674 + .data_hs_drv_up_ohm = STRENGTH_39_OHM, 1675 + .data_hs_drv_down_ohm = STRENGTH_39_OHM, 1676 + }; 1677 + 1678 + static const struct hs_drv_res_cfg rk3588_dphy_hs_drv_res_cfg = { 1679 + .clk_hs_drv_up_ohm = STRENGTH_34_OHM, 1680 + .clk_hs_drv_down_ohm = STRENGTH_34_OHM, 1681 + .data_hs_drv_up_ohm = STRENGTH_43_OHM, 1682 + .data_hs_drv_down_ohm = STRENGTH_43_OHM, 1683 + }; 1684 + 1685 + static const struct samsung_mipi_dcphy_plat_data rk3576_samsung_mipi_dcphy_plat_data = { 1686 + .dphy_hs_drv_res_cfg = &rk3576_dphy_hs_drv_res_cfg, 1687 + .dphy_tx_max_lane_kbps = 2500000L, 1688 + }; 1689 + 1690 + static const struct samsung_mipi_dcphy_plat_data rk3588_samsung_mipi_dcphy_plat_data = { 1691 + .dphy_hs_drv_res_cfg = &rk3588_dphy_hs_drv_res_cfg, 1692 + .dphy_tx_max_lane_kbps = 4500000L, 1693 + }; 1694 + 1695 + static const struct of_device_id samsung_mipi_dcphy_of_match[] = { 1696 + { 1697 + .compatible = "rockchip,rk3576-mipi-dcphy", 1698 + .data = &rk3576_samsung_mipi_dcphy_plat_data, 1699 + }, { 1700 + .compatible = "rockchip,rk3588-mipi-dcphy", 1701 + .data = &rk3588_samsung_mipi_dcphy_plat_data, 1702 + }, 1703 + { /* sentinel */ } 1704 + }; 1705 + MODULE_DEVICE_TABLE(of, samsung_mipi_dcphy_of_match); 1706 + 1707 + static struct platform_driver samsung_mipi_dcphy_driver = { 1708 + .driver = { 1709 + .name = "samsung-mipi-dcphy", 1710 + .of_match_table = samsung_mipi_dcphy_of_match, 1711 + .pm = &samsung_mipi_dcphy_pm_ops, 1712 + }, 1713 + .probe = samsung_mipi_dcphy_probe, 1714 + }; 1715 + module_platform_driver(samsung_mipi_dcphy_driver); 1716 + 1717 + MODULE_AUTHOR("Guochun Huang <hero.huang@rock-chips.com>"); 1718 + MODULE_DESCRIPTION("Samsung MIPI DCPHY Driver"); 1719 + MODULE_LICENSE("GPL");
+977 -69
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
··· 25 25 #define HDPTX_I_PLL_EN BIT(7) 26 26 #define HDPTX_I_BIAS_EN BIT(6) 27 27 #define HDPTX_I_BGR_EN BIT(5) 28 + #define HDPTX_MODE_SEL BIT(0) 28 29 #define GRF_HDPTX_STATUS 0x80 29 30 #define HDPTX_O_PLL_LOCK_DONE BIT(3) 30 31 #define HDPTX_O_PHY_CLK_RDY BIT(2) ··· 45 44 #define LANE_REG(n) HDTPX_REG(n, 0300, 062d) 46 45 47 46 /* CMN_REG(0008) */ 47 + #define OVRD_LCPLL_EN_MASK BIT(7) 48 48 #define LCPLL_EN_MASK BIT(6) 49 49 #define LCPLL_LCVCO_MODE_EN_MASK BIT(4) 50 50 /* CMN_REG(001e) */ 51 51 #define LCPLL_PI_EN_MASK BIT(5) 52 52 #define LCPLL_100M_CLK_EN_MASK BIT(0) 53 53 /* CMN_REG(0025) */ 54 - #define LCPLL_PMS_IQDIV_RSTN BIT(4) 54 + #define LCPLL_PMS_IQDIV_RSTN_MASK BIT(4) 55 55 /* CMN_REG(0028) */ 56 - #define LCPLL_SDC_FRAC_EN BIT(2) 57 - #define LCPLL_SDC_FRAC_RSTN BIT(0) 56 + #define LCPLL_SDC_FRAC_EN_MASK BIT(2) 57 + #define LCPLL_SDC_FRAC_RSTN_MASK BIT(0) 58 58 /* CMN_REG(002d) */ 59 59 #define LCPLL_SDC_N_MASK GENMASK(3, 1) 60 60 /* CMN_REG(002e) */ 61 61 #define LCPLL_SDC_NUMBERATOR_MASK GENMASK(5, 0) 62 62 /* CMN_REG(002f) */ 63 63 #define LCPLL_SDC_DENOMINATOR_MASK GENMASK(7, 2) 64 - #define LCPLL_SDC_NDIV_RSTN BIT(0) 64 + #define LCPLL_SDC_NDIV_RSTN_MASK BIT(0) 65 + /* CMN_REG(003c) */ 66 + #define ANA_LCPLL_RESERVED7_MASK BIT(7) 65 67 /* CMN_REG(003d) */ 66 - #define ROPLL_LCVCO_EN BIT(4) 68 + #define OVRD_ROPLL_EN_MASK BIT(7) 69 + #define ROPLL_EN_MASK BIT(6) 70 + #define ROPLL_LCVCO_EN_MASK BIT(4) 71 + /* CMN_REG(0046) */ 72 + #define ROPLL_ANA_CPP_CTRL_COARSE_MASK GENMASK(7, 4) 73 + #define ROPLL_ANA_CPP_CTRL_FINE_MASK GENMASK(3, 0) 74 + /* CMN_REG(0047) */ 75 + #define ROPLL_ANA_LPF_C_SEL_COARSE_MASK GENMASK(5, 3) 76 + #define ROPLL_ANA_LPF_C_SEL_FINE_MASK GENMASK(2, 0) 67 77 /* CMN_REG(004e) */ 68 - #define ROPLL_PI_EN BIT(5) 78 + #define ROPLL_PI_EN_MASK BIT(5) 79 + /* CMN_REG(0051) */ 80 + #define ROPLL_PMS_MDIV_MASK GENMASK(7, 0) 81 + /* CMN_REG(0055) */ 82 + #define ROPLL_PMS_MDIV_AFC_MASK GENMASK(7, 0) 83 + /* CMN_REG(0059) */ 84 + #define ANA_ROPLL_PMS_PDIV_MASK GENMASK(7, 4) 85 + #define ANA_ROPLL_PMS_REFDIV_MASK GENMASK(3, 0) 86 + /* CMN_REG(005a) */ 87 + #define ROPLL_PMS_SDIV_RBR_MASK GENMASK(7, 4) 88 + #define ROPLL_PMS_SDIV_HBR_MASK GENMASK(3, 0) 89 + /* CMN_REG(005b) */ 90 + #define ROPLL_PMS_SDIV_HBR2_MASK GENMASK(7, 4) 69 91 /* CMN_REG(005c) */ 70 - #define ROPLL_PMS_IQDIV_RSTN BIT(5) 92 + #define ROPLL_PMS_IQDIV_RSTN_MASK BIT(5) 71 93 /* CMN_REG(005e) */ 72 94 #define ROPLL_SDM_EN_MASK BIT(6) 73 - #define ROPLL_SDM_FRAC_EN_RBR BIT(3) 74 - #define ROPLL_SDM_FRAC_EN_HBR BIT(2) 75 - #define ROPLL_SDM_FRAC_EN_HBR2 BIT(1) 76 - #define ROPLL_SDM_FRAC_EN_HBR3 BIT(0) 95 + #define OVRD_ROPLL_SDM_RSTN_MASK BIT(5) 96 + #define ROPLL_SDM_RSTN_MASK BIT(4) 97 + #define ROPLL_SDC_FRAC_EN_RBR_MASK BIT(3) 98 + #define ROPLL_SDC_FRAC_EN_HBR_MASK BIT(2) 99 + #define ROPLL_SDC_FRAC_EN_HBR2_MASK BIT(1) 100 + #define ROPLL_SDM_FRAC_EN_HBR3_MASK BIT(0) 101 + /* CMN_REG(005f) */ 102 + #define OVRD_ROPLL_SDC_RSTN_MASK BIT(5) 103 + #define ROPLL_SDC_RSTN_MASK BIT(4) 104 + /* CMN_REG(0060) */ 105 + #define ROPLL_SDM_DENOMINATOR_MASK GENMASK(7, 0) 77 106 /* CMN_REG(0064) */ 78 107 #define ROPLL_SDM_NUM_SIGN_RBR_MASK BIT(3) 108 + #define ROPLL_SDM_NUM_SIGN_HBR_MASK BIT(2) 109 + #define ROPLL_SDM_NUM_SIGN_HBR2_MASK BIT(1) 110 + /* CMN_REG(0065) */ 111 + #define ROPLL_SDM_NUM_MASK GENMASK(7, 0) 79 112 /* CMN_REG(0069) */ 80 113 #define ROPLL_SDC_N_RBR_MASK GENMASK(2, 0) 114 + /* CMN_REG(006a) */ 115 + #define ROPLL_SDC_N_HBR_MASK GENMASK(5, 3) 116 + #define ROPLL_SDC_N_HBR2_MASK GENMASK(2, 0) 117 + /* CMN_REG(006b) */ 118 + #define ROPLL_SDC_N_HBR3_MASK GENMASK(3, 1) 119 + /* CMN_REG(006c) */ 120 + #define ROPLL_SDC_NUM_MASK GENMASK(5, 0) 121 + /* cmn_reg0070 */ 122 + #define ROPLL_SDC_DENO_MASK GENMASK(5, 0) 81 123 /* CMN_REG(0074) */ 82 - #define ROPLL_SDC_NDIV_RSTN BIT(2) 83 - #define ROPLL_SSC_EN BIT(0) 124 + #define OVRD_ROPLL_SDC_NDIV_RSTN_MASK BIT(3) 125 + #define ROPLL_SDC_NDIV_RSTN_MASK BIT(2) 126 + #define OVRD_ROPLL_SSC_EN_MASK BIT(1) 127 + #define ROPLL_SSC_EN_MASK BIT(0) 128 + /* CMN_REG(0075) */ 129 + #define ANA_ROPLL_SSC_FM_DEVIATION_MASK GENMASK(5, 0) 130 + /* CMN_REG(0076) */ 131 + #define ANA_ROPLL_SSC_FM_FREQ_MASK GENMASK(6, 2) 132 + /* CMN_REG(0077) */ 133 + #define ANA_ROPLL_SSC_CLK_DIV_SEL_MASK GENMASK(6, 3) 84 134 /* CMN_REG(0081) */ 85 - #define OVRD_PLL_CD_CLK_EN BIT(8) 86 - #define PLL_CD_HSCLK_EAST_EN BIT(0) 135 + #define OVRD_PLL_CD_CLK_EN_MASK BIT(8) 136 + #define ANA_PLL_CD_TX_SER_RATE_SEL_MASK BIT(3) 137 + #define ANA_PLL_CD_HSCLK_WEST_EN_MASK BIT(1) 138 + #define ANA_PLL_CD_HSCLK_EAST_EN_MASK BIT(0) 139 + /* CMN_REG(0082) */ 140 + #define ANA_PLL_CD_VREG_GAIN_CTRL_MASK GENMASK(3, 0) 141 + /* CMN_REG(0083) */ 142 + #define ANA_PLL_CD_VREG_ICTRL_MASK GENMASK(6, 5) 143 + /* CMN_REG(0084) */ 144 + #define PLL_LCRO_CLK_SEL_MASK BIT(5) 145 + /* CMN_REG(0085) */ 146 + #define ANA_PLL_SYNC_LOSS_DET_MODE_MASK GENMASK(1, 0) 87 147 /* CMN_REG(0086) */ 88 148 #define PLL_PCG_POSTDIV_SEL_MASK GENMASK(7, 4) 89 149 #define PLL_PCG_CLK_SEL_MASK GENMASK(3, 1) 90 - #define PLL_PCG_CLK_EN BIT(0) 150 + #define PLL_PCG_CLK_EN_MASK BIT(0) 91 151 /* CMN_REG(0087) */ 92 - #define PLL_FRL_MODE_EN BIT(3) 93 - #define PLL_TX_HS_CLK_EN BIT(2) 152 + #define ANA_PLL_FRL_MODE_EN_MASK BIT(3) 153 + #define ANA_PLL_TX_HS_CLK_EN_MASK BIT(2) 94 154 /* CMN_REG(0089) */ 95 - #define LCPLL_ALONE_MODE BIT(1) 155 + #define LCPLL_ALONE_MODE_MASK BIT(1) 156 + /* CMN_REG(0095) */ 157 + #define DP_TX_LINK_BW_MASK GENMASK(1, 0) 96 158 /* CMN_REG(0097) */ 97 - #define DIG_CLK_SEL BIT(1) 98 - #define ROPLL_REF BIT(1) 99 - #define LCPLL_REF 0 159 + #define DIG_CLK_SEL_MASK BIT(1) 160 + #define LCPLL_REF BIT(1) 161 + #define ROPLL_REF 0 100 162 /* CMN_REG(0099) */ 101 - #define CMN_ROPLL_ALONE_MODE BIT(2) 163 + #define SSC_EN_MASK GENMASK(7, 6) 164 + #define CMN_ROPLL_ALONE_MODE_MASK BIT(2) 102 165 #define ROPLL_ALONE_MODE BIT(2) 103 166 /* CMN_REG(009a) */ 104 - #define HS_SPEED_SEL BIT(0) 167 + #define HS_SPEED_SEL_MASK BIT(0) 105 168 #define DIV_10_CLOCK BIT(0) 106 169 /* CMN_REG(009b) */ 107 - #define IS_SPEED_SEL BIT(4) 170 + #define LS_SPEED_SEL_MASK BIT(4) 108 171 #define LINK_SYMBOL_CLOCK BIT(4) 109 172 #define LINK_SYMBOL_CLOCK1_2 0 110 173 ··· 183 118 /* SB_REG(0104) */ 184 119 #define OVRD_SB_EN_MASK BIT(5) 185 120 #define SB_EN_MASK BIT(4) 121 + #define OVRD_SB_AUX_EN_MASK BIT(1) 122 + #define SB_AUX_EN_MASK BIT(0) 186 123 /* SB_REG(0105) */ 187 124 #define OVRD_SB_EARC_CMDC_EN_MASK BIT(6) 188 125 #define SB_EARC_CMDC_EN_MASK BIT(5) ··· 193 126 #define ANA_SB_TX_LLVL_PROG_MASK GENMASK(6, 4) 194 127 /* SB_REG(0109) */ 195 128 #define ANA_SB_DMRX_AFC_DIV_RATIO_MASK GENMASK(2, 0) 129 + /* SB_REG(010d) */ 130 + #define ANA_SB_DMRX_LPBK_DATA_MASK BIT(4) 196 131 /* SB_REG(010f) */ 197 132 #define OVRD_SB_VREG_EN_MASK BIT(7) 198 133 #define SB_VREG_EN_MASK BIT(6) ··· 202 133 #define SB_VREG_LPF_BYPASS_MASK BIT(4) 203 134 #define ANA_SB_VREG_GAIN_CTRL_MASK GENMASK(3, 0) 204 135 /* SB_REG(0110) */ 136 + #define ANA_SB_VREG_OUT_SEL_MASK BIT(1) 205 137 #define ANA_SB_VREG_REF_SEL_MASK BIT(0) 206 138 /* SB_REG(0113) */ 207 139 #define SB_RX_RCAL_OPT_CODE_MASK GENMASK(5, 4) ··· 217 147 #define AFC_RSTN_DELAY_TIME_MASK GENMASK(6, 4) 218 148 /* SB_REG(0117) */ 219 149 #define FAST_PULSE_TIME_MASK GENMASK(3, 0) 150 + /* SB_REG(0118) */ 151 + #define SB_TG_EARC_DMRX_RECVRD_CLK_CNT_MASK GENMASK(7, 0) 152 + /* SB_REG(011a) */ 153 + #define SB_TG_CNT_RUN_NO_7_0_MASK GENMASK(7, 0) 220 154 /* SB_REG(011b) */ 221 155 #define SB_EARC_SIG_DET_BYPASS_MASK BIT(4) 222 156 #define SB_AFC_TOL_MASK GENMASK(3, 0) 157 + /* SB_REG(011c) */ 158 + #define SB_AFC_STB_NUM_MASK GENMASK(3, 0) 159 + /* SB_REG(011d) */ 160 + #define SB_TG_OSC_CNT_MIN_MASK GENMASK(7, 0) 161 + /* SB_REG(011e) */ 162 + #define SB_TG_OSC_CNT_MAX_MASK GENMASK(7, 0) 223 163 /* SB_REG(011f) */ 224 164 #define SB_PWM_AFC_CTRL_MASK GENMASK(7, 2) 225 165 #define SB_RCAL_RSTN_MASK BIT(1) 226 166 /* SB_REG(0120) */ 167 + #define SB_AUX_EN_IN_MASK BIT(7) 227 168 #define SB_EARC_EN_MASK BIT(1) 228 169 #define SB_EARC_AFC_EN_MASK BIT(2) 229 170 /* SB_REG(0123) */ ··· 242 161 #define SB_READY_MASK BIT(4) 243 162 244 163 /* LNTOP_REG(0200) */ 245 - #define PROTOCOL_SEL BIT(2) 164 + #define PROTOCOL_SEL_MASK BIT(2) 246 165 #define HDMI_MODE BIT(2) 247 166 #define HDMI_TMDS_FRL_SEL BIT(1) 248 167 /* LNTOP_REG(0206) */ 249 - #define DATA_BUS_SEL BIT(0) 168 + #define DATA_BUS_WIDTH_MASK GENMASK(2, 1) 169 + #define DATA_BUS_WIDTH_SEL_MASK BIT(0) 250 170 #define DATA_BUS_36_40 BIT(0) 251 171 /* LNTOP_REG(0207) */ 252 - #define LANE_EN 0xf 172 + #define LANE_EN_MASK 0xf 253 173 #define ALL_LANE_EN 0xf 254 174 175 + /* LANE_REG(0301) */ 176 + #define OVRD_LN_TX_DRV_EI_EN_MASK BIT(7) 177 + #define LN_TX_DRV_EI_EN_MASK BIT(6) 178 + /* LANE_REG(0303) */ 179 + #define OVRD_LN_TX_DRV_LVL_CTRL_MASK BIT(5) 180 + #define LN_TX_DRV_LVL_CTRL_MASK GENMASK(4, 0) 181 + /* LANE_REG(0304) */ 182 + #define OVRD_LN_TX_DRV_POST_LVL_CTRL_MASK BIT(4) 183 + #define LN_TX_DRV_POST_LVL_CTRL_MASK GENMASK(3, 0) 184 + /* LANE_REG(0305) */ 185 + #define OVRD_LN_TX_DRV_PRE_LVL_CTRL_MASK BIT(6) 186 + #define LN_TX_DRV_PRE_LVL_CTRL_MASK GENMASK(5, 2) 187 + /* LANE_REG(0306) */ 188 + #define LN_ANA_TX_DRV_IDRV_IDN_CTRL_MASK GENMASK(7, 5) 189 + #define LN_ANA_TX_DRV_IDRV_IUP_CTRL_MASK GENMASK(4, 2) 190 + #define LN_ANA_TX_DRV_ACCDRV_EN_MASK BIT(0) 191 + /* LANE_REG(0307) */ 192 + #define LN_ANA_TX_DRV_ACCDRV_POL_SEL_MASK BIT(6) 193 + #define LN_ANA_TX_DRV_ACCDRV_CTRL_MASK GENMASK(5, 3) 194 + /* LANE_REG(030a) */ 195 + #define LN_ANA_TX_JEQ_EN_MASK BIT(4) 196 + #define LN_TX_JEQ_EVEN_CTRL_RBR_MASK GENMASK(3, 0) 197 + /* LANE_REG(030b) */ 198 + #define LN_TX_JEQ_EVEN_CTRL_HBR_MASK GENMASK(7, 4) 199 + #define LN_TX_JEQ_EVEN_CTRL_HBR2_MASK GENMASK(3, 0) 200 + /* LANE_REG(030c) */ 201 + #define LN_TX_JEQ_ODD_CTRL_RBR_MASK GENMASK(3, 0) 202 + /* LANE_REG(030d) */ 203 + #define LN_TX_JEQ_ODD_CTRL_HBR_MASK GENMASK(7, 4) 204 + #define LN_TX_JEQ_ODD_CTRL_HBR2_MASK GENMASK(3, 0) 205 + /* LANE_REG(0310) */ 206 + #define LN_ANA_TX_SYNC_LOSS_DET_MODE_MASK GENMASK(1, 0) 207 + /* LANE_REG(0311) */ 208 + #define LN_TX_SER_40BIT_EN_RBR_MASK BIT(3) 209 + #define LN_TX_SER_40BIT_EN_HBR_MASK BIT(2) 210 + #define LN_TX_SER_40BIT_EN_HBR2_MASK BIT(1) 255 211 /* LANE_REG(0312) */ 256 - #define LN0_TX_SER_RATE_SEL_RBR BIT(5) 257 - #define LN0_TX_SER_RATE_SEL_HBR BIT(4) 258 - #define LN0_TX_SER_RATE_SEL_HBR2 BIT(3) 259 - #define LN0_TX_SER_RATE_SEL_HBR3 BIT(2) 212 + #define LN0_TX_SER_RATE_SEL_RBR_MASK BIT(5) 213 + #define LN0_TX_SER_RATE_SEL_HBR_MASK BIT(4) 214 + #define LN0_TX_SER_RATE_SEL_HBR2_MASK BIT(3) 215 + #define LN0_TX_SER_RATE_SEL_HBR3_MASK BIT(2) 216 + /* LANE_REG(0316) */ 217 + #define LN_ANA_TX_SER_VREG_GAIN_CTRL_MASK GENMASK(3, 0) 218 + /* LANE_REG(031B) */ 219 + #define LN_ANA_TX_RESERVED_MASK GENMASK(7, 0) 220 + /* LANE_REG(031e) */ 221 + #define LN_POLARITY_INV_MASK BIT(2) 222 + #define LN_LANE_MODE_MASK BIT(1) 223 + 260 224 /* LANE_REG(0412) */ 261 - #define LN1_TX_SER_RATE_SEL_RBR BIT(5) 262 - #define LN1_TX_SER_RATE_SEL_HBR BIT(4) 263 - #define LN1_TX_SER_RATE_SEL_HBR2 BIT(3) 264 - #define LN1_TX_SER_RATE_SEL_HBR3 BIT(2) 225 + #define LN1_TX_SER_RATE_SEL_RBR_MASK BIT(5) 226 + #define LN1_TX_SER_RATE_SEL_HBR_MASK BIT(4) 227 + #define LN1_TX_SER_RATE_SEL_HBR2_MASK BIT(3) 228 + #define LN1_TX_SER_RATE_SEL_HBR3_MASK BIT(2) 229 + 265 230 /* LANE_REG(0512) */ 266 - #define LN2_TX_SER_RATE_SEL_RBR BIT(5) 267 - #define LN2_TX_SER_RATE_SEL_HBR BIT(4) 268 - #define LN2_TX_SER_RATE_SEL_HBR2 BIT(3) 269 - #define LN2_TX_SER_RATE_SEL_HBR3 BIT(2) 231 + #define LN2_TX_SER_RATE_SEL_RBR_MASK BIT(5) 232 + #define LN2_TX_SER_RATE_SEL_HBR_MASK BIT(4) 233 + #define LN2_TX_SER_RATE_SEL_HBR2_MASK BIT(3) 234 + #define LN2_TX_SER_RATE_SEL_HBR3_MASK BIT(2) 235 + 270 236 /* LANE_REG(0612) */ 271 - #define LN3_TX_SER_RATE_SEL_RBR BIT(5) 272 - #define LN3_TX_SER_RATE_SEL_HBR BIT(4) 273 - #define LN3_TX_SER_RATE_SEL_HBR2 BIT(3) 274 - #define LN3_TX_SER_RATE_SEL_HBR3 BIT(2) 237 + #define LN3_TX_SER_RATE_SEL_RBR_MASK BIT(5) 238 + #define LN3_TX_SER_RATE_SEL_HBR_MASK BIT(4) 239 + #define LN3_TX_SER_RATE_SEL_HBR2_MASK BIT(3) 240 + #define LN3_TX_SER_RATE_SEL_HBR3_MASK BIT(2) 275 241 276 242 #define HDMI20_MAX_RATE 600000000 243 + 244 + enum dp_link_rate { 245 + DP_BW_RBR, 246 + DP_BW_HBR, 247 + DP_BW_HBR2, 248 + }; 277 249 278 250 struct lcpll_config { 279 251 u32 bit_rate; ··· 389 255 u8 cd_tx_ser_rate_sel; 390 256 }; 391 257 258 + struct tx_drv_ctrl { 259 + u8 tx_drv_lvl_ctrl; 260 + u8 tx_drv_post_lvl_ctrl; 261 + u8 ana_tx_drv_idrv_idn_ctrl; 262 + u8 ana_tx_drv_idrv_iup_ctrl; 263 + u8 ana_tx_drv_accdrv_en; 264 + u8 ana_tx_drv_accdrv_ctrl; 265 + u8 tx_drv_pre_lvl_ctrl; 266 + u8 ana_tx_jeq_en; 267 + u8 tx_jeq_even_ctrl; 268 + u8 tx_jeq_odd_ctrl; 269 + }; 270 + 392 271 enum rk_hdptx_reset { 393 272 RST_APB = 0, 394 273 RST_INIT, ··· 410 263 RST_MAX 411 264 }; 412 265 266 + #define MAX_HDPTX_PHY_NUM 2 267 + 268 + struct rk_hdptx_phy_cfg { 269 + unsigned int num_phys; 270 + unsigned int phy_ids[MAX_HDPTX_PHY_NUM]; 271 + }; 272 + 413 273 struct rk_hdptx_phy { 414 274 struct device *dev; 415 275 struct regmap *regmap; 416 276 struct regmap *grf; 277 + 278 + /* PHY const config */ 279 + const struct rk_hdptx_phy_cfg *cfgs; 280 + int phy_id; 417 281 418 282 struct phy *phy; 419 283 struct phy_config *phy_cfg; ··· 437 279 unsigned long rate; 438 280 439 281 atomic_t usage_count; 282 + 283 + /* used for dp mode */ 284 + unsigned int link_rate; 285 + unsigned int lanes; 440 286 }; 441 287 442 288 static const struct ropll_config ropll_tmds_cfg[] = { ··· 719 557 REG_SEQ0(LANE_REG(0606), 0x1c), 720 558 }; 721 559 560 + static struct tx_drv_ctrl tx_drv_ctrl_rbr[4][4] = { 561 + /* voltage swing 0, pre-emphasis 0->3 */ 562 + { 563 + { 0x2, 0x0, 0x4, 0x6, 0x0, 0x4, 0x1, 0x1, 0x7, 0x7 }, 564 + { 0x4, 0x3, 0x4, 0x6, 0x0, 0x4, 0x0, 0x1, 0x7, 0x7 }, 565 + { 0x7, 0x6, 0x4, 0x6, 0x0, 0x4, 0x0, 0x1, 0x7, 0x7 }, 566 + { 0xd, 0xc, 0x7, 0x7, 0x1, 0x7, 0x0, 0x1, 0x7, 0x7 }, 567 + }, 568 + 569 + /* voltage swing 1, pre-emphasis 0->2 */ 570 + { 571 + { 0x4, 0x0, 0x4, 0x6, 0x0, 0x4, 0x1, 0x1, 0x7, 0x7 }, 572 + { 0x9, 0x5, 0x4, 0x6, 0x0, 0x4, 0x0, 0x1, 0x7, 0x7 }, 573 + { 0xc, 0x8, 0x7, 0x7, 0x1, 0x7, 0x0, 0x1, 0x7, 0x7 }, 574 + }, 575 + 576 + /* voltage swing 2, pre-emphasis 0->1 */ 577 + { 578 + { 0x8, 0x0, 0x4, 0x6, 0x0, 0x4, 0x1, 0x1, 0x7, 0x7 }, 579 + { 0xc, 0x5, 0x7, 0x7, 0x1, 0x7, 0x0, 0x1, 0x7, 0x7 }, 580 + }, 581 + 582 + /* voltage swing 3, pre-emphasis 0 */ 583 + { 584 + { 0xb, 0x0, 0x7, 0x7, 0x1, 0x4, 0x1, 0x1, 0x7, 0x7 }, 585 + } 586 + }; 587 + 588 + static struct tx_drv_ctrl tx_drv_ctrl_hbr[4][4] = { 589 + /* voltage swing 0, pre-emphasis 0->3 */ 590 + { 591 + { 0x2, 0x0, 0x4, 0x6, 0x0, 0x4, 0x1, 0x1, 0x7, 0x7 }, 592 + { 0x5, 0x4, 0x4, 0x6, 0x0, 0x4, 0x0, 0x1, 0x7, 0x7 }, 593 + { 0x9, 0x8, 0x4, 0x6, 0x0, 0x4, 0x0, 0x1, 0x7, 0x7 }, 594 + { 0xd, 0xc, 0x7, 0x7, 0x1, 0x7, 0x0, 0x1, 0x7, 0x7 }, 595 + }, 596 + 597 + /* voltage swing 1, pre-emphasis 0->2 */ 598 + { 599 + { 0x6, 0x1, 0x4, 0x6, 0x0, 0x4, 0x1, 0x1, 0x7, 0x7 }, 600 + { 0xa, 0x6, 0x4, 0x6, 0x0, 0x4, 0x0, 0x1, 0x7, 0x7 }, 601 + { 0xc, 0x8, 0x7, 0x7, 0x1, 0x7, 0x0, 0x1, 0x7, 0x7 }, 602 + }, 603 + 604 + /* voltage swing 2, pre-emphasis 0->1 */ 605 + { 606 + { 0x9, 0x1, 0x4, 0x6, 0x0, 0x4, 0x1, 0x1, 0x7, 0x7 }, 607 + { 0xd, 0x6, 0x7, 0x7, 0x1, 0x7, 0x0, 0x1, 0x7, 0x7 }, 608 + }, 609 + 610 + /* voltage swing 3, pre-emphasis 0 */ 611 + { 612 + { 0xc, 0x1, 0x7, 0x7, 0x1, 0x4, 0x1, 0x1, 0x7, 0x7 }, 613 + } 614 + }; 615 + 616 + static struct tx_drv_ctrl tx_drv_ctrl_hbr2[4][4] = { 617 + /* voltage swing 0, pre-emphasis 0->3 */ 618 + { 619 + { 0x2, 0x1, 0x4, 0x6, 0x0, 0x4, 0x0, 0x1, 0x7, 0x7 }, 620 + { 0x5, 0x4, 0x4, 0x6, 0x0, 0x4, 0x0, 0x1, 0x7, 0x7 }, 621 + { 0x9, 0x8, 0x4, 0x6, 0x1, 0x4, 0x0, 0x1, 0x7, 0x7 }, 622 + { 0xd, 0xc, 0x7, 0x7, 0x1, 0x7, 0x0, 0x1, 0x7, 0x7 }, 623 + }, 624 + 625 + /* voltage swing 1, pre-emphasis 0->2 */ 626 + { 627 + { 0x6, 0x1, 0x4, 0x6, 0x0, 0x4, 0x1, 0x1, 0x7, 0x7 }, 628 + { 0xb, 0x7, 0x4, 0x6, 0x0, 0x4, 0x0, 0x1, 0x7, 0x7 }, 629 + { 0xd, 0x9, 0x7, 0x7, 0x1, 0x7, 0x0, 0x1, 0x7, 0x7 }, 630 + }, 631 + 632 + /* voltage swing 2, pre-emphasis 0->1 */ 633 + { 634 + { 0x8, 0x1, 0x4, 0x6, 0x0, 0x4, 0x1, 0x1, 0x7, 0x7 }, 635 + { 0xc, 0x6, 0x7, 0x7, 0x1, 0x7, 0x0, 0x1, 0x7, 0x7 }, 636 + }, 637 + 638 + /* voltage swing 3, pre-emphasis 0 */ 639 + { 640 + { 0xb, 0x0, 0x7, 0x7, 0x1, 0x4, 0x1, 0x1, 0x7, 0x7 }, 641 + } 642 + }; 643 + 722 644 static bool rk_hdptx_phy_is_rw_reg(struct device *dev, unsigned int reg) 723 645 { 724 646 switch (reg) { 725 - case 0x0000 ... 0x029c: 726 - case 0x0400 ... 0x04a4: 727 - case 0x0800 ... 0x08a4: 728 - case 0x0c00 ... 0x0cb4: 729 - case 0x1000 ... 0x10b4: 730 - case 0x1400 ... 0x14b4: 731 - case 0x1800 ... 0x18b4: 647 + case 0x0000 ... 0x029c: /* CMN Register */ 648 + case 0x0400 ... 0x04a4: /* Sideband Register */ 649 + case 0x0800 ... 0x08a4: /* Lane Top Register */ 650 + case 0x0c00 ... 0x0cb4: /* Lane 0 Register */ 651 + case 0x1000 ... 0x10b4: /* Lane 1 Register */ 652 + case 0x1400 ... 0x14b4: /* Lane 2 Register */ 653 + case 0x1800 ... 0x18b4: /* Lane 3 Register */ 732 654 return true; 733 655 } 734 656 ··· 1059 813 regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK, 1060 814 FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv)); 1061 815 1062 - regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN, 1063 - PLL_PCG_CLK_EN); 816 + regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK, 817 + FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1)); 1064 818 1065 819 return rk_hdptx_post_enable_pll(hdptx); 1066 820 } ··· 1089 843 return rk_hdptx_post_enable_lane(hdptx); 1090 844 } 1091 845 846 + static void rk_hdptx_dp_reset(struct rk_hdptx_phy *hdptx) 847 + { 848 + reset_control_assert(hdptx->rsts[RST_LANE].rstc); 849 + reset_control_assert(hdptx->rsts[RST_CMN].rstc); 850 + reset_control_assert(hdptx->rsts[RST_INIT].rstc); 851 + 852 + reset_control_assert(hdptx->rsts[RST_APB].rstc); 853 + udelay(10); 854 + reset_control_deassert(hdptx->rsts[RST_APB].rstc); 855 + 856 + regmap_update_bits(hdptx->regmap, LANE_REG(0301), 857 + OVRD_LN_TX_DRV_EI_EN_MASK | LN_TX_DRV_EI_EN_MASK, 858 + FIELD_PREP(OVRD_LN_TX_DRV_EI_EN_MASK, 1) | 859 + FIELD_PREP(LN_TX_DRV_EI_EN_MASK, 0)); 860 + regmap_update_bits(hdptx->regmap, LANE_REG(0401), 861 + OVRD_LN_TX_DRV_EI_EN_MASK | LN_TX_DRV_EI_EN_MASK, 862 + FIELD_PREP(OVRD_LN_TX_DRV_EI_EN_MASK, 1) | 863 + FIELD_PREP(LN_TX_DRV_EI_EN_MASK, 0)); 864 + regmap_update_bits(hdptx->regmap, LANE_REG(0501), 865 + OVRD_LN_TX_DRV_EI_EN_MASK | LN_TX_DRV_EI_EN_MASK, 866 + FIELD_PREP(OVRD_LN_TX_DRV_EI_EN_MASK, 1) | 867 + FIELD_PREP(LN_TX_DRV_EI_EN_MASK, 0)); 868 + regmap_update_bits(hdptx->regmap, LANE_REG(0601), 869 + OVRD_LN_TX_DRV_EI_EN_MASK | LN_TX_DRV_EI_EN_MASK, 870 + FIELD_PREP(OVRD_LN_TX_DRV_EI_EN_MASK, 1) | 871 + FIELD_PREP(LN_TX_DRV_EI_EN_MASK, 0)); 872 + 873 + regmap_write(hdptx->grf, GRF_HDPTX_CON0, 874 + HDPTX_I_PLL_EN << 16 | FIELD_PREP(HDPTX_I_PLL_EN, 0x0)); 875 + regmap_write(hdptx->grf, GRF_HDPTX_CON0, 876 + HDPTX_I_BIAS_EN << 16 | FIELD_PREP(HDPTX_I_BIAS_EN, 0x0)); 877 + regmap_write(hdptx->grf, GRF_HDPTX_CON0, 878 + HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x0)); 879 + } 880 + 1092 881 static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx, 1093 882 unsigned int rate) 1094 883 { 884 + enum phy_mode mode = phy_get_mode(hdptx->phy); 1095 885 u32 status; 1096 886 int ret; 1097 887 ··· 1141 859 if (status & HDPTX_O_PLL_LOCK_DONE) 1142 860 dev_warn(hdptx->dev, "PLL locked by unknown consumer!\n"); 1143 861 1144 - if (rate) { 1145 - ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate); 1146 - if (ret) 1147 - goto dec_usage; 862 + if (mode == PHY_MODE_DP) { 863 + rk_hdptx_dp_reset(hdptx); 864 + } else { 865 + if (rate) { 866 + ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate); 867 + if (ret) 868 + goto dec_usage; 869 + } 1148 870 } 1149 871 1150 872 return 0; ··· 1160 874 1161 875 static int rk_hdptx_phy_consumer_put(struct rk_hdptx_phy *hdptx, bool force) 1162 876 { 877 + enum phy_mode mode = phy_get_mode(hdptx->phy); 1163 878 u32 status; 1164 879 int ret; 1165 880 ··· 1174 887 } else { 1175 888 ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status); 1176 889 if (!ret) { 1177 - if (status & HDPTX_O_PLL_LOCK_DONE) 1178 - rk_hdptx_phy_disable(hdptx); 890 + if (status & HDPTX_O_PLL_LOCK_DONE) { 891 + if (mode == PHY_MODE_DP) 892 + rk_hdptx_dp_reset(hdptx); 893 + else 894 + rk_hdptx_phy_disable(hdptx); 895 + } 1179 896 return 0; 1180 897 } else if (force) { 1181 898 return 0; ··· 1190 899 return ret; 1191 900 } 1192 901 902 + static void rk_hdptx_dp_pll_init(struct rk_hdptx_phy *hdptx) 903 + { 904 + regmap_update_bits(hdptx->regmap, CMN_REG(003c), ANA_LCPLL_RESERVED7_MASK, 905 + FIELD_PREP(ANA_LCPLL_RESERVED7_MASK, 0x1)); 906 + 907 + regmap_update_bits(hdptx->regmap, CMN_REG(0046), 908 + ROPLL_ANA_CPP_CTRL_COARSE_MASK | ROPLL_ANA_CPP_CTRL_FINE_MASK, 909 + FIELD_PREP(ROPLL_ANA_CPP_CTRL_COARSE_MASK, 0xe) | 910 + FIELD_PREP(ROPLL_ANA_CPP_CTRL_FINE_MASK, 0xe)); 911 + regmap_update_bits(hdptx->regmap, CMN_REG(0047), 912 + ROPLL_ANA_LPF_C_SEL_COARSE_MASK | 913 + ROPLL_ANA_LPF_C_SEL_FINE_MASK, 914 + FIELD_PREP(ROPLL_ANA_LPF_C_SEL_COARSE_MASK, 0x4) | 915 + FIELD_PREP(ROPLL_ANA_LPF_C_SEL_FINE_MASK, 0x4)); 916 + 917 + regmap_write(hdptx->regmap, CMN_REG(0051), FIELD_PREP(ROPLL_PMS_MDIV_MASK, 0x87)); 918 + regmap_write(hdptx->regmap, CMN_REG(0052), FIELD_PREP(ROPLL_PMS_MDIV_MASK, 0x71)); 919 + regmap_write(hdptx->regmap, CMN_REG(0053), FIELD_PREP(ROPLL_PMS_MDIV_MASK, 0x71)); 920 + 921 + regmap_write(hdptx->regmap, CMN_REG(0055), 922 + FIELD_PREP(ROPLL_PMS_MDIV_AFC_MASK, 0x87)); 923 + regmap_write(hdptx->regmap, CMN_REG(0056), 924 + FIELD_PREP(ROPLL_PMS_MDIV_AFC_MASK, 0x71)); 925 + regmap_write(hdptx->regmap, CMN_REG(0057), 926 + FIELD_PREP(ROPLL_PMS_MDIV_AFC_MASK, 0x71)); 927 + 928 + regmap_write(hdptx->regmap, CMN_REG(0059), 929 + FIELD_PREP(ANA_ROPLL_PMS_PDIV_MASK, 0x1) | 930 + FIELD_PREP(ANA_ROPLL_PMS_REFDIV_MASK, 0x1)); 931 + regmap_write(hdptx->regmap, CMN_REG(005a), 932 + FIELD_PREP(ROPLL_PMS_SDIV_RBR_MASK, 0x3) | 933 + FIELD_PREP(ROPLL_PMS_SDIV_HBR_MASK, 0x1)); 934 + regmap_update_bits(hdptx->regmap, CMN_REG(005b), ROPLL_PMS_SDIV_HBR2_MASK, 935 + FIELD_PREP(ROPLL_PMS_SDIV_HBR2_MASK, 0x0)); 936 + 937 + regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDM_EN_MASK, 938 + FIELD_PREP(ROPLL_SDM_EN_MASK, 0x1)); 939 + regmap_update_bits(hdptx->regmap, CMN_REG(005e), 940 + OVRD_ROPLL_SDM_RSTN_MASK | ROPLL_SDM_RSTN_MASK, 941 + FIELD_PREP(OVRD_ROPLL_SDM_RSTN_MASK, 0x1) | 942 + FIELD_PREP(ROPLL_SDM_RSTN_MASK, 0x1)); 943 + regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDC_FRAC_EN_RBR_MASK, 944 + FIELD_PREP(ROPLL_SDC_FRAC_EN_RBR_MASK, 0x1)); 945 + regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDC_FRAC_EN_HBR_MASK, 946 + FIELD_PREP(ROPLL_SDC_FRAC_EN_HBR_MASK, 0x1)); 947 + regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDC_FRAC_EN_HBR2_MASK, 948 + FIELD_PREP(ROPLL_SDC_FRAC_EN_HBR2_MASK, 0x1)); 949 + 950 + regmap_update_bits(hdptx->regmap, CMN_REG(005f), 951 + OVRD_ROPLL_SDC_RSTN_MASK | ROPLL_SDC_RSTN_MASK, 952 + FIELD_PREP(OVRD_ROPLL_SDC_RSTN_MASK, 0x1) | 953 + FIELD_PREP(ROPLL_SDC_RSTN_MASK, 0x1)); 954 + regmap_write(hdptx->regmap, CMN_REG(0060), 955 + FIELD_PREP(ROPLL_SDM_DENOMINATOR_MASK, 0x21)); 956 + regmap_write(hdptx->regmap, CMN_REG(0061), 957 + FIELD_PREP(ROPLL_SDM_DENOMINATOR_MASK, 0x27)); 958 + regmap_write(hdptx->regmap, CMN_REG(0062), 959 + FIELD_PREP(ROPLL_SDM_DENOMINATOR_MASK, 0x27)); 960 + 961 + regmap_update_bits(hdptx->regmap, CMN_REG(0064), 962 + ROPLL_SDM_NUM_SIGN_RBR_MASK | 963 + ROPLL_SDM_NUM_SIGN_HBR_MASK | 964 + ROPLL_SDM_NUM_SIGN_HBR2_MASK, 965 + FIELD_PREP(ROPLL_SDM_NUM_SIGN_RBR_MASK, 0x0) | 966 + FIELD_PREP(ROPLL_SDM_NUM_SIGN_HBR_MASK, 0x1) | 967 + FIELD_PREP(ROPLL_SDM_NUM_SIGN_HBR2_MASK, 0x1)); 968 + regmap_write(hdptx->regmap, CMN_REG(0065), 969 + FIELD_PREP(ROPLL_SDM_NUM_MASK, 0x0)); 970 + regmap_write(hdptx->regmap, CMN_REG(0066), 971 + FIELD_PREP(ROPLL_SDM_NUM_MASK, 0xd)); 972 + regmap_write(hdptx->regmap, CMN_REG(0067), 973 + FIELD_PREP(ROPLL_SDM_NUM_MASK, 0xd)); 974 + 975 + regmap_update_bits(hdptx->regmap, CMN_REG(0069), ROPLL_SDC_N_RBR_MASK, 976 + FIELD_PREP(ROPLL_SDC_N_RBR_MASK, 0x2)); 977 + 978 + regmap_update_bits(hdptx->regmap, CMN_REG(006a), 979 + ROPLL_SDC_N_HBR_MASK | ROPLL_SDC_N_HBR2_MASK, 980 + FIELD_PREP(ROPLL_SDC_N_HBR_MASK, 0x1) | 981 + FIELD_PREP(ROPLL_SDC_N_HBR2_MASK, 0x1)); 982 + 983 + regmap_write(hdptx->regmap, CMN_REG(006c), 984 + FIELD_PREP(ROPLL_SDC_NUM_MASK, 0x3)); 985 + regmap_write(hdptx->regmap, CMN_REG(006d), 986 + FIELD_PREP(ROPLL_SDC_NUM_MASK, 0x7)); 987 + regmap_write(hdptx->regmap, CMN_REG(006e), 988 + FIELD_PREP(ROPLL_SDC_NUM_MASK, 0x7)); 989 + 990 + regmap_write(hdptx->regmap, CMN_REG(0070), 991 + FIELD_PREP(ROPLL_SDC_DENO_MASK, 0x8)); 992 + regmap_write(hdptx->regmap, CMN_REG(0071), 993 + FIELD_PREP(ROPLL_SDC_DENO_MASK, 0x18)); 994 + regmap_write(hdptx->regmap, CMN_REG(0072), 995 + FIELD_PREP(ROPLL_SDC_DENO_MASK, 0x18)); 996 + 997 + regmap_update_bits(hdptx->regmap, CMN_REG(0074), 998 + OVRD_ROPLL_SDC_NDIV_RSTN_MASK | ROPLL_SDC_NDIV_RSTN_MASK, 999 + FIELD_PREP(OVRD_ROPLL_SDC_NDIV_RSTN_MASK, 0x1) | 1000 + FIELD_PREP(ROPLL_SDC_NDIV_RSTN_MASK, 0x1)); 1001 + 1002 + regmap_update_bits(hdptx->regmap, CMN_REG(0077), ANA_ROPLL_SSC_CLK_DIV_SEL_MASK, 1003 + FIELD_PREP(ANA_ROPLL_SSC_CLK_DIV_SEL_MASK, 0x1)); 1004 + 1005 + regmap_update_bits(hdptx->regmap, CMN_REG(0081), ANA_PLL_CD_TX_SER_RATE_SEL_MASK, 1006 + FIELD_PREP(ANA_PLL_CD_TX_SER_RATE_SEL_MASK, 0x0)); 1007 + regmap_update_bits(hdptx->regmap, CMN_REG(0081), 1008 + ANA_PLL_CD_HSCLK_EAST_EN_MASK | ANA_PLL_CD_HSCLK_WEST_EN_MASK, 1009 + FIELD_PREP(ANA_PLL_CD_HSCLK_EAST_EN_MASK, 0x1) | 1010 + FIELD_PREP(ANA_PLL_CD_HSCLK_WEST_EN_MASK, 0x0)); 1011 + 1012 + regmap_update_bits(hdptx->regmap, CMN_REG(0082), ANA_PLL_CD_VREG_GAIN_CTRL_MASK, 1013 + FIELD_PREP(ANA_PLL_CD_VREG_GAIN_CTRL_MASK, 0x4)); 1014 + regmap_update_bits(hdptx->regmap, CMN_REG(0083), ANA_PLL_CD_VREG_ICTRL_MASK, 1015 + FIELD_PREP(ANA_PLL_CD_VREG_ICTRL_MASK, 0x1)); 1016 + regmap_update_bits(hdptx->regmap, CMN_REG(0084), PLL_LCRO_CLK_SEL_MASK, 1017 + FIELD_PREP(PLL_LCRO_CLK_SEL_MASK, 0x1)); 1018 + regmap_update_bits(hdptx->regmap, CMN_REG(0085), ANA_PLL_SYNC_LOSS_DET_MODE_MASK, 1019 + FIELD_PREP(ANA_PLL_SYNC_LOSS_DET_MODE_MASK, 0x3)); 1020 + 1021 + regmap_update_bits(hdptx->regmap, CMN_REG(0087), ANA_PLL_TX_HS_CLK_EN_MASK, 1022 + FIELD_PREP(ANA_PLL_TX_HS_CLK_EN_MASK, 0x1)); 1023 + 1024 + regmap_update_bits(hdptx->regmap, CMN_REG(0097), DIG_CLK_SEL_MASK, 1025 + FIELD_PREP(DIG_CLK_SEL_MASK, 0x1)); 1026 + 1027 + regmap_update_bits(hdptx->regmap, CMN_REG(0099), CMN_ROPLL_ALONE_MODE_MASK, 1028 + FIELD_PREP(CMN_ROPLL_ALONE_MODE_MASK, 0x1)); 1029 + regmap_update_bits(hdptx->regmap, CMN_REG(009a), HS_SPEED_SEL_MASK, 1030 + FIELD_PREP(HS_SPEED_SEL_MASK, 0x1)); 1031 + regmap_update_bits(hdptx->regmap, CMN_REG(009b), LS_SPEED_SEL_MASK, 1032 + FIELD_PREP(LS_SPEED_SEL_MASK, 0x1)); 1033 + } 1034 + 1035 + static int rk_hdptx_dp_aux_init(struct rk_hdptx_phy *hdptx) 1036 + { 1037 + u32 status; 1038 + int ret; 1039 + 1040 + regmap_update_bits(hdptx->regmap, SB_REG(0102), ANA_SB_RXTERM_OFFSP_MASK, 1041 + FIELD_PREP(ANA_SB_RXTERM_OFFSP_MASK, 0x3)); 1042 + regmap_update_bits(hdptx->regmap, SB_REG(0103), ANA_SB_RXTERM_OFFSN_MASK, 1043 + FIELD_PREP(ANA_SB_RXTERM_OFFSN_MASK, 0x3)); 1044 + regmap_update_bits(hdptx->regmap, SB_REG(0104), SB_AUX_EN_MASK, 1045 + FIELD_PREP(SB_AUX_EN_MASK, 0x1)); 1046 + regmap_update_bits(hdptx->regmap, SB_REG(0105), ANA_SB_TX_HLVL_PROG_MASK, 1047 + FIELD_PREP(ANA_SB_TX_HLVL_PROG_MASK, 0x7)); 1048 + regmap_update_bits(hdptx->regmap, SB_REG(0106), ANA_SB_TX_LLVL_PROG_MASK, 1049 + FIELD_PREP(ANA_SB_TX_LLVL_PROG_MASK, 0x7)); 1050 + 1051 + regmap_update_bits(hdptx->regmap, SB_REG(010d), ANA_SB_DMRX_LPBK_DATA_MASK, 1052 + FIELD_PREP(ANA_SB_DMRX_LPBK_DATA_MASK, 0x1)); 1053 + 1054 + regmap_update_bits(hdptx->regmap, SB_REG(010f), ANA_SB_VREG_GAIN_CTRL_MASK, 1055 + FIELD_PREP(ANA_SB_VREG_GAIN_CTRL_MASK, 0x0)); 1056 + regmap_update_bits(hdptx->regmap, SB_REG(0110), 1057 + ANA_SB_VREG_OUT_SEL_MASK | ANA_SB_VREG_REF_SEL_MASK, 1058 + FIELD_PREP(ANA_SB_VREG_OUT_SEL_MASK, 0x1) | 1059 + FIELD_PREP(ANA_SB_VREG_REF_SEL_MASK, 0x1)); 1060 + 1061 + regmap_update_bits(hdptx->regmap, SB_REG(0113), 1062 + SB_RX_RCAL_OPT_CODE_MASK | SB_RX_RTERM_CTRL_MASK, 1063 + FIELD_PREP(SB_RX_RCAL_OPT_CODE_MASK, 0x1) | 1064 + FIELD_PREP(SB_RX_RTERM_CTRL_MASK, 0x3)); 1065 + regmap_update_bits(hdptx->regmap, SB_REG(0114), 1066 + SB_TG_SB_EN_DELAY_TIME_MASK | SB_TG_RXTERM_EN_DELAY_TIME_MASK, 1067 + FIELD_PREP(SB_TG_SB_EN_DELAY_TIME_MASK, 0x2) | 1068 + FIELD_PREP(SB_TG_RXTERM_EN_DELAY_TIME_MASK, 0x2)); 1069 + regmap_update_bits(hdptx->regmap, SB_REG(0115), 1070 + SB_READY_DELAY_TIME_MASK | SB_TG_OSC_EN_DELAY_TIME_MASK, 1071 + FIELD_PREP(SB_READY_DELAY_TIME_MASK, 0x2) | 1072 + FIELD_PREP(SB_TG_OSC_EN_DELAY_TIME_MASK, 0x2)); 1073 + regmap_update_bits(hdptx->regmap, SB_REG(0116), 1074 + AFC_RSTN_DELAY_TIME_MASK, 1075 + FIELD_PREP(AFC_RSTN_DELAY_TIME_MASK, 0x2)); 1076 + regmap_update_bits(hdptx->regmap, SB_REG(0117), 1077 + FAST_PULSE_TIME_MASK, 1078 + FIELD_PREP(FAST_PULSE_TIME_MASK, 0x4)); 1079 + regmap_update_bits(hdptx->regmap, SB_REG(0118), 1080 + SB_TG_EARC_DMRX_RECVRD_CLK_CNT_MASK, 1081 + FIELD_PREP(SB_TG_EARC_DMRX_RECVRD_CLK_CNT_MASK, 0xa)); 1082 + 1083 + regmap_update_bits(hdptx->regmap, SB_REG(011a), SB_TG_CNT_RUN_NO_7_0_MASK, 1084 + FIELD_PREP(SB_TG_CNT_RUN_NO_7_0_MASK, 0x3)); 1085 + regmap_update_bits(hdptx->regmap, SB_REG(011b), 1086 + SB_EARC_SIG_DET_BYPASS_MASK | SB_AFC_TOL_MASK, 1087 + FIELD_PREP(SB_EARC_SIG_DET_BYPASS_MASK, 0x1) | 1088 + FIELD_PREP(SB_AFC_TOL_MASK, 0x3)); 1089 + regmap_update_bits(hdptx->regmap, SB_REG(011c), SB_AFC_STB_NUM_MASK, 1090 + FIELD_PREP(SB_AFC_STB_NUM_MASK, 0x4)); 1091 + regmap_update_bits(hdptx->regmap, SB_REG(011d), SB_TG_OSC_CNT_MIN_MASK, 1092 + FIELD_PREP(SB_TG_OSC_CNT_MIN_MASK, 0x67)); 1093 + regmap_update_bits(hdptx->regmap, SB_REG(011e), SB_TG_OSC_CNT_MAX_MASK, 1094 + FIELD_PREP(SB_TG_OSC_CNT_MAX_MASK, 0x6a)); 1095 + regmap_update_bits(hdptx->regmap, SB_REG(011f), SB_PWM_AFC_CTRL_MASK, 1096 + FIELD_PREP(SB_PWM_AFC_CTRL_MASK, 0x5)); 1097 + regmap_update_bits(hdptx->regmap, SB_REG(011f), SB_RCAL_RSTN_MASK, 1098 + FIELD_PREP(SB_RCAL_RSTN_MASK, 0x1)); 1099 + regmap_update_bits(hdptx->regmap, SB_REG(0120), SB_AUX_EN_IN_MASK, 1100 + FIELD_PREP(SB_AUX_EN_IN_MASK, 0x1)); 1101 + 1102 + regmap_update_bits(hdptx->regmap, SB_REG(0102), OVRD_SB_RXTERM_EN_MASK, 1103 + FIELD_PREP(OVRD_SB_RXTERM_EN_MASK, 0x1)); 1104 + regmap_update_bits(hdptx->regmap, SB_REG(0103), OVRD_SB_RX_RESCAL_DONE_MASK, 1105 + FIELD_PREP(OVRD_SB_RX_RESCAL_DONE_MASK, 0x1)); 1106 + regmap_update_bits(hdptx->regmap, SB_REG(0104), OVRD_SB_EN_MASK, 1107 + FIELD_PREP(OVRD_SB_EN_MASK, 0x1)); 1108 + regmap_update_bits(hdptx->regmap, SB_REG(0104), OVRD_SB_AUX_EN_MASK, 1109 + FIELD_PREP(OVRD_SB_AUX_EN_MASK, 0x1)); 1110 + 1111 + regmap_update_bits(hdptx->regmap, SB_REG(010f), OVRD_SB_VREG_EN_MASK, 1112 + FIELD_PREP(OVRD_SB_VREG_EN_MASK, 0x1)); 1113 + 1114 + regmap_write(hdptx->grf, GRF_HDPTX_CON0, 1115 + HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x1)); 1116 + regmap_write(hdptx->grf, GRF_HDPTX_CON0, 1117 + HDPTX_I_BIAS_EN << 16 | FIELD_PREP(HDPTX_I_BIAS_EN, 0x1)); 1118 + usleep_range(20, 25); 1119 + 1120 + reset_control_deassert(hdptx->rsts[RST_INIT].rstc); 1121 + usleep_range(20, 25); 1122 + reset_control_deassert(hdptx->rsts[RST_CMN].rstc); 1123 + usleep_range(20, 25); 1124 + 1125 + regmap_update_bits(hdptx->regmap, SB_REG(0103), OVRD_SB_RX_RESCAL_DONE_MASK, 1126 + FIELD_PREP(OVRD_SB_RX_RESCAL_DONE_MASK, 0x1)); 1127 + usleep_range(100, 110); 1128 + regmap_update_bits(hdptx->regmap, SB_REG(0104), SB_EN_MASK, 1129 + FIELD_PREP(SB_EN_MASK, 0x1)); 1130 + usleep_range(100, 110); 1131 + regmap_update_bits(hdptx->regmap, SB_REG(0102), SB_RXTERM_EN_MASK, 1132 + FIELD_PREP(SB_RXTERM_EN_MASK, 0x1)); 1133 + usleep_range(20, 25); 1134 + regmap_update_bits(hdptx->regmap, SB_REG(010f), SB_VREG_EN_MASK, 1135 + FIELD_PREP(SB_VREG_EN_MASK, 0x1)); 1136 + usleep_range(20, 25); 1137 + regmap_update_bits(hdptx->regmap, SB_REG(0104), SB_AUX_EN_MASK, 1138 + FIELD_PREP(SB_AUX_EN_MASK, 0x1)); 1139 + usleep_range(100, 110); 1140 + 1141 + ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, 1142 + status, FIELD_GET(HDPTX_O_SB_RDY, status), 1143 + 50, 1000); 1144 + if (ret) { 1145 + dev_err(hdptx->dev, "Failed to get phy sb ready: %d\n", ret); 1146 + return ret; 1147 + } 1148 + 1149 + return 0; 1150 + } 1151 + 1193 1152 static int rk_hdptx_phy_power_on(struct phy *phy) 1194 1153 { 1195 1154 struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); 1196 1155 int bus_width = phy_get_bus_width(hdptx->phy); 1197 - int ret; 1156 + enum phy_mode mode = phy_get_mode(phy); 1157 + int ret, lane; 1198 1158 1199 1159 /* 1200 1160 * FIXME: Temporary workaround to pass pixel_clk_rate ··· 1461 919 if (ret) 1462 920 return ret; 1463 921 1464 - ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); 1465 - if (ret) 1466 - rk_hdptx_phy_consumer_put(hdptx, true); 922 + if (mode == PHY_MODE_DP) { 923 + regmap_write(hdptx->grf, GRF_HDPTX_CON0, 924 + HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x1)); 925 + 926 + for (lane = 0; lane < 4; lane++) { 927 + regmap_update_bits(hdptx->regmap, LANE_REG(031e) + 0x400 * lane, 928 + LN_POLARITY_INV_MASK | LN_LANE_MODE_MASK, 929 + FIELD_PREP(LN_POLARITY_INV_MASK, 0) | 930 + FIELD_PREP(LN_LANE_MODE_MASK, 1)); 931 + } 932 + 933 + regmap_update_bits(hdptx->regmap, LNTOP_REG(0200), PROTOCOL_SEL_MASK, 934 + FIELD_PREP(PROTOCOL_SEL_MASK, 0x0)); 935 + regmap_update_bits(hdptx->regmap, LNTOP_REG(0206), DATA_BUS_WIDTH_MASK, 936 + FIELD_PREP(DATA_BUS_WIDTH_MASK, 0x1)); 937 + regmap_update_bits(hdptx->regmap, LNTOP_REG(0206), DATA_BUS_WIDTH_SEL_MASK, 938 + FIELD_PREP(DATA_BUS_WIDTH_SEL_MASK, 0x0)); 939 + 940 + rk_hdptx_dp_pll_init(hdptx); 941 + 942 + ret = rk_hdptx_dp_aux_init(hdptx); 943 + if (ret) 944 + rk_hdptx_phy_consumer_put(hdptx, true); 945 + } else { 946 + regmap_write(hdptx->grf, GRF_HDPTX_CON0, 947 + HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0)); 948 + 949 + ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); 950 + if (ret) 951 + rk_hdptx_phy_consumer_put(hdptx, true); 952 + } 1467 953 1468 954 return ret; 1469 955 } ··· 1503 933 return rk_hdptx_phy_consumer_put(hdptx, false); 1504 934 } 1505 935 936 + static int rk_hdptx_phy_verify_config(struct rk_hdptx_phy *hdptx, 937 + struct phy_configure_opts_dp *dp) 938 + { 939 + int i; 940 + 941 + if (dp->set_rate) { 942 + switch (dp->link_rate) { 943 + case 1620: 944 + case 2700: 945 + case 5400: 946 + break; 947 + default: 948 + return -EINVAL; 949 + } 950 + } 951 + 952 + if (dp->set_lanes) { 953 + switch (dp->lanes) { 954 + case 1: 955 + case 2: 956 + case 4: 957 + break; 958 + default: 959 + return -EINVAL; 960 + } 961 + } 962 + 963 + if (dp->set_voltages) { 964 + for (i = 0; i < hdptx->lanes; i++) { 965 + if (dp->voltage[i] > 3 || dp->pre[i] > 3) 966 + return -EINVAL; 967 + 968 + if (dp->voltage[i] + dp->pre[i] > 3) 969 + return -EINVAL; 970 + } 971 + } 972 + 973 + return 0; 974 + } 975 + 976 + static int rk_hdptx_phy_set_rate(struct rk_hdptx_phy *hdptx, 977 + struct phy_configure_opts_dp *dp) 978 + { 979 + u32 bw, status; 980 + int ret; 981 + 982 + regmap_write(hdptx->grf, GRF_HDPTX_CON0, 983 + HDPTX_I_PLL_EN << 16 | FIELD_PREP(HDPTX_I_PLL_EN, 0x0)); 984 + 985 + switch (dp->link_rate) { 986 + case 1620: 987 + bw = DP_BW_RBR; 988 + break; 989 + case 2700: 990 + bw = DP_BW_HBR; 991 + break; 992 + case 5400: 993 + bw = DP_BW_HBR2; 994 + break; 995 + default: 996 + return -EINVAL; 997 + } 998 + hdptx->link_rate = dp->link_rate; 999 + 1000 + regmap_update_bits(hdptx->regmap, CMN_REG(0008), OVRD_LCPLL_EN_MASK | LCPLL_EN_MASK, 1001 + FIELD_PREP(OVRD_LCPLL_EN_MASK, 0x1) | 1002 + FIELD_PREP(LCPLL_EN_MASK, 0x0)); 1003 + 1004 + regmap_update_bits(hdptx->regmap, CMN_REG(003d), OVRD_ROPLL_EN_MASK | ROPLL_EN_MASK, 1005 + FIELD_PREP(OVRD_ROPLL_EN_MASK, 0x1) | 1006 + FIELD_PREP(ROPLL_EN_MASK, 0x1)); 1007 + 1008 + if (dp->ssc) { 1009 + regmap_update_bits(hdptx->regmap, CMN_REG(0074), 1010 + OVRD_ROPLL_SSC_EN_MASK | ROPLL_SSC_EN_MASK, 1011 + FIELD_PREP(OVRD_ROPLL_SSC_EN_MASK, 0x1) | 1012 + FIELD_PREP(ROPLL_SSC_EN_MASK, 0x1)); 1013 + regmap_write(hdptx->regmap, CMN_REG(0075), 1014 + FIELD_PREP(ANA_ROPLL_SSC_FM_DEVIATION_MASK, 0xc)); 1015 + regmap_update_bits(hdptx->regmap, CMN_REG(0076), 1016 + ANA_ROPLL_SSC_FM_FREQ_MASK, 1017 + FIELD_PREP(ANA_ROPLL_SSC_FM_FREQ_MASK, 0x1f)); 1018 + 1019 + regmap_update_bits(hdptx->regmap, CMN_REG(0099), SSC_EN_MASK, 1020 + FIELD_PREP(SSC_EN_MASK, 0x2)); 1021 + } else { 1022 + regmap_update_bits(hdptx->regmap, CMN_REG(0074), 1023 + OVRD_ROPLL_SSC_EN_MASK | ROPLL_SSC_EN_MASK, 1024 + FIELD_PREP(OVRD_ROPLL_SSC_EN_MASK, 0x1) | 1025 + FIELD_PREP(ROPLL_SSC_EN_MASK, 0x0)); 1026 + regmap_write(hdptx->regmap, CMN_REG(0075), 1027 + FIELD_PREP(ANA_ROPLL_SSC_FM_DEVIATION_MASK, 0x20)); 1028 + regmap_update_bits(hdptx->regmap, CMN_REG(0076), 1029 + ANA_ROPLL_SSC_FM_FREQ_MASK, 1030 + FIELD_PREP(ANA_ROPLL_SSC_FM_FREQ_MASK, 0xc)); 1031 + 1032 + regmap_update_bits(hdptx->regmap, CMN_REG(0099), SSC_EN_MASK, 1033 + FIELD_PREP(SSC_EN_MASK, 0x0)); 1034 + } 1035 + 1036 + regmap_update_bits(hdptx->regmap, CMN_REG(0095), DP_TX_LINK_BW_MASK, 1037 + FIELD_PREP(DP_TX_LINK_BW_MASK, bw)); 1038 + 1039 + regmap_write(hdptx->grf, GRF_HDPTX_CON0, 1040 + HDPTX_I_PLL_EN << 16 | FIELD_PREP(HDPTX_I_PLL_EN, 0x1)); 1041 + 1042 + ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, 1043 + status, FIELD_GET(HDPTX_O_PLL_LOCK_DONE, status), 1044 + 50, 1000); 1045 + if (ret) { 1046 + dev_err(hdptx->dev, "Failed to get phy pll lock: %d\n", ret); 1047 + return ret; 1048 + } 1049 + 1050 + return 0; 1051 + } 1052 + 1053 + static int rk_hdptx_phy_set_lanes(struct rk_hdptx_phy *hdptx, 1054 + struct phy_configure_opts_dp *dp) 1055 + { 1056 + hdptx->lanes = dp->lanes; 1057 + 1058 + regmap_update_bits(hdptx->regmap, LNTOP_REG(0207), LANE_EN_MASK, 1059 + FIELD_PREP(LANE_EN_MASK, GENMASK(hdptx->lanes - 1, 0))); 1060 + 1061 + return 0; 1062 + } 1063 + 1064 + static void rk_hdptx_phy_set_voltage(struct rk_hdptx_phy *hdptx, 1065 + struct phy_configure_opts_dp *dp, 1066 + u8 lane) 1067 + { 1068 + const struct tx_drv_ctrl *ctrl; 1069 + u32 offset = lane * 0x400; 1070 + 1071 + switch (hdptx->link_rate) { 1072 + case 1620: 1073 + ctrl = &tx_drv_ctrl_rbr[dp->voltage[lane]][dp->pre[lane]]; 1074 + regmap_update_bits(hdptx->regmap, LANE_REG(030a) + offset, 1075 + LN_TX_JEQ_EVEN_CTRL_RBR_MASK, 1076 + FIELD_PREP(LN_TX_JEQ_EVEN_CTRL_RBR_MASK, 1077 + ctrl->tx_jeq_even_ctrl)); 1078 + regmap_update_bits(hdptx->regmap, LANE_REG(030c) + offset, 1079 + LN_TX_JEQ_ODD_CTRL_RBR_MASK, 1080 + FIELD_PREP(LN_TX_JEQ_ODD_CTRL_RBR_MASK, 1081 + ctrl->tx_jeq_odd_ctrl)); 1082 + regmap_update_bits(hdptx->regmap, LANE_REG(0311) + offset, 1083 + LN_TX_SER_40BIT_EN_RBR_MASK, 1084 + FIELD_PREP(LN_TX_SER_40BIT_EN_RBR_MASK, 0x1)); 1085 + break; 1086 + case 2700: 1087 + ctrl = &tx_drv_ctrl_hbr[dp->voltage[lane]][dp->pre[lane]]; 1088 + regmap_update_bits(hdptx->regmap, LANE_REG(030b) + offset, 1089 + LN_TX_JEQ_EVEN_CTRL_HBR_MASK, 1090 + FIELD_PREP(LN_TX_JEQ_EVEN_CTRL_HBR_MASK, 1091 + ctrl->tx_jeq_even_ctrl)); 1092 + regmap_update_bits(hdptx->regmap, LANE_REG(030d) + offset, 1093 + LN_TX_JEQ_ODD_CTRL_HBR_MASK, 1094 + FIELD_PREP(LN_TX_JEQ_ODD_CTRL_HBR_MASK, 1095 + ctrl->tx_jeq_odd_ctrl)); 1096 + regmap_update_bits(hdptx->regmap, LANE_REG(0311) + offset, 1097 + LN_TX_SER_40BIT_EN_HBR_MASK, 1098 + FIELD_PREP(LN_TX_SER_40BIT_EN_HBR_MASK, 0x1)); 1099 + break; 1100 + case 5400: 1101 + default: 1102 + ctrl = &tx_drv_ctrl_hbr2[dp->voltage[lane]][dp->pre[lane]]; 1103 + regmap_update_bits(hdptx->regmap, LANE_REG(030b) + offset, 1104 + LN_TX_JEQ_EVEN_CTRL_HBR2_MASK, 1105 + FIELD_PREP(LN_TX_JEQ_EVEN_CTRL_HBR2_MASK, 1106 + ctrl->tx_jeq_even_ctrl)); 1107 + regmap_update_bits(hdptx->regmap, LANE_REG(030d) + offset, 1108 + LN_TX_JEQ_ODD_CTRL_HBR2_MASK, 1109 + FIELD_PREP(LN_TX_JEQ_ODD_CTRL_HBR2_MASK, 1110 + ctrl->tx_jeq_odd_ctrl)); 1111 + regmap_update_bits(hdptx->regmap, LANE_REG(0311) + offset, 1112 + LN_TX_SER_40BIT_EN_HBR2_MASK, 1113 + FIELD_PREP(LN_TX_SER_40BIT_EN_HBR2_MASK, 0x1)); 1114 + break; 1115 + } 1116 + 1117 + regmap_update_bits(hdptx->regmap, LANE_REG(0303) + offset, 1118 + OVRD_LN_TX_DRV_LVL_CTRL_MASK | LN_TX_DRV_LVL_CTRL_MASK, 1119 + FIELD_PREP(OVRD_LN_TX_DRV_LVL_CTRL_MASK, 0x1) | 1120 + FIELD_PREP(LN_TX_DRV_LVL_CTRL_MASK, 1121 + ctrl->tx_drv_lvl_ctrl)); 1122 + regmap_update_bits(hdptx->regmap, LANE_REG(0304) + offset, 1123 + OVRD_LN_TX_DRV_POST_LVL_CTRL_MASK | 1124 + LN_TX_DRV_POST_LVL_CTRL_MASK, 1125 + FIELD_PREP(OVRD_LN_TX_DRV_POST_LVL_CTRL_MASK, 0x1) | 1126 + FIELD_PREP(LN_TX_DRV_POST_LVL_CTRL_MASK, 1127 + ctrl->tx_drv_post_lvl_ctrl)); 1128 + regmap_update_bits(hdptx->regmap, LANE_REG(0305) + offset, 1129 + OVRD_LN_TX_DRV_PRE_LVL_CTRL_MASK | 1130 + LN_TX_DRV_PRE_LVL_CTRL_MASK, 1131 + FIELD_PREP(OVRD_LN_TX_DRV_PRE_LVL_CTRL_MASK, 0x1) | 1132 + FIELD_PREP(LN_TX_DRV_PRE_LVL_CTRL_MASK, 1133 + ctrl->tx_drv_pre_lvl_ctrl)); 1134 + regmap_update_bits(hdptx->regmap, LANE_REG(0306) + offset, 1135 + LN_ANA_TX_DRV_IDRV_IDN_CTRL_MASK | 1136 + LN_ANA_TX_DRV_IDRV_IUP_CTRL_MASK | 1137 + LN_ANA_TX_DRV_ACCDRV_EN_MASK, 1138 + FIELD_PREP(LN_ANA_TX_DRV_IDRV_IDN_CTRL_MASK, 1139 + ctrl->ana_tx_drv_idrv_idn_ctrl) | 1140 + FIELD_PREP(LN_ANA_TX_DRV_IDRV_IUP_CTRL_MASK, 1141 + ctrl->ana_tx_drv_idrv_iup_ctrl) | 1142 + FIELD_PREP(LN_ANA_TX_DRV_ACCDRV_EN_MASK, 1143 + ctrl->ana_tx_drv_accdrv_en)); 1144 + regmap_update_bits(hdptx->regmap, LANE_REG(0307) + offset, 1145 + LN_ANA_TX_DRV_ACCDRV_POL_SEL_MASK | 1146 + LN_ANA_TX_DRV_ACCDRV_CTRL_MASK, 1147 + FIELD_PREP(LN_ANA_TX_DRV_ACCDRV_POL_SEL_MASK, 0x1) | 1148 + FIELD_PREP(LN_ANA_TX_DRV_ACCDRV_CTRL_MASK, 1149 + ctrl->ana_tx_drv_accdrv_ctrl)); 1150 + 1151 + regmap_update_bits(hdptx->regmap, LANE_REG(030a) + offset, 1152 + LN_ANA_TX_JEQ_EN_MASK, 1153 + FIELD_PREP(LN_ANA_TX_JEQ_EN_MASK, ctrl->ana_tx_jeq_en)); 1154 + 1155 + regmap_update_bits(hdptx->regmap, LANE_REG(0310) + offset, 1156 + LN_ANA_TX_SYNC_LOSS_DET_MODE_MASK, 1157 + FIELD_PREP(LN_ANA_TX_SYNC_LOSS_DET_MODE_MASK, 0x3)); 1158 + 1159 + regmap_update_bits(hdptx->regmap, LANE_REG(0316) + offset, 1160 + LN_ANA_TX_SER_VREG_GAIN_CTRL_MASK, 1161 + FIELD_PREP(LN_ANA_TX_SER_VREG_GAIN_CTRL_MASK, 0x2)); 1162 + 1163 + regmap_update_bits(hdptx->regmap, LANE_REG(031b) + offset, 1164 + LN_ANA_TX_RESERVED_MASK, 1165 + FIELD_PREP(LN_ANA_TX_RESERVED_MASK, 0x1)); 1166 + } 1167 + 1168 + static int rk_hdptx_phy_set_voltages(struct rk_hdptx_phy *hdptx, 1169 + struct phy_configure_opts_dp *dp) 1170 + { 1171 + u8 lane; 1172 + u32 status; 1173 + int ret; 1174 + 1175 + for (lane = 0; lane < hdptx->lanes; lane++) 1176 + rk_hdptx_phy_set_voltage(hdptx, dp, lane); 1177 + 1178 + reset_control_deassert(hdptx->rsts[RST_LANE].rstc); 1179 + 1180 + ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, 1181 + status, FIELD_GET(HDPTX_O_PHY_RDY, status), 1182 + 50, 5000); 1183 + if (ret) { 1184 + dev_err(hdptx->dev, "Failed to get phy ready: %d\n", ret); 1185 + return ret; 1186 + } 1187 + 1188 + return 0; 1189 + } 1190 + 1191 + static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opts) 1192 + { 1193 + struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); 1194 + enum phy_mode mode = phy_get_mode(phy); 1195 + int ret; 1196 + 1197 + if (mode != PHY_MODE_DP) 1198 + return 0; 1199 + 1200 + ret = rk_hdptx_phy_verify_config(hdptx, &opts->dp); 1201 + if (ret) { 1202 + dev_err(hdptx->dev, "invalid params for phy configure\n"); 1203 + return ret; 1204 + } 1205 + 1206 + if (opts->dp.set_rate) { 1207 + ret = rk_hdptx_phy_set_rate(hdptx, &opts->dp); 1208 + if (ret) { 1209 + dev_err(hdptx->dev, "failed to set rate: %d\n", ret); 1210 + return ret; 1211 + } 1212 + } 1213 + 1214 + if (opts->dp.set_lanes) { 1215 + ret = rk_hdptx_phy_set_lanes(hdptx, &opts->dp); 1216 + if (ret) { 1217 + dev_err(hdptx->dev, "failed to set lanes: %d\n", ret); 1218 + return ret; 1219 + } 1220 + } 1221 + 1222 + if (opts->dp.set_voltages) { 1223 + ret = rk_hdptx_phy_set_voltages(hdptx, &opts->dp); 1224 + if (ret) { 1225 + dev_err(hdptx->dev, "failed to set voltages: %d\n", 1226 + ret); 1227 + return ret; 1228 + } 1229 + } 1230 + 1231 + return 0; 1232 + } 1233 + 1506 1234 static const struct phy_ops rk_hdptx_phy_ops = { 1507 1235 .power_on = rk_hdptx_phy_power_on, 1508 1236 .power_off = rk_hdptx_phy_power_off, 1237 + .configure = rk_hdptx_phy_configure, 1509 1238 .owner = THIS_MODULE, 1510 1239 }; 1511 1240 ··· 1876 1007 struct device *dev = hdptx->dev; 1877 1008 const char *name, *pname; 1878 1009 struct clk *refclk; 1879 - int ret, id; 1010 + int ret; 1880 1011 1881 1012 refclk = devm_clk_get(dev, "ref"); 1882 1013 if (IS_ERR(refclk)) 1883 1014 return dev_err_probe(dev, PTR_ERR(refclk), 1884 1015 "Failed to get ref clock\n"); 1885 1016 1886 - id = of_alias_get_id(dev->of_node, "hdptxphy"); 1887 - name = id > 0 ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0"; 1017 + name = hdptx->phy_id > 0 ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0"; 1888 1018 pname = __clk_get_name(refclk); 1889 1019 1890 1020 hdptx->hw.init = CLK_HW_INIT(name, pname, &hdptx_phy_clk_ops, ··· 1926 1058 struct phy_provider *phy_provider; 1927 1059 struct device *dev = &pdev->dev; 1928 1060 struct rk_hdptx_phy *hdptx; 1061 + struct resource *res; 1929 1062 void __iomem *regs; 1930 - int ret; 1063 + int ret, id; 1931 1064 1932 1065 hdptx = devm_kzalloc(dev, sizeof(*hdptx), GFP_KERNEL); 1933 1066 if (!hdptx) ··· 1936 1067 1937 1068 hdptx->dev = dev; 1938 1069 1939 - regs = devm_platform_ioremap_resource(pdev, 0); 1070 + regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 1940 1071 if (IS_ERR(regs)) 1941 1072 return dev_err_probe(dev, PTR_ERR(regs), 1942 1073 "Failed to ioremap resource\n"); 1074 + 1075 + hdptx->cfgs = device_get_match_data(dev); 1076 + if (!hdptx->cfgs) 1077 + return dev_err_probe(dev, -EINVAL, "missing match data\n"); 1078 + 1079 + /* find the phy-id from the io address */ 1080 + hdptx->phy_id = -ENODEV; 1081 + for (id = 0; id < hdptx->cfgs->num_phys; id++) { 1082 + if (res->start == hdptx->cfgs->phy_ids[id]) { 1083 + hdptx->phy_id = id; 1084 + break; 1085 + } 1086 + } 1087 + 1088 + if (hdptx->phy_id < 0) 1089 + return dev_err_probe(dev, -ENODEV, "no matching device found\n"); 1943 1090 1944 1091 ret = devm_clk_bulk_get_all(dev, &hdptx->clks); 1945 1092 if (ret < 0) ··· 2017 1132 rk_hdptx_phy_runtime_resume, NULL) 2018 1133 }; 2019 1134 1135 + static const struct rk_hdptx_phy_cfg rk3576_hdptx_phy_cfgs = { 1136 + .num_phys = 1, 1137 + .phy_ids = { 1138 + 0x2b000000, 1139 + }, 1140 + }; 1141 + 1142 + static const struct rk_hdptx_phy_cfg rk3588_hdptx_phy_cfgs = { 1143 + .num_phys = 2, 1144 + .phy_ids = { 1145 + 0xfed60000, 1146 + 0xfed70000, 1147 + }, 1148 + }; 1149 + 2020 1150 static const struct of_device_id rk_hdptx_phy_of_match[] = { 2021 - { .compatible = "rockchip,rk3588-hdptx-phy", }, 1151 + { 1152 + .compatible = "rockchip,rk3576-hdptx-phy", 1153 + .data = &rk3576_hdptx_phy_cfgs 1154 + }, 1155 + { 1156 + .compatible = "rockchip,rk3588-hdptx-phy", 1157 + .data = &rk3588_hdptx_phy_cfgs 1158 + }, 2022 1159 {} 2023 1160 }; 2024 1161 MODULE_DEVICE_TABLE(of, rk_hdptx_phy_of_match); ··· 2057 1150 2058 1151 MODULE_AUTHOR("Algea Cao <algea.cao@rock-chips.com>"); 2059 1152 MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@collabora.com>"); 1153 + MODULE_AUTHOR("Damon Ding <damon.ding@rock-chips.com>"); 2060 1154 MODULE_DESCRIPTION("Samsung HDMI/eDP Transmitter Combo PHY Driver"); 2061 1155 MODULE_LICENSE("GPL");
+63 -45
drivers/phy/rockchip/phy-rockchip-usbdp.c
··· 187 187 u32 dp_aux_din_sel; 188 188 bool dp_sink_hpd_sel; 189 189 bool dp_sink_hpd_cfg; 190 + unsigned int link_rate; 191 + unsigned int lanes; 190 192 u8 bw; 191 193 int id; 192 194 ··· 980 978 981 979 if (device_property_present(dev, "maximum-speed")) { 982 980 maximum_speed = usb_get_maximum_speed(dev); 983 - udphy->hs = maximum_speed <= USB_SPEED_HIGH ? true : false; 981 + udphy->hs = maximum_speed <= USB_SPEED_HIGH; 984 982 } 985 983 986 984 ret = rk_udphy_clk_init(udphy, dev); ··· 1047 1045 mutex_lock(&udphy->mutex); 1048 1046 1049 1047 udphy->dp_in_use = true; 1050 - rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg); 1051 1048 1052 1049 mutex_unlock(&udphy->mutex); 1053 1050 ··· 1104 1103 return 0; 1105 1104 } 1106 1105 1107 - static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate) 1106 + /* 1107 + * Verify link rate 1108 + */ 1109 + static int rk_udphy_dp_phy_verify_link_rate(struct rk_udphy *udphy, 1110 + struct phy_configure_opts_dp *dp) 1108 1111 { 1109 - switch (link_rate) { 1112 + switch (dp->link_rate) { 1110 1113 case 1620: 1111 1114 case 2700: 1112 1115 case 5400: 1113 1116 case 8100: 1117 + udphy->link_rate = dp->link_rate; 1118 + break; 1119 + default: 1120 + return -EINVAL; 1121 + } 1122 + 1123 + return 0; 1124 + } 1125 + 1126 + static int rk_udphy_dp_phy_verify_lanes(struct rk_udphy *udphy, 1127 + struct phy_configure_opts_dp *dp) 1128 + { 1129 + switch (dp->lanes) { 1130 + case 1: 1131 + case 2: 1132 + case 4: 1133 + /* valid lane count. */ 1134 + udphy->lanes = dp->lanes; 1114 1135 break; 1115 1136 1116 1137 default: ··· 1142 1119 return 0; 1143 1120 } 1144 1121 1145 - static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy, 1146 - struct phy_configure_opts_dp *dp) 1122 + /* 1123 + * If changing voltages is required, check swing and pre-emphasis 1124 + * levels, per-lane. 1125 + */ 1126 + static int rk_udphy_dp_phy_verify_voltages(struct rk_udphy *udphy, 1127 + struct phy_configure_opts_dp *dp) 1147 1128 { 1148 - int i, ret; 1129 + int i; 1149 1130 1150 - /* If changing link rate was required, verify it's supported. */ 1151 - ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate); 1152 - if (ret) 1153 - return ret; 1131 + /* Lane count verified previously. */ 1132 + for (i = 0; i < udphy->lanes; i++) { 1133 + if (dp->voltage[i] > 3 || dp->pre[i] > 3) 1134 + return -EINVAL; 1154 1135 1155 - /* Verify lane count. */ 1156 - switch (dp->lanes) { 1157 - case 1: 1158 - case 2: 1159 - case 4: 1160 - /* valid lane count. */ 1161 - break; 1162 - 1163 - default: 1164 - return -EINVAL; 1165 - } 1166 - 1167 - /* 1168 - * If changing voltages is required, check swing and pre-emphasis 1169 - * levels, per-lane. 1170 - */ 1171 - if (dp->set_voltages) { 1172 - /* Lane count verified previously. */ 1173 - for (i = 0; i < dp->lanes; i++) { 1174 - if (dp->voltage[i] > 3 || dp->pre[i] > 3) 1175 - return -EINVAL; 1176 - 1177 - /* 1178 - * Sum of voltage swing and pre-emphasis levels cannot 1179 - * exceed 3. 1180 - */ 1181 - if (dp->voltage[i] + dp->pre[i] > 3) 1182 - return -EINVAL; 1183 - } 1136 + /* 1137 + * Sum of voltage swing and pre-emphasis levels cannot 1138 + * exceed 3. 1139 + */ 1140 + if (dp->voltage[i] + dp->pre[i] > 3) 1141 + return -EINVAL; 1184 1142 } 1185 1143 1186 1144 return 0; ··· 1201 1197 u32 i, val, lane; 1202 1198 int ret; 1203 1199 1204 - ret = rk_udphy_dp_phy_verify_config(udphy, dp); 1205 - if (ret) 1206 - return ret; 1200 + if (dp->set_rate) { 1201 + ret = rk_udphy_dp_phy_verify_link_rate(udphy, dp); 1202 + if (ret) 1203 + return ret; 1204 + } 1205 + 1206 + if (dp->set_lanes) { 1207 + ret = rk_udphy_dp_phy_verify_lanes(udphy, dp); 1208 + if (ret) 1209 + return ret; 1210 + } 1211 + 1212 + if (dp->set_voltages) { 1213 + ret = rk_udphy_dp_phy_verify_voltages(udphy, dp); 1214 + if (ret) 1215 + return ret; 1216 + } 1207 1217 1208 1218 if (dp->set_rate) { 1209 1219 regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, ··· 1262 1244 } 1263 1245 1264 1246 if (dp->set_voltages) { 1265 - for (i = 0; i < dp->lanes; i++) { 1247 + for (i = 0; i < udphy->lanes; i++) { 1266 1248 lane = udphy->dp_lane_sel[i]; 1267 - switch (dp->link_rate) { 1249 + switch (udphy->link_rate) { 1268 1250 case 1620: 1269 1251 case 2700: 1270 1252 regmap_update_bits(udphy->pma_regmap,
+1
drivers/phy/samsung/Kconfig
··· 81 81 tristate "Exynos5 SoC series USB DRD PHY driver" 82 82 depends on (ARCH_EXYNOS && OF) || COMPILE_TEST 83 83 depends on HAS_IOMEM 84 + depends on TYPEC || !TYPEC 84 85 depends on USB_DWC3_EXYNOS 85 86 select GENERIC_PHY 86 87 select MFD_SYSCON
+1
drivers/phy/samsung/Makefile
··· 7 7 phy-exynos-ufs-y += phy-samsung-ufs.o 8 8 phy-exynos-ufs-y += phy-exynos7-ufs.o 9 9 phy-exynos-ufs-y += phy-exynosautov9-ufs.o 10 + phy-exynos-ufs-y += phy-exynosautov920-ufs.o 10 11 phy-exynos-ufs-y += phy-fsd-ufs.o 11 12 obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o 12 13 phy-exynos-usb2-y += phy-samsung-usb2.o
+161 -41
drivers/phy/samsung/phy-exynos5-usbdrd.c
··· 23 23 #include <linux/regmap.h> 24 24 #include <linux/regulator/consumer.h> 25 25 #include <linux/soc/samsung/exynos-regs-pmu.h> 26 + #include <linux/usb/typec.h> 27 + #include <linux/usb/typec_mux.h> 26 28 27 29 /* Exynos USB PHY registers */ 28 30 #define EXYNOS5_FSEL_9MHZ6 0x0 ··· 211 209 212 210 #define EXYNOS9_PMA_USBDP_CMN_REG00B8 0x02e0 213 211 #define CMN_REG00B8_LANE_MUX_SEL_DP GENMASK(3, 0) 212 + #define CMN_REG00B8_LANE_MUX_SEL_DP_LANE3 BIT(3) 213 + #define CMN_REG00B8_LANE_MUX_SEL_DP_LANE2 BIT(2) 214 + #define CMN_REG00B8_LANE_MUX_SEL_DP_LANE1 BIT(1) 215 + #define CMN_REG00B8_LANE_MUX_SEL_DP_LANE0 BIT(0) 214 216 215 217 #define EXYNOS9_PMA_USBDP_CMN_REG01C0 0x0700 216 218 #define CMN_REG01C0_ANA_LCPLL_LOCK_DONE BIT(7) ··· 389 383 * @clks: clocks for register access 390 384 * @core_clks: core clocks for phy (ref, pipe3, utmi+, ITP, etc. as required) 391 385 * @drv_data: pointer to SoC level driver data structure 386 + * @phy_mutex: mutex protecting phy_init/exit & TCPC callbacks 392 387 * @phys: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY 393 388 * instances each with its 'phy' and 'phy_cfg'. 394 389 * @extrefclk: frequency select settings when using 'separate 395 390 * reference clocks' for SS and HS operations 396 391 * @regulators: regulators for phy 392 + * @sw: TypeC orientation switch handle 393 + * @orientation: TypeC connector orientation - normal or flipped 397 394 */ 398 395 struct exynos5_usbdrd_phy { 399 396 struct device *dev; ··· 406 397 struct clk_bulk_data *clks; 407 398 struct clk_bulk_data *core_clks; 408 399 const struct exynos5_usbdrd_phy_drvdata *drv_data; 400 + struct mutex phy_mutex; 409 401 struct phy_usb_instance { 410 402 struct phy *phy; 411 403 u32 index; ··· 416 406 } phys[EXYNOS5_DRDPHYS_NUM]; 417 407 u32 extrefclk; 418 408 struct regulator_bulk_data *regulators; 409 + 410 + struct typec_switch_dev *sw; 411 + enum typec_orientation orientation; 419 412 }; 420 413 421 414 static inline ··· 660 647 /* lane configuration: USB on all lanes */ 661 648 reg = readl(regs_base + EXYNOS9_PMA_USBDP_CMN_REG00B8); 662 649 reg &= ~CMN_REG00B8_LANE_MUX_SEL_DP; 650 + /* 651 + * USB on lanes 0 & 1 in normal mode, or 2 & 3 if reversed, DP on the 652 + * other ones. 653 + */ 654 + reg |= FIELD_PREP(CMN_REG00B8_LANE_MUX_SEL_DP, 655 + ((phy_drd->orientation == TYPEC_ORIENTATION_NORMAL) 656 + ? (CMN_REG00B8_LANE_MUX_SEL_DP_LANE3 657 + | CMN_REG00B8_LANE_MUX_SEL_DP_LANE2) 658 + : (CMN_REG00B8_LANE_MUX_SEL_DP_LANE1 659 + | CMN_REG00B8_LANE_MUX_SEL_DP_LANE0))); 663 660 writel(reg, regs_base + EXYNOS9_PMA_USBDP_CMN_REG00B8); 664 661 665 - /* 666 - * FIXME: below code supports one connector orientation only. It needs 667 - * updating once we can receive connector events. 668 - */ 669 662 /* override of TX receiver detector and comparator: lane 1 */ 670 663 reg = readl(regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0413); 671 - reg &= ~TRSV_REG0413_OVRD_LN1_TX_RXD_COMP_EN; 672 - reg &= ~TRSV_REG0413_OVRD_LN1_TX_RXD_EN; 664 + if (phy_drd->orientation == TYPEC_ORIENTATION_NORMAL) { 665 + reg &= ~TRSV_REG0413_OVRD_LN1_TX_RXD_COMP_EN; 666 + reg &= ~TRSV_REG0413_OVRD_LN1_TX_RXD_EN; 667 + } else { 668 + reg |= TRSV_REG0413_OVRD_LN1_TX_RXD_COMP_EN; 669 + reg |= TRSV_REG0413_OVRD_LN1_TX_RXD_EN; 670 + } 673 671 writel(reg, regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0413); 674 672 675 673 /* lane 3 */ 676 674 reg = readl(regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0813); 677 - reg |= TRSV_REG0813_OVRD_LN3_TX_RXD_COMP_EN; 678 - reg |= TRSV_REG0813_OVRD_LN3_TX_RXD_EN; 675 + if (phy_drd->orientation == TYPEC_ORIENTATION_NORMAL) { 676 + reg |= TRSV_REG0813_OVRD_LN3_TX_RXD_COMP_EN; 677 + reg |= TRSV_REG0813_OVRD_LN3_TX_RXD_EN; 678 + } else { 679 + reg &= ~TRSV_REG0813_OVRD_LN3_TX_RXD_COMP_EN; 680 + reg &= ~TRSV_REG0813_OVRD_LN3_TX_RXD_EN; 681 + } 679 682 writel(reg, regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0813); 680 683 } 681 684 ··· 729 700 int err; 730 701 731 702 err = readl_poll_timeout( 732 - phy_drd->reg_pma + EXYNOS9_PMA_USBDP_TRSV_REG03C3, 733 - reg, (reg & locked) == locked, sleep_us, timeout_us); 734 - if (!err) 735 - return; 736 - 737 - dev_err(phy_drd->dev, 738 - "timed out waiting for CDR lock (l0): %#.8x, retrying\n", reg); 739 - 740 - /* based on cable orientation, this might be on the other phy port */ 741 - err = readl_poll_timeout( 742 - phy_drd->reg_pma + EXYNOS9_PMA_USBDP_TRSV_REG07C3, 703 + /* lane depends on cable orientation */ 704 + (phy_drd->reg_pma 705 + + ((phy_drd->orientation == TYPEC_ORIENTATION_NORMAL) 706 + ? EXYNOS9_PMA_USBDP_TRSV_REG03C3 707 + : EXYNOS9_PMA_USBDP_TRSV_REG07C3)), 743 708 reg, (reg & locked) == locked, sleep_us, timeout_us); 744 709 if (err) 745 710 dev_err(phy_drd->dev, 746 - "timed out waiting for CDR lock (l2): %#.8x\n", reg); 711 + "timed out waiting for CDR(l%d) lock: %#.8x\n", 712 + ((phy_drd->orientation == TYPEC_ORIENTATION_NORMAL) 713 + ? 0 714 + : 2), reg); 747 715 } 748 716 749 717 static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd) ··· 1137 1111 reg |= LINKCTRL_BUS_FILTER_BYPASS(0xf); 1138 1112 writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL); 1139 1113 1140 - reg = readl(regs_base + EXYNOS850_DRD_UTMI); 1141 - reg |= UTMI_FORCE_BVALID | UTMI_FORCE_VBUSVALID; 1142 - writel(reg, regs_base + EXYNOS850_DRD_UTMI); 1114 + if (!phy_drd->sw) { 1115 + reg = readl(regs_base + EXYNOS850_DRD_UTMI); 1116 + reg |= UTMI_FORCE_BVALID | UTMI_FORCE_VBUSVALID; 1117 + writel(reg, regs_base + EXYNOS850_DRD_UTMI); 1143 1118 1144 - reg = readl(regs_base + EXYNOS850_DRD_HSP); 1145 - reg |= HSP_VBUSVLDEXT | HSP_VBUSVLDEXTSEL; 1146 - writel(reg, regs_base + EXYNOS850_DRD_HSP); 1119 + reg = readl(regs_base + EXYNOS850_DRD_HSP); 1120 + reg |= HSP_VBUSVLDEXT | HSP_VBUSVLDEXTSEL; 1121 + writel(reg, regs_base + EXYNOS850_DRD_HSP); 1122 + } 1147 1123 1148 1124 reg = readl(regs_base + EXYNOS850_DRD_SSPPLLCTL); 1149 1125 reg &= ~SSPPLLCTL_FSEL; ··· 1212 1184 return ret; 1213 1185 1214 1186 /* UTMI or PIPE3 specific init */ 1215 - inst->phy_cfg->phy_init(phy_drd); 1187 + scoped_guard(mutex, &phy_drd->phy_mutex) 1188 + inst->phy_cfg->phy_init(phy_drd); 1216 1189 1217 1190 clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks); 1218 1191 ··· 1231 1202 ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks); 1232 1203 if (ret) 1233 1204 return ret; 1205 + 1206 + guard(mutex)(&phy_drd->phy_mutex); 1234 1207 1235 1208 /* Set PHY clock and control HS PHY */ 1236 1209 reg = readl(regs_base + EXYNOS850_DRD_UTMI); ··· 1405 1374 return 0; 1406 1375 } 1407 1376 1377 + static int exynos5_usbdrd_orien_sw_set(struct typec_switch_dev *sw, 1378 + enum typec_orientation orientation) 1379 + { 1380 + struct exynos5_usbdrd_phy *phy_drd = typec_switch_get_drvdata(sw); 1381 + int ret; 1382 + 1383 + ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks); 1384 + if (ret) { 1385 + dev_err(phy_drd->dev, "Failed to enable PHY clocks(s)\n"); 1386 + return ret; 1387 + } 1388 + 1389 + scoped_guard(mutex, &phy_drd->phy_mutex) { 1390 + void __iomem * const regs_base = phy_drd->reg_phy; 1391 + unsigned int reg; 1392 + 1393 + if (orientation == TYPEC_ORIENTATION_NONE) { 1394 + reg = readl(regs_base + EXYNOS850_DRD_UTMI); 1395 + reg &= ~(UTMI_FORCE_VBUSVALID | UTMI_FORCE_BVALID); 1396 + writel(reg, regs_base + EXYNOS850_DRD_UTMI); 1397 + 1398 + reg = readl(regs_base + EXYNOS850_DRD_HSP); 1399 + reg |= HSP_VBUSVLDEXTSEL; 1400 + reg &= ~HSP_VBUSVLDEXT; 1401 + writel(reg, regs_base + EXYNOS850_DRD_HSP); 1402 + } else { 1403 + reg = readl(regs_base + EXYNOS850_DRD_UTMI); 1404 + reg |= UTMI_FORCE_VBUSVALID | UTMI_FORCE_BVALID; 1405 + writel(reg, regs_base + EXYNOS850_DRD_UTMI); 1406 + 1407 + reg = readl(regs_base + EXYNOS850_DRD_HSP); 1408 + reg |= HSP_VBUSVLDEXTSEL | HSP_VBUSVLDEXT; 1409 + writel(reg, regs_base + EXYNOS850_DRD_HSP); 1410 + } 1411 + 1412 + phy_drd->orientation = orientation; 1413 + } 1414 + 1415 + clk_bulk_disable(phy_drd->drv_data->n_clks, phy_drd->clks); 1416 + 1417 + return 0; 1418 + } 1419 + 1420 + static void exynos5_usbdrd_orien_switch_unregister(void *data) 1421 + { 1422 + struct exynos5_usbdrd_phy *phy_drd = data; 1423 + 1424 + typec_switch_unregister(phy_drd->sw); 1425 + } 1426 + 1427 + static int exynos5_usbdrd_setup_notifiers(struct exynos5_usbdrd_phy *phy_drd) 1428 + { 1429 + int ret; 1430 + 1431 + if (!IS_ENABLED(CONFIG_TYPEC)) 1432 + return 0; 1433 + 1434 + if (device_property_present(phy_drd->dev, "orientation-switch")) { 1435 + struct typec_switch_desc sw_desc = { }; 1436 + 1437 + sw_desc.drvdata = phy_drd; 1438 + sw_desc.fwnode = dev_fwnode(phy_drd->dev); 1439 + sw_desc.set = exynos5_usbdrd_orien_sw_set; 1440 + 1441 + phy_drd->sw = typec_switch_register(phy_drd->dev, &sw_desc); 1442 + if (IS_ERR(phy_drd->sw)) 1443 + return dev_err_probe(phy_drd->dev, 1444 + PTR_ERR(phy_drd->sw), 1445 + "Failed to register TypeC orientation switch\n"); 1446 + 1447 + ret = devm_add_action_or_reset(phy_drd->dev, 1448 + exynos5_usbdrd_orien_switch_unregister, 1449 + phy_drd); 1450 + if (ret) 1451 + return dev_err_probe(phy_drd->dev, ret, 1452 + "Failed to register TypeC orientation devm action\n"); 1453 + } 1454 + 1455 + return 0; 1456 + } 1457 + 1408 1458 static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { 1409 1459 { 1410 1460 .id = EXYNOS5_DRDPHY_UTMI, ··· 1625 1513 PHY_TUNING_ENTRY_PMA(0x09e0, -1, 0x00), 1626 1514 PHY_TUNING_ENTRY_PMA(0x09e4, -1, 0x36), 1627 1515 PHY_TUNING_ENTRY_PMA(0x1e7c, -1, 0x06), 1628 - PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x00), 1629 - PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x36), 1516 + PHY_TUNING_ENTRY_PMA(0x19e0, -1, 0x00), 1517 + PHY_TUNING_ENTRY_PMA(0x19e4, -1, 0x36), 1518 + /* fix bootloader bug */ 1519 + PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x02), 1520 + PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x0b), 1630 1521 /* improve LVCC */ 1631 1522 PHY_TUNING_ENTRY_PMA(0x08f0, -1, 0x30), 1632 1523 PHY_TUNING_ENTRY_PMA(0x18f0, -1, 0x30), ··· 1813 1698 return -EINVAL; 1814 1699 phy_drd->drv_data = drv_data; 1815 1700 1701 + ret = devm_mutex_init(dev, &phy_drd->phy_mutex); 1702 + if (ret) 1703 + return ret; 1704 + 1816 1705 if (of_property_present(dev->of_node, "reg-names")) { 1817 1706 void __iomem *reg; 1818 1707 ··· 1847 1728 1848 1729 reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, 1849 1730 "samsung,pmu-syscon"); 1850 - if (IS_ERR(reg_pmu)) { 1851 - dev_err(dev, "Failed to lookup PMU regmap\n"); 1852 - return PTR_ERR(reg_pmu); 1853 - } 1731 + if (IS_ERR(reg_pmu)) 1732 + return dev_err_probe(dev, PTR_ERR(reg_pmu), 1733 + "Failed to lookup PMU regmap\n"); 1854 1734 1855 1735 /* 1856 1736 * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with ··· 1875 1757 if (ret) 1876 1758 return dev_err_probe(dev, ret, "failed to get regulators\n"); 1877 1759 1760 + ret = exynos5_usbdrd_setup_notifiers(phy_drd); 1761 + if (ret) 1762 + return ret; 1763 + 1878 1764 dev_vdbg(dev, "Creating usbdrd_phy phy\n"); 1879 1765 1880 1766 for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) { 1881 1767 struct phy *phy = devm_phy_create(dev, NULL, drv_data->phy_ops); 1882 1768 1883 - if (IS_ERR(phy)) { 1884 - dev_err(dev, "Failed to create usbdrd_phy phy\n"); 1885 - return PTR_ERR(phy); 1886 - } 1769 + if (IS_ERR(phy)) 1770 + return dev_err_probe(dev, PTR_ERR(phy), 1771 + "Failed to create usbdrd_phy phy\n"); 1887 1772 1888 1773 phy_drd->phys[i].phy = phy; 1889 1774 phy_drd->phys[i].index = i; ··· 1910 1789 1911 1790 phy_provider = devm_of_phy_provider_register(dev, 1912 1791 exynos5_usbdrd_phy_xlate); 1913 - if (IS_ERR(phy_provider)) { 1914 - dev_err(phy_drd->dev, "Failed to register phy provider\n"); 1915 - return PTR_ERR(phy_provider); 1916 - } 1792 + if (IS_ERR(phy_provider)) 1793 + return dev_err_probe(phy_drd->dev, PTR_ERR(phy_provider), 1794 + "Failed to register phy provider\n"); 1917 1795 1918 1796 return 0; 1919 1797 }
+168
drivers/phy/samsung/phy-exynosautov920-ufs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * UFS PHY driver data for Samsung ExynosAuto v920 SoC 4 + * 5 + * Copyright (C) 2024 Samsung Electronics Co., Ltd. 6 + */ 7 + 8 + #include "phy-samsung-ufs.h" 9 + 10 + #define EXYNOSAUTOV920_EMBEDDED_COMBO_PHY_CTRL 0x708 11 + #define EXYNOSAUTOV920_EMBEDDED_COMBO_PHY_CTRL_MASK 0x1 12 + #define EXYNOSAUTOV920_EMBEDDED_COMBO_PHY_CTRL_EN BIT(0) 13 + #define EXYNOSAUTOV920_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS 0x5e 14 + 15 + #define EXYNOSAUTOV920_CDR_LOCK_OFFSET 0xce4 16 + 17 + #define PHY_EXYNOSAUTOV920_LANE_OFFSET 0x200 18 + #define PHY_TRSV_REG_CFG_AUTOV920(o, v, d) \ 19 + PHY_TRSV_REG_CFG_OFFSET(o, v, d, PHY_EXYNOSAUTOV920_LANE_OFFSET) 20 + 21 + /* Calibration for phy initialization */ 22 + static const struct samsung_ufs_phy_cfg exynosautov920_pre_init_cfg[] = { 23 + PHY_COMN_REG_CFG(0x29, 0x22, PWR_MODE_ANY), 24 + PHY_COMN_REG_CFG(0x43, 0x10, PWR_MODE_ANY), 25 + PHY_COMN_REG_CFG(0x3c, 0x14, PWR_MODE_ANY), 26 + PHY_COMN_REG_CFG(0x46, 0x48, PWR_MODE_ANY), 27 + PHY_COMN_REG_CFG(0x04, 0x95, PWR_MODE_ANY), 28 + PHY_COMN_REG_CFG(0x06, 0x30, PWR_MODE_ANY), 29 + 30 + PHY_TRSV_REG_CFG_AUTOV920(0x200, 0x00, PWR_MODE_ANY), 31 + PHY_TRSV_REG_CFG_AUTOV920(0x201, 0x06, PWR_MODE_ANY), 32 + PHY_TRSV_REG_CFG_AUTOV920(0x202, 0x06, PWR_MODE_ANY), 33 + PHY_TRSV_REG_CFG_AUTOV920(0x203, 0x0a, PWR_MODE_ANY), 34 + PHY_TRSV_REG_CFG_AUTOV920(0x204, 0x00, PWR_MODE_ANY), 35 + PHY_TRSV_REG_CFG_AUTOV920(0x205, 0x10, PWR_MODE_ANY), 36 + PHY_TRSV_REG_CFG_AUTOV920(0x207, 0x0c, PWR_MODE_ANY), 37 + PHY_TRSV_REG_CFG_AUTOV920(0x2e1, 0xc0, PWR_MODE_ANY), 38 + PHY_TRSV_REG_CFG_AUTOV920(0x22d, 0xf8, PWR_MODE_ANY), 39 + PHY_TRSV_REG_CFG_AUTOV920(0x234, 0x60, PWR_MODE_ANY), 40 + PHY_TRSV_REG_CFG_AUTOV920(0x238, 0x13, PWR_MODE_ANY), 41 + PHY_TRSV_REG_CFG_AUTOV920(0x239, 0x48, PWR_MODE_ANY), 42 + PHY_TRSV_REG_CFG_AUTOV920(0x23a, 0x01, PWR_MODE_ANY), 43 + PHY_TRSV_REG_CFG_AUTOV920(0x23b, 0x29, PWR_MODE_ANY), 44 + PHY_TRSV_REG_CFG_AUTOV920(0x23c, 0x2a, PWR_MODE_ANY), 45 + PHY_TRSV_REG_CFG_AUTOV920(0x23d, 0x01, PWR_MODE_ANY), 46 + PHY_TRSV_REG_CFG_AUTOV920(0x23e, 0x14, PWR_MODE_ANY), 47 + PHY_TRSV_REG_CFG_AUTOV920(0x23f, 0x13, PWR_MODE_ANY), 48 + 49 + PHY_TRSV_REG_CFG_AUTOV920(0x240, 0x4a, PWR_MODE_ANY), 50 + PHY_TRSV_REG_CFG_AUTOV920(0x243, 0x40, PWR_MODE_ANY), 51 + PHY_TRSV_REG_CFG_AUTOV920(0x244, 0x02, PWR_MODE_ANY), 52 + PHY_TRSV_REG_CFG_AUTOV920(0x25d, 0x00, PWR_MODE_ANY), 53 + PHY_TRSV_REG_CFG_AUTOV920(0x25e, 0x3f, PWR_MODE_ANY), 54 + PHY_TRSV_REG_CFG_AUTOV920(0x25f, 0xff, PWR_MODE_ANY), 55 + PHY_TRSV_REG_CFG_AUTOV920(0x26f, 0xf0, PWR_MODE_ANY), 56 + PHY_TRSV_REG_CFG_AUTOV920(0x273, 0x33, PWR_MODE_ANY), 57 + PHY_TRSV_REG_CFG_AUTOV920(0x274, 0x50, PWR_MODE_ANY), 58 + 59 + PHY_TRSV_REG_CFG_AUTOV920(0x284, 0x02, PWR_MODE_ANY), 60 + PHY_TRSV_REG_CFG_AUTOV920(0x285, 0x02, PWR_MODE_ANY), 61 + PHY_TRSV_REG_CFG_AUTOV920(0x2a2, 0x04, PWR_MODE_ANY), 62 + PHY_TRSV_REG_CFG_AUTOV920(0x27d, 0x01, PWR_MODE_ANY), 63 + PHY_TRSV_REG_CFG_AUTOV920(0x2fa, 0x01, PWR_MODE_ANY), 64 + 65 + PHY_TRSV_REG_CFG_AUTOV920(0x286, 0x03, PWR_MODE_ANY), 66 + PHY_TRSV_REG_CFG_AUTOV920(0x287, 0x03, PWR_MODE_ANY), 67 + PHY_TRSV_REG_CFG_AUTOV920(0x288, 0x03, PWR_MODE_ANY), 68 + PHY_TRSV_REG_CFG_AUTOV920(0x289, 0x03, PWR_MODE_ANY), 69 + PHY_TRSV_REG_CFG_AUTOV920(0x2b3, 0x04, PWR_MODE_ANY), 70 + PHY_TRSV_REG_CFG_AUTOV920(0x2b6, 0x0b, PWR_MODE_ANY), 71 + PHY_TRSV_REG_CFG_AUTOV920(0x2b7, 0x0b, PWR_MODE_ANY), 72 + PHY_TRSV_REG_CFG_AUTOV920(0x2b8, 0x0b, PWR_MODE_ANY), 73 + PHY_TRSV_REG_CFG_AUTOV920(0x2b9, 0x0b, PWR_MODE_ANY), 74 + PHY_TRSV_REG_CFG_AUTOV920(0x2ba, 0x0b, PWR_MODE_ANY), 75 + PHY_TRSV_REG_CFG_AUTOV920(0x2bb, 0x06, PWR_MODE_ANY), 76 + PHY_TRSV_REG_CFG_AUTOV920(0x2bc, 0x06, PWR_MODE_ANY), 77 + PHY_TRSV_REG_CFG_AUTOV920(0x2bd, 0x06, PWR_MODE_ANY), 78 + PHY_TRSV_REG_CFG_AUTOV920(0x2be, 0x06, PWR_MODE_ANY), 79 + PHY_TRSV_REG_CFG_AUTOV920(0x34b, 0x01, PWR_MODE_ANY), 80 + PHY_TRSV_REG_CFG_AUTOV920(0x34c, 0x24, PWR_MODE_ANY), 81 + PHY_TRSV_REG_CFG_AUTOV920(0x34d, 0x23, PWR_MODE_ANY), 82 + PHY_TRSV_REG_CFG_AUTOV920(0x34e, 0x45, PWR_MODE_ANY), 83 + PHY_TRSV_REG_CFG_AUTOV920(0x34f, 0x00, PWR_MODE_ANY), 84 + PHY_TRSV_REG_CFG_AUTOV920(0x350, 0x31, PWR_MODE_ANY), 85 + PHY_TRSV_REG_CFG_AUTOV920(0x351, 0x00, PWR_MODE_ANY), 86 + PHY_TRSV_REG_CFG_AUTOV920(0x352, 0x02, PWR_MODE_ANY), 87 + PHY_TRSV_REG_CFG_AUTOV920(0x353, 0x00, PWR_MODE_ANY), 88 + PHY_TRSV_REG_CFG_AUTOV920(0x354, 0x01, PWR_MODE_ANY), 89 + 90 + PHY_COMN_REG_CFG(0x43, 0x18, PWR_MODE_ANY), 91 + PHY_COMN_REG_CFG(0x43, 0x00, PWR_MODE_ANY), 92 + 93 + END_UFS_PHY_CFG, 94 + }; 95 + 96 + /* Calibration for HS mode series A/B */ 97 + static const struct samsung_ufs_phy_cfg exynosautov920_pre_pwr_hs_cfg[] = { 98 + PHY_TRSV_REG_CFG_AUTOV920(0x369, 0x11, PWR_MODE_ANY), 99 + PHY_TRSV_REG_CFG_AUTOV920(0x246, 0x03, PWR_MODE_ANY), 100 + 101 + END_UFS_PHY_CFG, 102 + }; 103 + 104 + static const struct samsung_ufs_phy_cfg exynosautov920_post_pwr_hs_cfg[] = { 105 + END_UFS_PHY_CFG, 106 + }; 107 + 108 + #define DELAY_IN_US 40 109 + #define RETRY_CNT 100 110 + #define EXYNOSAUTOV920_CDR_LOCK_MASK 0x8 111 + 112 + int exynosautov920_ufs_phy_wait_cdr_lock(struct phy *phy, u8 lane) 113 + { 114 + struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy); 115 + u32 reg, i; 116 + 117 + struct samsung_ufs_phy_cfg cfg[4] = { 118 + PHY_TRSV_REG_CFG_AUTOV920(0x222, 0x10, PWR_MODE_ANY), 119 + PHY_TRSV_REG_CFG_AUTOV920(0x222, 0x18, PWR_MODE_ANY), 120 + PHY_TRSV_REG_CFG_AUTOV920(0x246, 0x01, PWR_MODE_ANY), 121 + END_UFS_PHY_CFG, 122 + }; 123 + 124 + for (i = 0; i < RETRY_CNT; i++) { 125 + udelay(DELAY_IN_US); 126 + 127 + reg = readl(ufs_phy->reg_pma + EXYNOSAUTOV920_CDR_LOCK_OFFSET + 128 + (PHY_APB_ADDR(PHY_EXYNOSAUTOV920_LANE_OFFSET) * lane)); 129 + 130 + if ((reg & EXYNOSAUTOV920_CDR_LOCK_MASK) 131 + == EXYNOSAUTOV920_CDR_LOCK_MASK) { 132 + samsung_ufs_phy_config(ufs_phy, &cfg[2], lane); 133 + return 0; 134 + } 135 + 136 + udelay(DELAY_IN_US); 137 + 138 + /* Disable and enable CDR */ 139 + samsung_ufs_phy_config(ufs_phy, &cfg[0], lane); 140 + samsung_ufs_phy_config(ufs_phy, &cfg[1], lane); 141 + } 142 + 143 + dev_err(ufs_phy->dev, "failed to get phy cdr lock\n"); 144 + return -ETIMEDOUT; 145 + } 146 + 147 + static const struct samsung_ufs_phy_cfg *exynosautov920_ufs_phy_cfgs[CFG_TAG_MAX] = { 148 + [CFG_PRE_INIT] = exynosautov920_pre_init_cfg, 149 + [CFG_PRE_PWR_HS] = exynosautov920_pre_pwr_hs_cfg, 150 + [CFG_POST_PWR_HS] = exynosautov920_post_pwr_hs_cfg, 151 + }; 152 + 153 + static const char * const exynosautov920_ufs_phy_clks[] = { 154 + "ref_clk", 155 + }; 156 + 157 + const struct samsung_ufs_phy_drvdata exynosautov920_ufs_phy = { 158 + .cfgs = exynosautov920_ufs_phy_cfgs, 159 + .isol = { 160 + .offset = EXYNOSAUTOV920_EMBEDDED_COMBO_PHY_CTRL, 161 + .mask = EXYNOSAUTOV920_EMBEDDED_COMBO_PHY_CTRL_MASK, 162 + .en = EXYNOSAUTOV920_EMBEDDED_COMBO_PHY_CTRL_EN, 163 + }, 164 + .clk_list = exynosautov920_ufs_phy_clks, 165 + .num_clks = ARRAY_SIZE(exynosautov920_ufs_phy_clks), 166 + .cdr_lock_status_offset = EXYNOSAUTOV920_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS, 167 + .wait_for_cdr = exynosautov920_ufs_phy_wait_cdr_lock, 168 + };
+6 -3
drivers/phy/samsung/phy-samsung-ufs.c
··· 28 28 29 29 #define PHY_DEF_LANE_CNT 1 30 30 31 - static void samsung_ufs_phy_config(struct samsung_ufs_phy *phy, 32 - const struct samsung_ufs_phy_cfg *cfg, 33 - u8 lane) 31 + void samsung_ufs_phy_config(struct samsung_ufs_phy *phy, 32 + const struct samsung_ufs_phy_cfg *cfg, 33 + u8 lane) 34 34 { 35 35 enum {LANE_0, LANE_1}; /* lane index */ 36 36 ··· 323 323 }, { 324 324 .compatible = "samsung,exynosautov9-ufs-phy", 325 325 .data = &exynosautov9_ufs_phy, 326 + }, { 327 + .compatible = "samsung,exynosautov920-ufs-phy", 328 + .data = &exynosautov920_ufs_phy, 326 329 }, { 327 330 .compatible = "tesla,fsd-ufs-phy", 328 331 .data = &fsd_ufs_phy,
+4
drivers/phy/samsung/phy-samsung-ufs.h
··· 143 143 } 144 144 145 145 int samsung_ufs_phy_wait_for_lock_acq(struct phy *phy, u8 lane); 146 + int exynosautov920_ufs_phy_wait_cdr_lock(struct phy *phy, u8 lane); 147 + void samsung_ufs_phy_config(struct samsung_ufs_phy *phy, 148 + const struct samsung_ufs_phy_cfg *cfg, u8 lane); 146 149 147 150 extern const struct samsung_ufs_phy_drvdata exynos7_ufs_phy; 148 151 extern const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy; 152 + extern const struct samsung_ufs_phy_drvdata exynosautov920_ufs_phy; 149 153 extern const struct samsung_ufs_phy_drvdata fsd_ufs_phy; 150 154 extern const struct samsung_ufs_phy_drvdata tensor_gs101_ufs_phy; 151 155
+7 -17
drivers/phy/st/phy-stih407-usb.c
··· 18 18 #include <linux/mfd/syscon.h> 19 19 #include <linux/phy/phy.h> 20 20 21 - #define PHYPARAM_REG 1 22 - #define PHYCTRL_REG 2 21 + #define PHYPARAM_REG 0 22 + #define PHYCTRL_REG 1 23 23 24 24 /* Default PHY_SEL and REFCLKSEL configuration */ 25 25 #define STIH407_USB_PICOPHY_CTRL_PORT_CONF 0x6 ··· 91 91 struct device *dev = &pdev->dev; 92 92 struct device_node *np = dev->of_node; 93 93 struct phy_provider *phy_provider; 94 + unsigned int syscon_args[2]; 94 95 struct phy *phy; 95 - int ret; 96 96 97 97 phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL); 98 98 if (!phy_dev) ··· 116 116 /* Reset port by default: only deassert it in phy init */ 117 117 reset_control_assert(phy_dev->rstport); 118 118 119 - phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); 119 + phy_dev->regmap = syscon_regmap_lookup_by_phandle_args(np, "st,syscfg", 120 + 2, syscon_args); 120 121 if (IS_ERR(phy_dev->regmap)) { 121 122 dev_err(dev, "No syscfg phandle specified\n"); 122 123 return PTR_ERR(phy_dev->regmap); 123 124 } 124 125 125 - ret = of_property_read_u32_index(np, "st,syscfg", PHYPARAM_REG, 126 - &phy_dev->param); 127 - if (ret) { 128 - dev_err(dev, "can't get phyparam offset (%d)\n", ret); 129 - return ret; 130 - } 131 - 132 - ret = of_property_read_u32_index(np, "st,syscfg", PHYCTRL_REG, 133 - &phy_dev->ctrl); 134 - if (ret) { 135 - dev_err(dev, "can't get phyctrl offset (%d)\n", ret); 136 - return ret; 137 - } 126 + phy_dev->param = syscon_args[PHYPARAM_REG]; 127 + phy_dev->ctrl = syscon_args[PHYCTRL_REG]; 138 128 139 129 phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data); 140 130 if (IS_ERR(phy)) {
-12
include/linux/phy/phy.h
··· 227 227 int phy_pm_runtime_get_sync(struct phy *phy); 228 228 int phy_pm_runtime_put(struct phy *phy); 229 229 int phy_pm_runtime_put_sync(struct phy *phy); 230 - void phy_pm_runtime_allow(struct phy *phy); 231 - void phy_pm_runtime_forbid(struct phy *phy); 232 230 int phy_init(struct phy *phy); 233 231 int phy_exit(struct phy *phy); 234 232 int phy_power_on(struct phy *phy); ··· 317 319 if (!phy) 318 320 return 0; 319 321 return -ENOSYS; 320 - } 321 - 322 - static inline void phy_pm_runtime_allow(struct phy *phy) 323 - { 324 - return; 325 - } 326 - 327 - static inline void phy_pm_runtime_forbid(struct phy *phy) 328 - { 329 - return; 330 322 } 331 323 332 324 static inline int phy_init(struct phy *phy)