1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2017, 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/iopoll.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> |
14 | #include <linux/of.h> |
15 | #include <linux/of_device.h> |
16 | #include <linux/of_address.h> |
17 | #include <linux/phy/phy.h> |
18 | #include <linux/platform_device.h> |
19 | #include <linux/regulator/consumer.h> |
20 | #include <linux/reset.h> |
21 | #include <linux/slab.h> |
22 | |
23 | #include "phy-qcom-qmp.h" |
24 | #include "phy-qcom-qmp-pcs-misc-v3.h" |
25 | #include "phy-qcom-qmp-pcs-usb-v4.h" |
26 | #include "phy-qcom-qmp-pcs-usb-v5.h" |
27 | |
28 | #include "phy-qcom-qmp-dp-com-v3.h" |
29 | |
30 | /* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ |
31 | /* DP PHY soft reset */ |
32 | #define SW_DPPHY_RESET BIT(0) |
33 | /* mux to select DP PHY reset control, 0:HW control, 1: software reset */ |
34 | #define SW_DPPHY_RESET_MUX BIT(1) |
35 | /* USB3 PHY soft reset */ |
36 | #define SW_USB3PHY_RESET BIT(2) |
37 | /* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */ |
38 | #define SW_USB3PHY_RESET_MUX BIT(3) |
39 | |
40 | /* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */ |
41 | #define USB3_MODE BIT(0) /* enables USB3 mode */ |
42 | #define DP_MODE BIT(1) /* enables DP mode */ |
43 | |
44 | #define PHY_INIT_COMPLETE_TIMEOUT 10000 |
45 | |
46 | struct qmp_phy_init_tbl { |
47 | unsigned int offset; |
48 | unsigned int val; |
49 | /* |
50 | * mask of lanes for which this register is written |
51 | * for cases when second lane needs different values |
52 | */ |
53 | u8 lane_mask; |
54 | }; |
55 | |
56 | #define QMP_PHY_INIT_CFG(o, v) \ |
57 | { \ |
58 | .offset = o, \ |
59 | .val = v, \ |
60 | .lane_mask = 0xff, \ |
61 | } |
62 | |
63 | #define QMP_PHY_INIT_CFG_LANE(o, v, l) \ |
64 | { \ |
65 | .offset = o, \ |
66 | .val = v, \ |
67 | .lane_mask = l, \ |
68 | } |
69 | |
70 | /* set of registers with offsets different per-PHY */ |
71 | enum qphy_reg_layout { |
72 | /* PCS registers */ |
73 | QPHY_SW_RESET, |
74 | QPHY_START_CTRL, |
75 | QPHY_PCS_STATUS, |
76 | QPHY_PCS_AUTONOMOUS_MODE_CTRL, |
77 | QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, |
78 | QPHY_PCS_POWER_DOWN_CONTROL, |
79 | /* Keep last to ensure regs_layout arrays are properly initialized */ |
80 | QPHY_LAYOUT_SIZE |
81 | }; |
82 | |
83 | static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { |
84 | [QPHY_SW_RESET] = QPHY_V3_PCS_SW_RESET, |
85 | [QPHY_START_CTRL] = QPHY_V3_PCS_START_CONTROL, |
86 | [QPHY_PCS_STATUS] = QPHY_V3_PCS_PCS_STATUS, |
87 | [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V3_PCS_AUTONOMOUS_MODE_CTRL, |
88 | [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V3_PCS_LFPS_RXTERM_IRQ_CLEAR, |
89 | [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V3_PCS_POWER_DOWN_CONTROL, |
90 | }; |
91 | |
92 | static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { |
93 | [QPHY_SW_RESET] = QPHY_V4_PCS_SW_RESET, |
94 | [QPHY_START_CTRL] = QPHY_V4_PCS_START_CONTROL, |
95 | [QPHY_PCS_STATUS] = QPHY_V4_PCS_PCS_STATUS1, |
96 | [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V4_PCS_POWER_DOWN_CONTROL, |
97 | |
98 | /* In PCS_USB */ |
99 | [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL, |
100 | [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR, |
101 | }; |
102 | |
103 | static const unsigned int qmp_v5_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { |
104 | [QPHY_SW_RESET] = QPHY_V5_PCS_SW_RESET, |
105 | [QPHY_START_CTRL] = QPHY_V5_PCS_START_CONTROL, |
106 | [QPHY_PCS_STATUS] = QPHY_V5_PCS_PCS_STATUS1, |
107 | [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V5_PCS_POWER_DOWN_CONTROL, |
108 | |
109 | /* In PCS_USB */ |
110 | [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V5_PCS_USB3_AUTONOMOUS_MODE_CTRL, |
111 | [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V5_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR, |
112 | }; |
113 | |
114 | static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = { |
115 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), |
116 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), |
117 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x08), |
118 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), |
119 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), |
120 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), |
121 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x16), |
122 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), |
123 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), |
124 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), |
125 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), |
126 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), |
127 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), |
128 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), |
129 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), |
130 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), |
131 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), |
132 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), |
133 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), |
134 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), |
135 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), |
136 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), |
137 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), |
138 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), |
139 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), |
140 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), |
141 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), |
142 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), |
143 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), |
144 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), |
145 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), |
146 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), |
147 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), |
148 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), |
149 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), |
150 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), |
151 | }; |
152 | |
153 | static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = { |
154 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), |
155 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), |
156 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), |
157 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x09), |
158 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), |
159 | }; |
160 | |
161 | static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = { |
162 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), |
163 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), |
164 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), |
165 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), |
166 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), |
167 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), |
168 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), |
169 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), |
170 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), |
171 | }; |
172 | |
173 | static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = { |
174 | /* FLL settings */ |
175 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), |
176 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), |
177 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), |
178 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), |
179 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), |
180 | |
181 | /* Lock Det settings */ |
182 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), |
183 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), |
184 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), |
185 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), |
186 | |
187 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), |
188 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), |
189 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), |
190 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), |
191 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), |
192 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), |
193 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), |
194 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), |
195 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), |
196 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), |
197 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), |
198 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), |
199 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), |
200 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), |
201 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), |
202 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), |
203 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), |
204 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), |
205 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), |
206 | |
207 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), |
208 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), |
209 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), |
210 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), |
211 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), |
212 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), |
213 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), |
214 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), |
215 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), |
216 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), |
217 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), |
218 | }; |
219 | |
220 | static const struct qmp_phy_init_tbl sm8150_usb3_serdes_tbl[] = { |
221 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), |
222 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), |
223 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), |
224 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), |
225 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), |
226 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), |
227 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), |
228 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), |
229 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), |
230 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), |
231 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), |
232 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), |
233 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), |
234 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), |
235 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), |
236 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), |
237 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), |
238 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), |
239 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), |
240 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), |
241 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), |
242 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), |
243 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), |
244 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), |
245 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), |
246 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), |
247 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), |
248 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), |
249 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), |
250 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), |
251 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), |
252 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), |
253 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), |
254 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), |
255 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), |
256 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), |
257 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), |
258 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), |
259 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), |
260 | QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), |
261 | }; |
262 | |
263 | static const struct qmp_phy_init_tbl sm8150_usb3_tx_tbl[] = { |
264 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x00), |
265 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x00), |
266 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), |
267 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), |
268 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), |
269 | }; |
270 | |
271 | static const struct qmp_phy_init_tbl sm8150_usb3_rx_tbl[] = { |
272 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), |
273 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), |
274 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), |
275 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), |
276 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), |
277 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), |
278 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), |
279 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), |
280 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), |
281 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), |
282 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), |
283 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0e), |
284 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), |
285 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), |
286 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), |
287 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), |
288 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), |
289 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), |
290 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), |
291 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), |
292 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), |
293 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xbf), |
294 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x3f), |
295 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), |
296 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x94), |
297 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), |
298 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), |
299 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), |
300 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), |
301 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), |
302 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), |
303 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), |
304 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), |
305 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), |
306 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), |
307 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), |
308 | }; |
309 | |
310 | static const struct qmp_phy_init_tbl sm8150_usb3_pcs_tbl[] = { |
311 | /* Lock Det settings */ |
312 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), |
313 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), |
314 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), |
315 | |
316 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), |
317 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), |
318 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), |
319 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), |
320 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), |
321 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), |
322 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), |
323 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), |
324 | }; |
325 | |
326 | static const struct qmp_phy_init_tbl sm8150_usb3_pcs_usb_tbl[] = { |
327 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), |
328 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), |
329 | }; |
330 | |
331 | static const struct qmp_phy_init_tbl sm8250_usb3_tx_tbl[] = { |
332 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x60), |
333 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x60), |
334 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), |
335 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), |
336 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), |
337 | QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), |
338 | QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x40, 1), |
339 | QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x54, 2), |
340 | }; |
341 | |
342 | static const struct qmp_phy_init_tbl sm8250_usb3_rx_tbl[] = { |
343 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), |
344 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), |
345 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), |
346 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), |
347 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), |
348 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), |
349 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), |
350 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), |
351 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), |
352 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), |
353 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), |
354 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), |
355 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), |
356 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), |
357 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), |
358 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), |
359 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), |
360 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), |
361 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), |
362 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), |
363 | QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0xff, 1), |
364 | QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f, 2), |
365 | QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f, 1), |
366 | QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff, 2), |
367 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x7f), |
368 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), |
369 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x97), |
370 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), |
371 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), |
372 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), |
373 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), |
374 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), |
375 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), |
376 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), |
377 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), |
378 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), |
379 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), |
380 | QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), |
381 | }; |
382 | |
383 | static const struct qmp_phy_init_tbl sm8250_usb3_pcs_tbl[] = { |
384 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), |
385 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), |
386 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), |
387 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), |
388 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), |
389 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), |
390 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), |
391 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), |
392 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), |
393 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), |
394 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), |
395 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), |
396 | }; |
397 | |
398 | static const struct qmp_phy_init_tbl sm8250_usb3_pcs_usb_tbl[] = { |
399 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), |
400 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), |
401 | }; |
402 | |
403 | static const struct qmp_phy_init_tbl sm8350_usb3_tx_tbl[] = { |
404 | QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_TX, 0x00), |
405 | QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_RX, 0x00), |
406 | QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), |
407 | QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), |
408 | QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x35), |
409 | QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), |
410 | QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x7f), |
411 | QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_5, 0x3f), |
412 | QMP_PHY_INIT_CFG(QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12), |
413 | QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), |
414 | }; |
415 | |
416 | static const struct qmp_phy_init_tbl sm8350_usb3_rx_tbl[] = { |
417 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), |
418 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), |
419 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), |
420 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), |
421 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), |
422 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), |
423 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), |
424 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), |
425 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), |
426 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), |
427 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), |
428 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), |
429 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), |
430 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), |
431 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), |
432 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), |
433 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), |
434 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), |
435 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), |
436 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), |
437 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), |
438 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xbb), |
439 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7b), |
440 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbb), |
441 | QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3d, 1), |
442 | QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3c, 2), |
443 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), |
444 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), |
445 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), |
446 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xd2), |
447 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x13), |
448 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), |
449 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_EN_TIMER, 0x04), |
450 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), |
451 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), |
452 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), |
453 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), |
454 | QMP_PHY_INIT_CFG(QSERDES_V5_RX_VTH_CODE, 0x10), |
455 | }; |
456 | |
457 | static const struct qmp_phy_init_tbl sm8350_usb3_pcs_tbl[] = { |
458 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), |
459 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), |
460 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), |
461 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), |
462 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), |
463 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), |
464 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), |
465 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), |
466 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), |
467 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), |
468 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), |
469 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), |
470 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), |
471 | QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), |
472 | }; |
473 | |
474 | static const struct qmp_phy_init_tbl sm8350_usb3_pcs_usb_tbl[] = { |
475 | QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_L, 0x40), |
476 | QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00), |
477 | QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), |
478 | QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), |
479 | }; |
480 | |
481 | struct qmp_usb_legacy_offsets { |
482 | u16 serdes; |
483 | u16 pcs; |
484 | u16 pcs_usb; |
485 | u16 tx; |
486 | u16 rx; |
487 | }; |
488 | |
489 | /* struct qmp_phy_cfg - per-PHY initialization config */ |
490 | struct qmp_phy_cfg { |
491 | const struct qmp_usb_legacy_offsets *offsets; |
492 | |
493 | /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ |
494 | const struct qmp_phy_init_tbl *serdes_tbl; |
495 | int serdes_tbl_num; |
496 | const struct qmp_phy_init_tbl *tx_tbl; |
497 | int tx_tbl_num; |
498 | const struct qmp_phy_init_tbl *rx_tbl; |
499 | int rx_tbl_num; |
500 | const struct qmp_phy_init_tbl *pcs_tbl; |
501 | int pcs_tbl_num; |
502 | const struct qmp_phy_init_tbl *pcs_usb_tbl; |
503 | int pcs_usb_tbl_num; |
504 | |
505 | /* clock ids to be requested */ |
506 | const char * const *clk_list; |
507 | int num_clks; |
508 | /* resets to be requested */ |
509 | const char * const *reset_list; |
510 | int num_resets; |
511 | /* regulators to be requested */ |
512 | const char * const *vreg_list; |
513 | int num_vregs; |
514 | |
515 | /* array of registers with different offsets */ |
516 | const unsigned int *regs; |
517 | |
518 | /* Offset from PCS to PCS_USB region */ |
519 | unsigned int pcs_usb_offset; |
520 | }; |
521 | |
522 | struct qmp_usb { |
523 | struct device *dev; |
524 | |
525 | const struct qmp_phy_cfg *cfg; |
526 | |
527 | void __iomem *serdes; |
528 | void __iomem *pcs; |
529 | void __iomem *pcs_misc; |
530 | void __iomem *pcs_usb; |
531 | void __iomem *tx; |
532 | void __iomem *rx; |
533 | void __iomem *tx2; |
534 | void __iomem *rx2; |
535 | |
536 | void __iomem *dp_com; |
537 | |
538 | struct clk *pipe_clk; |
539 | struct clk_bulk_data *clks; |
540 | struct reset_control_bulk_data *resets; |
541 | struct regulator_bulk_data *vregs; |
542 | |
543 | enum phy_mode mode; |
544 | |
545 | struct phy *phy; |
546 | |
547 | struct clk_fixed_rate pipe_clk_fixed; |
548 | }; |
549 | |
550 | static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) |
551 | { |
552 | u32 reg; |
553 | |
554 | reg = readl(addr: base + offset); |
555 | reg |= val; |
556 | writel(val: reg, addr: base + offset); |
557 | |
558 | /* ensure that above write is through */ |
559 | readl(addr: base + offset); |
560 | } |
561 | |
562 | static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) |
563 | { |
564 | u32 reg; |
565 | |
566 | reg = readl(addr: base + offset); |
567 | reg &= ~val; |
568 | writel(val: reg, addr: base + offset); |
569 | |
570 | /* ensure that above write is through */ |
571 | readl(addr: base + offset); |
572 | } |
573 | |
574 | /* list of clocks required by phy */ |
575 | static const char * const qmp_v3_phy_clk_l[] = { |
576 | "aux" , "cfg_ahb" , "ref" , "com_aux" , |
577 | }; |
578 | |
579 | static const char * const qmp_v4_ref_phy_clk_l[] = { |
580 | "aux" , "ref_clk_src" , "ref" , "com_aux" , |
581 | }; |
582 | |
583 | /* the primary usb3 phy on sm8250 doesn't have a ref clock */ |
584 | static const char * const qmp_v4_sm8250_usbphy_clk_l[] = { |
585 | "aux" , "ref_clk_src" , "com_aux" |
586 | }; |
587 | |
588 | /* list of resets */ |
589 | static const char * const msm8996_usb3phy_reset_l[] = { |
590 | "phy" , "common" , |
591 | }; |
592 | |
593 | static const char * const sc7180_usb3phy_reset_l[] = { |
594 | "phy" , |
595 | }; |
596 | |
597 | /* list of regulators */ |
598 | static const char * const qmp_phy_vreg_l[] = { |
599 | "vdda-phy" , "vdda-pll" , |
600 | }; |
601 | |
602 | static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { |
603 | .serdes_tbl = qmp_v3_usb3_serdes_tbl, |
604 | .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), |
605 | .tx_tbl = qmp_v3_usb3_tx_tbl, |
606 | .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), |
607 | .rx_tbl = qmp_v3_usb3_rx_tbl, |
608 | .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), |
609 | .pcs_tbl = qmp_v3_usb3_pcs_tbl, |
610 | .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), |
611 | .clk_list = qmp_v3_phy_clk_l, |
612 | .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), |
613 | .reset_list = msm8996_usb3phy_reset_l, |
614 | .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), |
615 | .vreg_list = qmp_phy_vreg_l, |
616 | .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), |
617 | .regs = qmp_v3_usb3phy_regs_layout, |
618 | }; |
619 | |
620 | static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { |
621 | .serdes_tbl = qmp_v3_usb3_serdes_tbl, |
622 | .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), |
623 | .tx_tbl = qmp_v3_usb3_tx_tbl, |
624 | .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), |
625 | .rx_tbl = qmp_v3_usb3_rx_tbl, |
626 | .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), |
627 | .pcs_tbl = qmp_v3_usb3_pcs_tbl, |
628 | .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), |
629 | .clk_list = qmp_v3_phy_clk_l, |
630 | .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), |
631 | .reset_list = sc7180_usb3phy_reset_l, |
632 | .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), |
633 | .vreg_list = qmp_phy_vreg_l, |
634 | .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), |
635 | .regs = qmp_v3_usb3phy_regs_layout, |
636 | }; |
637 | |
638 | static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { |
639 | .serdes_tbl = sm8150_usb3_serdes_tbl, |
640 | .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), |
641 | .tx_tbl = sm8150_usb3_tx_tbl, |
642 | .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_tx_tbl), |
643 | .rx_tbl = sm8150_usb3_rx_tbl, |
644 | .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_rx_tbl), |
645 | .pcs_tbl = sm8150_usb3_pcs_tbl, |
646 | .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_pcs_tbl), |
647 | .pcs_usb_tbl = sm8150_usb3_pcs_usb_tbl, |
648 | .pcs_usb_tbl_num = ARRAY_SIZE(sm8150_usb3_pcs_usb_tbl), |
649 | .clk_list = qmp_v4_ref_phy_clk_l, |
650 | .num_clks = ARRAY_SIZE(qmp_v4_ref_phy_clk_l), |
651 | .reset_list = msm8996_usb3phy_reset_l, |
652 | .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), |
653 | .vreg_list = qmp_phy_vreg_l, |
654 | .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), |
655 | .regs = qmp_v4_usb3phy_regs_layout, |
656 | .pcs_usb_offset = 0x300, |
657 | }; |
658 | |
659 | static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { |
660 | .serdes_tbl = sm8150_usb3_serdes_tbl, |
661 | .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), |
662 | .tx_tbl = sm8250_usb3_tx_tbl, |
663 | .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_tx_tbl), |
664 | .rx_tbl = sm8250_usb3_rx_tbl, |
665 | .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_rx_tbl), |
666 | .pcs_tbl = sm8250_usb3_pcs_tbl, |
667 | .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_pcs_tbl), |
668 | .pcs_usb_tbl = sm8250_usb3_pcs_usb_tbl, |
669 | .pcs_usb_tbl_num = ARRAY_SIZE(sm8250_usb3_pcs_usb_tbl), |
670 | .clk_list = qmp_v4_sm8250_usbphy_clk_l, |
671 | .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), |
672 | .reset_list = msm8996_usb3phy_reset_l, |
673 | .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), |
674 | .vreg_list = qmp_phy_vreg_l, |
675 | .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), |
676 | .regs = qmp_v4_usb3phy_regs_layout, |
677 | .pcs_usb_offset = 0x300, |
678 | }; |
679 | |
680 | static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { |
681 | .serdes_tbl = sm8150_usb3_serdes_tbl, |
682 | .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), |
683 | .tx_tbl = sm8350_usb3_tx_tbl, |
684 | .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_tx_tbl), |
685 | .rx_tbl = sm8350_usb3_rx_tbl, |
686 | .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_rx_tbl), |
687 | .pcs_tbl = sm8350_usb3_pcs_tbl, |
688 | .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_pcs_tbl), |
689 | .pcs_usb_tbl = sm8350_usb3_pcs_usb_tbl, |
690 | .pcs_usb_tbl_num = ARRAY_SIZE(sm8350_usb3_pcs_usb_tbl), |
691 | .clk_list = qmp_v4_sm8250_usbphy_clk_l, |
692 | .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), |
693 | .reset_list = msm8996_usb3phy_reset_l, |
694 | .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), |
695 | .vreg_list = qmp_phy_vreg_l, |
696 | .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), |
697 | .regs = qmp_v5_usb3phy_regs_layout, |
698 | .pcs_usb_offset = 0x300, |
699 | }; |
700 | |
701 | static void qmp_usb_legacy_configure_lane(void __iomem *base, |
702 | const struct qmp_phy_init_tbl tbl[], |
703 | int num, |
704 | u8 lane_mask) |
705 | { |
706 | int i; |
707 | const struct qmp_phy_init_tbl *t = tbl; |
708 | |
709 | if (!t) |
710 | return; |
711 | |
712 | for (i = 0; i < num; i++, t++) { |
713 | if (!(t->lane_mask & lane_mask)) |
714 | continue; |
715 | |
716 | writel(val: t->val, addr: base + t->offset); |
717 | } |
718 | } |
719 | |
720 | static void qmp_usb_legacy_configure(void __iomem *base, |
721 | const struct qmp_phy_init_tbl tbl[], |
722 | int num) |
723 | { |
724 | qmp_usb_legacy_configure_lane(base, tbl, num, lane_mask: 0xff); |
725 | } |
726 | |
727 | static int qmp_usb_legacy_serdes_init(struct qmp_usb *qmp) |
728 | { |
729 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
730 | void __iomem *serdes = qmp->serdes; |
731 | const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; |
732 | int serdes_tbl_num = cfg->serdes_tbl_num; |
733 | |
734 | qmp_usb_legacy_configure(base: serdes, tbl: serdes_tbl, num: serdes_tbl_num); |
735 | |
736 | return 0; |
737 | } |
738 | |
739 | static void qmp_usb_legacy_init_dp_com(struct phy *phy) |
740 | { |
741 | struct qmp_usb *qmp = phy_get_drvdata(phy); |
742 | void __iomem *dp_com = qmp->dp_com; |
743 | |
744 | qphy_setbits(base: dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, |
745 | SW_PWRDN); |
746 | /* override hardware control for reset of qmp phy */ |
747 | qphy_setbits(base: dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, |
748 | SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | |
749 | SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); |
750 | |
751 | /* Default type-c orientation, i.e CC1 */ |
752 | qphy_setbits(base: dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, val: 0x02); |
753 | |
754 | qphy_setbits(base: dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL, |
755 | USB3_MODE | DP_MODE); |
756 | |
757 | /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ |
758 | qphy_clrbits(base: dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, |
759 | SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | |
760 | SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); |
761 | |
762 | qphy_clrbits(base: dp_com, QPHY_V3_DP_COM_SWI_CTRL, val: 0x03); |
763 | qphy_clrbits(base: dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); |
764 | } |
765 | |
766 | static int qmp_usb_legacy_init(struct phy *phy) |
767 | { |
768 | struct qmp_usb *qmp = phy_get_drvdata(phy); |
769 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
770 | void __iomem *pcs = qmp->pcs; |
771 | int ret; |
772 | |
773 | ret = regulator_bulk_enable(num_consumers: cfg->num_vregs, consumers: qmp->vregs); |
774 | if (ret) { |
775 | dev_err(qmp->dev, "failed to enable regulators, err=%d\n" , ret); |
776 | return ret; |
777 | } |
778 | |
779 | ret = reset_control_bulk_assert(num_rstcs: cfg->num_resets, rstcs: qmp->resets); |
780 | if (ret) { |
781 | dev_err(qmp->dev, "reset assert failed\n" ); |
782 | goto err_disable_regulators; |
783 | } |
784 | |
785 | ret = reset_control_bulk_deassert(num_rstcs: cfg->num_resets, rstcs: qmp->resets); |
786 | if (ret) { |
787 | dev_err(qmp->dev, "reset deassert failed\n" ); |
788 | goto err_disable_regulators; |
789 | } |
790 | |
791 | ret = clk_bulk_prepare_enable(num_clks: cfg->num_clks, clks: qmp->clks); |
792 | if (ret) |
793 | goto err_assert_reset; |
794 | |
795 | qmp_usb_legacy_init_dp_com(phy); |
796 | |
797 | qphy_setbits(base: pcs, offset: cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN); |
798 | |
799 | return 0; |
800 | |
801 | err_assert_reset: |
802 | reset_control_bulk_assert(num_rstcs: cfg->num_resets, rstcs: qmp->resets); |
803 | err_disable_regulators: |
804 | regulator_bulk_disable(num_consumers: cfg->num_vregs, consumers: qmp->vregs); |
805 | |
806 | return ret; |
807 | } |
808 | |
809 | static int qmp_usb_legacy_exit(struct phy *phy) |
810 | { |
811 | struct qmp_usb *qmp = phy_get_drvdata(phy); |
812 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
813 | |
814 | reset_control_bulk_assert(num_rstcs: cfg->num_resets, rstcs: qmp->resets); |
815 | |
816 | clk_bulk_disable_unprepare(num_clks: cfg->num_clks, clks: qmp->clks); |
817 | |
818 | regulator_bulk_disable(num_consumers: cfg->num_vregs, consumers: qmp->vregs); |
819 | |
820 | return 0; |
821 | } |
822 | |
823 | static int qmp_usb_legacy_power_on(struct phy *phy) |
824 | { |
825 | struct qmp_usb *qmp = phy_get_drvdata(phy); |
826 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
827 | void __iomem *tx = qmp->tx; |
828 | void __iomem *rx = qmp->rx; |
829 | void __iomem *pcs = qmp->pcs; |
830 | void __iomem *status; |
831 | unsigned int val; |
832 | int ret; |
833 | |
834 | qmp_usb_legacy_serdes_init(qmp); |
835 | |
836 | ret = clk_prepare_enable(clk: qmp->pipe_clk); |
837 | if (ret) { |
838 | dev_err(qmp->dev, "pipe_clk enable failed err=%d\n" , ret); |
839 | return ret; |
840 | } |
841 | |
842 | /* Tx, Rx, and PCS configurations */ |
843 | qmp_usb_legacy_configure_lane(base: tx, tbl: cfg->tx_tbl, num: cfg->tx_tbl_num, lane_mask: 1); |
844 | qmp_usb_legacy_configure_lane(base: rx, tbl: cfg->rx_tbl, num: cfg->rx_tbl_num, lane_mask: 1); |
845 | |
846 | qmp_usb_legacy_configure_lane(base: qmp->tx2, tbl: cfg->tx_tbl, num: cfg->tx_tbl_num, lane_mask: 2); |
847 | qmp_usb_legacy_configure_lane(base: qmp->rx2, tbl: cfg->rx_tbl, num: cfg->rx_tbl_num, lane_mask: 2); |
848 | |
849 | qmp_usb_legacy_configure(base: pcs, tbl: cfg->pcs_tbl, num: cfg->pcs_tbl_num); |
850 | |
851 | usleep_range(min: 10, max: 20); |
852 | |
853 | /* Pull PHY out of reset state */ |
854 | qphy_clrbits(base: pcs, offset: cfg->regs[QPHY_SW_RESET], SW_RESET); |
855 | |
856 | /* start SerDes and Phy-Coding-Sublayer */ |
857 | qphy_setbits(base: pcs, offset: cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START); |
858 | |
859 | status = pcs + cfg->regs[QPHY_PCS_STATUS]; |
860 | ret = readl_poll_timeout(status, val, !(val & PHYSTATUS), 200, |
861 | PHY_INIT_COMPLETE_TIMEOUT); |
862 | if (ret) { |
863 | dev_err(qmp->dev, "phy initialization timed-out\n" ); |
864 | goto err_disable_pipe_clk; |
865 | } |
866 | |
867 | return 0; |
868 | |
869 | err_disable_pipe_clk: |
870 | clk_disable_unprepare(clk: qmp->pipe_clk); |
871 | |
872 | return ret; |
873 | } |
874 | |
875 | static int qmp_usb_legacy_power_off(struct phy *phy) |
876 | { |
877 | struct qmp_usb *qmp = phy_get_drvdata(phy); |
878 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
879 | |
880 | clk_disable_unprepare(clk: qmp->pipe_clk); |
881 | |
882 | /* PHY reset */ |
883 | qphy_setbits(base: qmp->pcs, offset: cfg->regs[QPHY_SW_RESET], SW_RESET); |
884 | |
885 | /* stop SerDes and Phy-Coding-Sublayer */ |
886 | qphy_clrbits(base: qmp->pcs, offset: cfg->regs[QPHY_START_CTRL], |
887 | SERDES_START | PCS_START); |
888 | |
889 | /* Put PHY into POWER DOWN state: active low */ |
890 | qphy_clrbits(base: qmp->pcs, offset: cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], |
891 | SW_PWRDN); |
892 | |
893 | return 0; |
894 | } |
895 | |
896 | static int qmp_usb_legacy_enable(struct phy *phy) |
897 | { |
898 | int ret; |
899 | |
900 | ret = qmp_usb_legacy_init(phy); |
901 | if (ret) |
902 | return ret; |
903 | |
904 | ret = qmp_usb_legacy_power_on(phy); |
905 | if (ret) |
906 | qmp_usb_legacy_exit(phy); |
907 | |
908 | return ret; |
909 | } |
910 | |
911 | static int qmp_usb_legacy_disable(struct phy *phy) |
912 | { |
913 | int ret; |
914 | |
915 | ret = qmp_usb_legacy_power_off(phy); |
916 | if (ret) |
917 | return ret; |
918 | return qmp_usb_legacy_exit(phy); |
919 | } |
920 | |
921 | static int qmp_usb_legacy_set_mode(struct phy *phy, enum phy_mode mode, int submode) |
922 | { |
923 | struct qmp_usb *qmp = phy_get_drvdata(phy); |
924 | |
925 | qmp->mode = mode; |
926 | |
927 | return 0; |
928 | } |
929 | |
930 | static const struct phy_ops qmp_usb_legacy_phy_ops = { |
931 | .init = qmp_usb_legacy_enable, |
932 | .exit = qmp_usb_legacy_disable, |
933 | .set_mode = qmp_usb_legacy_set_mode, |
934 | .owner = THIS_MODULE, |
935 | }; |
936 | |
937 | static void qmp_usb_legacy_enable_autonomous_mode(struct qmp_usb *qmp) |
938 | { |
939 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
940 | void __iomem *pcs_usb = qmp->pcs_usb ?: qmp->pcs; |
941 | void __iomem *pcs_misc = qmp->pcs_misc; |
942 | u32 intr_mask; |
943 | |
944 | if (qmp->mode == PHY_MODE_USB_HOST_SS || |
945 | qmp->mode == PHY_MODE_USB_DEVICE_SS) |
946 | intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN; |
947 | else |
948 | intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL; |
949 | |
950 | /* Clear any pending interrupts status */ |
951 | qphy_setbits(base: pcs_usb, offset: cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); |
952 | /* Writing 1 followed by 0 clears the interrupt */ |
953 | qphy_clrbits(base: pcs_usb, offset: cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); |
954 | |
955 | qphy_clrbits(base: pcs_usb, offset: cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], |
956 | ARCVR_DTCT_EN | ALFPS_DTCT_EN | ARCVR_DTCT_EVENT_SEL); |
957 | |
958 | /* Enable required PHY autonomous mode interrupts */ |
959 | qphy_setbits(base: pcs_usb, offset: cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], val: intr_mask); |
960 | |
961 | /* Enable i/o clamp_n for autonomous mode */ |
962 | if (pcs_misc) |
963 | qphy_clrbits(base: pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); |
964 | } |
965 | |
966 | static void qmp_usb_legacy_disable_autonomous_mode(struct qmp_usb *qmp) |
967 | { |
968 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
969 | void __iomem *pcs_usb = qmp->pcs_usb ?: qmp->pcs; |
970 | void __iomem *pcs_misc = qmp->pcs_misc; |
971 | |
972 | /* Disable i/o clamp_n on resume for normal mode */ |
973 | if (pcs_misc) |
974 | qphy_setbits(base: pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); |
975 | |
976 | qphy_clrbits(base: pcs_usb, offset: cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], |
977 | ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN); |
978 | |
979 | qphy_setbits(base: pcs_usb, offset: cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); |
980 | /* Writing 1 followed by 0 clears the interrupt */ |
981 | qphy_clrbits(base: pcs_usb, offset: cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); |
982 | } |
983 | |
984 | static int __maybe_unused qmp_usb_legacy_runtime_suspend(struct device *dev) |
985 | { |
986 | struct qmp_usb *qmp = dev_get_drvdata(dev); |
987 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
988 | |
989 | dev_vdbg(dev, "Suspending QMP phy, mode:%d\n" , qmp->mode); |
990 | |
991 | if (!qmp->phy->init_count) { |
992 | dev_vdbg(dev, "PHY not initialized, bailing out\n" ); |
993 | return 0; |
994 | } |
995 | |
996 | qmp_usb_legacy_enable_autonomous_mode(qmp); |
997 | |
998 | clk_disable_unprepare(clk: qmp->pipe_clk); |
999 | clk_bulk_disable_unprepare(num_clks: cfg->num_clks, clks: qmp->clks); |
1000 | |
1001 | return 0; |
1002 | } |
1003 | |
1004 | static int __maybe_unused qmp_usb_legacy_runtime_resume(struct device *dev) |
1005 | { |
1006 | struct qmp_usb *qmp = dev_get_drvdata(dev); |
1007 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
1008 | int ret = 0; |
1009 | |
1010 | dev_vdbg(dev, "Resuming QMP phy, mode:%d\n" , qmp->mode); |
1011 | |
1012 | if (!qmp->phy->init_count) { |
1013 | dev_vdbg(dev, "PHY not initialized, bailing out\n" ); |
1014 | return 0; |
1015 | } |
1016 | |
1017 | ret = clk_bulk_prepare_enable(num_clks: cfg->num_clks, clks: qmp->clks); |
1018 | if (ret) |
1019 | return ret; |
1020 | |
1021 | ret = clk_prepare_enable(clk: qmp->pipe_clk); |
1022 | if (ret) { |
1023 | dev_err(dev, "pipe_clk enable failed, err=%d\n" , ret); |
1024 | clk_bulk_disable_unprepare(num_clks: cfg->num_clks, clks: qmp->clks); |
1025 | return ret; |
1026 | } |
1027 | |
1028 | qmp_usb_legacy_disable_autonomous_mode(qmp); |
1029 | |
1030 | return 0; |
1031 | } |
1032 | |
1033 | static const struct dev_pm_ops qmp_usb_legacy_pm_ops = { |
1034 | SET_RUNTIME_PM_OPS(qmp_usb_legacy_runtime_suspend, |
1035 | qmp_usb_legacy_runtime_resume, NULL) |
1036 | }; |
1037 | |
1038 | static int qmp_usb_legacy_vreg_init(struct qmp_usb *qmp) |
1039 | { |
1040 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
1041 | struct device *dev = qmp->dev; |
1042 | int num = cfg->num_vregs; |
1043 | int i; |
1044 | |
1045 | qmp->vregs = devm_kcalloc(dev, n: num, size: sizeof(*qmp->vregs), GFP_KERNEL); |
1046 | if (!qmp->vregs) |
1047 | return -ENOMEM; |
1048 | |
1049 | for (i = 0; i < num; i++) |
1050 | qmp->vregs[i].supply = cfg->vreg_list[i]; |
1051 | |
1052 | return devm_regulator_bulk_get(dev, num_consumers: num, consumers: qmp->vregs); |
1053 | } |
1054 | |
1055 | static int qmp_usb_legacy_reset_init(struct qmp_usb *qmp) |
1056 | { |
1057 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
1058 | struct device *dev = qmp->dev; |
1059 | int i; |
1060 | int ret; |
1061 | |
1062 | qmp->resets = devm_kcalloc(dev, n: cfg->num_resets, |
1063 | size: sizeof(*qmp->resets), GFP_KERNEL); |
1064 | if (!qmp->resets) |
1065 | return -ENOMEM; |
1066 | |
1067 | for (i = 0; i < cfg->num_resets; i++) |
1068 | qmp->resets[i].id = cfg->reset_list[i]; |
1069 | |
1070 | ret = devm_reset_control_bulk_get_exclusive(dev, num_rstcs: cfg->num_resets, rstcs: qmp->resets); |
1071 | if (ret) |
1072 | return dev_err_probe(dev, err: ret, fmt: "failed to get resets\n" ); |
1073 | |
1074 | return 0; |
1075 | } |
1076 | |
1077 | static int qmp_usb_legacy_clk_init(struct qmp_usb *qmp) |
1078 | { |
1079 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
1080 | struct device *dev = qmp->dev; |
1081 | int num = cfg->num_clks; |
1082 | int i; |
1083 | |
1084 | qmp->clks = devm_kcalloc(dev, n: num, size: sizeof(*qmp->clks), GFP_KERNEL); |
1085 | if (!qmp->clks) |
1086 | return -ENOMEM; |
1087 | |
1088 | for (i = 0; i < num; i++) |
1089 | qmp->clks[i].id = cfg->clk_list[i]; |
1090 | |
1091 | return devm_clk_bulk_get(dev, num_clks: num, clks: qmp->clks); |
1092 | } |
1093 | |
1094 | static void phy_clk_release_provider(void *res) |
1095 | { |
1096 | of_clk_del_provider(np: res); |
1097 | } |
1098 | |
1099 | /* |
1100 | * Register a fixed rate pipe clock. |
1101 | * |
1102 | * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate |
1103 | * controls it. The <s>_pipe_clk coming out of the GCC is requested |
1104 | * by the PHY driver for its operations. |
1105 | * We register the <s>_pipe_clksrc here. The gcc driver takes care |
1106 | * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk. |
1107 | * Below picture shows this relationship. |
1108 | * |
1109 | * +---------------+ |
1110 | * | PHY block |<<---------------------------------------+ |
1111 | * | | | |
1112 | * | +-------+ | +-----+ | |
1113 | * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ |
1114 | * clk | +-------+ | +-----+ |
1115 | * +---------------+ |
1116 | */ |
1117 | static int phy_pipe_clk_register(struct qmp_usb *qmp, struct device_node *np) |
1118 | { |
1119 | struct clk_fixed_rate *fixed = &qmp->pipe_clk_fixed; |
1120 | struct clk_init_data init = { }; |
1121 | int ret; |
1122 | |
1123 | ret = of_property_read_string(np, propname: "clock-output-names" , out_string: &init.name); |
1124 | if (ret) { |
1125 | dev_err(qmp->dev, "%pOFn: No clock-output-names\n" , np); |
1126 | return ret; |
1127 | } |
1128 | |
1129 | init.ops = &clk_fixed_rate_ops; |
1130 | |
1131 | /* controllers using QMP phys use 125MHz pipe clock interface */ |
1132 | fixed->fixed_rate = 125000000; |
1133 | fixed->hw.init = &init; |
1134 | |
1135 | ret = devm_clk_hw_register(dev: qmp->dev, hw: &fixed->hw); |
1136 | if (ret) |
1137 | return ret; |
1138 | |
1139 | ret = of_clk_add_hw_provider(np, get: of_clk_hw_simple_get, data: &fixed->hw); |
1140 | if (ret) |
1141 | return ret; |
1142 | |
1143 | /* |
1144 | * Roll a devm action because the clock provider is the child node, but |
1145 | * the child node is not actually a device. |
1146 | */ |
1147 | return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); |
1148 | } |
1149 | |
1150 | static int qmp_usb_legacy_parse_dt_legacy(struct qmp_usb *qmp, struct device_node *np) |
1151 | { |
1152 | struct platform_device *pdev = to_platform_device(qmp->dev); |
1153 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
1154 | struct device *dev = qmp->dev; |
1155 | |
1156 | qmp->serdes = devm_platform_ioremap_resource(pdev, index: 0); |
1157 | if (IS_ERR(ptr: qmp->serdes)) |
1158 | return PTR_ERR(ptr: qmp->serdes); |
1159 | |
1160 | qmp->dp_com = devm_platform_ioremap_resource(pdev, index: 1); |
1161 | if (IS_ERR(ptr: qmp->dp_com)) |
1162 | return PTR_ERR(ptr: qmp->dp_com); |
1163 | |
1164 | /* |
1165 | * Get memory resources for the PHY: |
1166 | * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. |
1167 | * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 |
1168 | * For single lane PHYs: pcs_misc (optional) -> 3. |
1169 | */ |
1170 | qmp->tx = devm_of_iomap(dev, node: np, index: 0, NULL); |
1171 | if (IS_ERR(ptr: qmp->tx)) |
1172 | return PTR_ERR(ptr: qmp->tx); |
1173 | |
1174 | qmp->rx = devm_of_iomap(dev, node: np, index: 1, NULL); |
1175 | if (IS_ERR(ptr: qmp->rx)) |
1176 | return PTR_ERR(ptr: qmp->rx); |
1177 | |
1178 | qmp->pcs = devm_of_iomap(dev, node: np, index: 2, NULL); |
1179 | if (IS_ERR(ptr: qmp->pcs)) |
1180 | return PTR_ERR(ptr: qmp->pcs); |
1181 | |
1182 | if (cfg->pcs_usb_offset) |
1183 | qmp->pcs_usb = qmp->pcs + cfg->pcs_usb_offset; |
1184 | |
1185 | qmp->tx2 = devm_of_iomap(dev, node: np, index: 3, NULL); |
1186 | if (IS_ERR(ptr: qmp->tx2)) |
1187 | return PTR_ERR(ptr: qmp->tx2); |
1188 | |
1189 | qmp->rx2 = devm_of_iomap(dev, node: np, index: 4, NULL); |
1190 | if (IS_ERR(ptr: qmp->rx2)) |
1191 | return PTR_ERR(ptr: qmp->rx2); |
1192 | |
1193 | qmp->pcs_misc = devm_of_iomap(dev, node: np, index: 5, NULL); |
1194 | if (IS_ERR(ptr: qmp->pcs_misc)) { |
1195 | dev_vdbg(dev, "PHY pcs_misc-reg not used\n" ); |
1196 | qmp->pcs_misc = NULL; |
1197 | } |
1198 | |
1199 | qmp->pipe_clk = devm_get_clk_from_child(dev, np, NULL); |
1200 | if (IS_ERR(ptr: qmp->pipe_clk)) { |
1201 | return dev_err_probe(dev, err: PTR_ERR(ptr: qmp->pipe_clk), |
1202 | fmt: "failed to get pipe clock\n" ); |
1203 | } |
1204 | |
1205 | return 0; |
1206 | } |
1207 | |
1208 | static int qmp_usb_legacy_parse_dt(struct qmp_usb *qmp) |
1209 | { |
1210 | struct platform_device *pdev = to_platform_device(qmp->dev); |
1211 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
1212 | const struct qmp_usb_legacy_offsets *offs = cfg->offsets; |
1213 | struct device *dev = qmp->dev; |
1214 | void __iomem *base; |
1215 | |
1216 | if (!offs) |
1217 | return -EINVAL; |
1218 | |
1219 | base = devm_platform_ioremap_resource(pdev, index: 0); |
1220 | if (IS_ERR(ptr: base)) |
1221 | return PTR_ERR(ptr: base); |
1222 | |
1223 | qmp->serdes = base + offs->serdes; |
1224 | qmp->pcs = base + offs->pcs; |
1225 | qmp->pcs_usb = base + offs->pcs_usb; |
1226 | qmp->tx = base + offs->tx; |
1227 | qmp->rx = base + offs->rx; |
1228 | |
1229 | qmp->pipe_clk = devm_clk_get(dev, id: "pipe" ); |
1230 | if (IS_ERR(ptr: qmp->pipe_clk)) { |
1231 | return dev_err_probe(dev, err: PTR_ERR(ptr: qmp->pipe_clk), |
1232 | fmt: "failed to get pipe clock\n" ); |
1233 | } |
1234 | |
1235 | return 0; |
1236 | } |
1237 | |
1238 | static int qmp_usb_legacy_probe(struct platform_device *pdev) |
1239 | { |
1240 | struct device *dev = &pdev->dev; |
1241 | struct phy_provider *phy_provider; |
1242 | struct device_node *np; |
1243 | struct qmp_usb *qmp; |
1244 | int ret; |
1245 | |
1246 | qmp = devm_kzalloc(dev, size: sizeof(*qmp), GFP_KERNEL); |
1247 | if (!qmp) |
1248 | return -ENOMEM; |
1249 | |
1250 | qmp->dev = dev; |
1251 | |
1252 | qmp->cfg = of_device_get_match_data(dev); |
1253 | if (!qmp->cfg) |
1254 | return -EINVAL; |
1255 | |
1256 | ret = qmp_usb_legacy_clk_init(qmp); |
1257 | if (ret) |
1258 | return ret; |
1259 | |
1260 | ret = qmp_usb_legacy_reset_init(qmp); |
1261 | if (ret) |
1262 | return ret; |
1263 | |
1264 | ret = qmp_usb_legacy_vreg_init(qmp); |
1265 | if (ret) |
1266 | return ret; |
1267 | |
1268 | /* Check for legacy binding with child node. */ |
1269 | np = of_get_next_available_child(node: dev->of_node, NULL); |
1270 | if (np) { |
1271 | ret = qmp_usb_legacy_parse_dt_legacy(qmp, np); |
1272 | } else { |
1273 | np = of_node_get(node: dev->of_node); |
1274 | ret = qmp_usb_legacy_parse_dt(qmp); |
1275 | } |
1276 | if (ret) |
1277 | goto err_node_put; |
1278 | |
1279 | pm_runtime_set_active(dev); |
1280 | ret = devm_pm_runtime_enable(dev); |
1281 | if (ret) |
1282 | goto err_node_put; |
1283 | /* |
1284 | * Prevent runtime pm from being ON by default. Users can enable |
1285 | * it using power/control in sysfs. |
1286 | */ |
1287 | pm_runtime_forbid(dev); |
1288 | |
1289 | ret = phy_pipe_clk_register(qmp, np); |
1290 | if (ret) |
1291 | goto err_node_put; |
1292 | |
1293 | qmp->phy = devm_phy_create(dev, node: np, ops: &qmp_usb_legacy_phy_ops); |
1294 | if (IS_ERR(ptr: qmp->phy)) { |
1295 | ret = PTR_ERR(ptr: qmp->phy); |
1296 | dev_err(dev, "failed to create PHY: %d\n" , ret); |
1297 | goto err_node_put; |
1298 | } |
1299 | |
1300 | phy_set_drvdata(phy: qmp->phy, data: qmp); |
1301 | |
1302 | of_node_put(node: np); |
1303 | |
1304 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); |
1305 | |
1306 | return PTR_ERR_OR_ZERO(ptr: phy_provider); |
1307 | |
1308 | err_node_put: |
1309 | of_node_put(node: np); |
1310 | return ret; |
1311 | } |
1312 | |
1313 | static const struct of_device_id qmp_usb_legacy_of_match_table[] = { |
1314 | { |
1315 | .compatible = "qcom,sc7180-qmp-usb3-phy" , |
1316 | .data = &sc7180_usb3phy_cfg, |
1317 | }, { |
1318 | .compatible = "qcom,sc8180x-qmp-usb3-phy" , |
1319 | .data = &sm8150_usb3phy_cfg, |
1320 | }, { |
1321 | .compatible = "qcom,sdm845-qmp-usb3-phy" , |
1322 | .data = &qmp_v3_usb3phy_cfg, |
1323 | }, { |
1324 | .compatible = "qcom,sm8150-qmp-usb3-phy" , |
1325 | .data = &sm8150_usb3phy_cfg, |
1326 | }, { |
1327 | .compatible = "qcom,sm8250-qmp-usb3-phy" , |
1328 | .data = &sm8250_usb3phy_cfg, |
1329 | }, { |
1330 | .compatible = "qcom,sm8350-qmp-usb3-phy" , |
1331 | .data = &sm8350_usb3phy_cfg, |
1332 | }, { |
1333 | .compatible = "qcom,sm8450-qmp-usb3-phy" , |
1334 | .data = &sm8350_usb3phy_cfg, |
1335 | }, |
1336 | { }, |
1337 | }; |
1338 | MODULE_DEVICE_TABLE(of, qmp_usb_legacy_of_match_table); |
1339 | |
1340 | static struct platform_driver qmp_usb_legacy_driver = { |
1341 | .probe = qmp_usb_legacy_probe, |
1342 | .driver = { |
1343 | .name = "qcom-qmp-usb-legacy-phy" , |
1344 | .pm = &qmp_usb_legacy_pm_ops, |
1345 | .of_match_table = qmp_usb_legacy_of_match_table, |
1346 | }, |
1347 | }; |
1348 | |
1349 | module_platform_driver(qmp_usb_legacy_driver); |
1350 | |
1351 | MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>" ); |
1352 | MODULE_DESCRIPTION("Qualcomm QMP legacy USB+DP PHY driver" ); |
1353 | MODULE_LICENSE("GPL v2" ); |
1354 | |