GNU Linux-libre 6.8.7-gnu
[releases.git] / drivers / usb / typec / mux / wcd939x-usbss.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  * Copyright (C) 2023 Linaro Ltd.
5  */
6
7 #include <linux/bits.h>
8 #include <linux/i2c.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/mutex.h>
12 #include <linux/regmap.h>
13 #include <linux/bitfield.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/usb/typec_dp.h>
16 #include <linux/usb/typec_mux.h>
17
18 #define WCD_USBSS_PMP_OUT1                      0x2
19
20 #define WCD_USBSS_DP_DN_MISC1                   0x20
21
22 #define WCD_USBSS_DP_DN_MISC1_DP_PCOMP_2X_DYN_BST_ON_EN                 BIT(3)
23 #define WCD_USBSS_DP_DN_MISC1_DN_PCOMP_2X_DYN_BST_ON_EN                 BIT(0)
24
25 #define WCD_USBSS_MG1_EN                        0x24
26
27 #define WCD_USBSS_MG1_EN_CT_SNS_EN                                      BIT(1)
28
29 #define WCD_USBSS_MG1_BIAS                      0x25
30
31 #define WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN                             BIT(3)
32
33 #define WCD_USBSS_MG1_MISC                      0x27
34
35 #define WCD_USBSS_MG1_MISC_PCOMP_2X_DYN_BST_ON_EN                       BIT(5)
36
37 #define WCD_USBSS_MG2_EN                        0x28
38
39 #define WCD_USBSS_MG2_EN_CT_SNS_EN                                      BIT(1)
40
41 #define WCD_USBSS_MG2_BIAS                      0x29
42
43 #define WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN                             BIT(3)
44
45 #define WCD_USBSS_MG2_MISC                      0x30
46
47 #define WCD_USBSS_MG2_MISC_PCOMP_2X_DYN_BST_ON_EN                       BIT(5)
48
49 #define WCD_USBSS_DISP_AUXP_THRESH              0x80
50
51 #define WCD_USBSS_DISP_AUXP_THRESH_DISP_AUXP_OVPON_CM                   GENMASK(7, 5)
52
53 #define WCD_USBSS_DISP_AUXP_CTL                 0x81
54
55 #define WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF                     GENMASK(2, 0)
56
57 #define WCD_USBSS_CPLDO_CTL2                    0xa1
58
59 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE        0x403
60
61 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DEVICE_ENABLE                  BIT(7)
62 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES        BIT(6)
63 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES        BIT(5)
64 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES                   BIT(4)
65 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES                   BIT(3)
66 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES                 BIT(2)
67 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES                   BIT(1)
68 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES                  BIT(0)
69
70 #define WCD_USBSS_SWITCH_SELECT0                0x404
71
72 #define WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES                       BIT(7)  /* 1-> MG2 */
73 #define WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES                       BIT(6)  /* 1-> MG2 */
74 #define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES                           GENMASK(5, 4)
75 #define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES                           GENMASK(3, 2)
76 #define WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES                         BIT(1)  /* 1-> SBU2 */
77 #define WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES                           BIT(0)  /* 1-> MG2 */
78
79 #define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_L           0
80 #define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_DN          1
81 #define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_DN2         2
82
83 #define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_R           0
84 #define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_DP          1
85 #define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_DR2         2
86
87 #define WCD_USBSS_SWITCH_SELECT1                0x405
88
89 #define WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES                          BIT(0)  /* 1-> MG2 */
90
91 #define WCD_USBSS_DELAY_R_SW                    0x40d
92 #define WCD_USBSS_DELAY_MIC_SW                  0x40e
93 #define WCD_USBSS_DELAY_SENSE_SW                0x40f
94 #define WCD_USBSS_DELAY_GND_SW                  0x410
95 #define WCD_USBSS_DELAY_L_SW                    0x411
96
97 #define WCD_USBSS_FUNCTION_ENABLE               0x413
98
99 #define WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT                         GENMASK(1, 0)
100
101 #define WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT_MANUAL          1
102 #define WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT_AUDIO_FSM       2
103
104 #define WCD_USBSS_EQUALIZER1                    0x415
105
106 #define WCD_USBSS_EQUALIZER1_EQ_EN                                      BIT(7)
107 #define WCD_USBSS_EQUALIZER1_BW_SETTINGS                                GENMASK(6, 3)
108
109 #define WCD_USBSS_USB_SS_CNTL                   0x419
110
111 #define WCD_USBSS_USB_SS_CNTL_STANDBY_STATE                             BIT(4)
112 #define WCD_USBSS_USB_SS_CNTL_RCO_EN                                    BIT(3)
113 #define WCD_USBSS_USB_SS_CNTL_USB_SS_MODE                               GENMASK(2, 0)
114
115 #define WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_AATC          2
116 #define WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_USB           5
117
118 #define WCD_USBSS_AUDIO_FSM_START               0x433
119
120 #define WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG                  BIT(0)
121
122 #define WCD_USBSS_RATIO_SPKR_REXT_L_LSB         0x461
123 #define WCD_USBSS_RATIO_SPKR_REXT_L_MSB         0x462
124 #define WCD_USBSS_RATIO_SPKR_REXT_R_LSB         0x463
125 #define WCD_USBSS_RATIO_SPKR_REXT_R_MSB         0x464
126 #define WCD_USBSS_AUD_COEF_L_K0_0               0x475
127 #define WCD_USBSS_AUD_COEF_L_K0_1               0x476
128 #define WCD_USBSS_AUD_COEF_L_K0_2               0x477
129 #define WCD_USBSS_AUD_COEF_L_K1_0               0x478
130 #define WCD_USBSS_AUD_COEF_L_K1_1               0x479
131 #define WCD_USBSS_AUD_COEF_L_K2_0               0x47a
132 #define WCD_USBSS_AUD_COEF_L_K2_1               0x47b
133 #define WCD_USBSS_AUD_COEF_L_K3_0               0x47c
134 #define WCD_USBSS_AUD_COEF_L_K3_1               0x47d
135 #define WCD_USBSS_AUD_COEF_L_K4_0               0x47e
136 #define WCD_USBSS_AUD_COEF_L_K4_1               0x47f
137 #define WCD_USBSS_AUD_COEF_L_K5_0               0x480
138 #define WCD_USBSS_AUD_COEF_L_K5_1               0x481
139 #define WCD_USBSS_AUD_COEF_R_K0_0               0x482
140 #define WCD_USBSS_AUD_COEF_R_K0_1               0x483
141 #define WCD_USBSS_AUD_COEF_R_K0_2               0x484
142 #define WCD_USBSS_AUD_COEF_R_K1_0               0x485
143 #define WCD_USBSS_AUD_COEF_R_K1_1               0x486
144 #define WCD_USBSS_AUD_COEF_R_K2_0               0x487
145 #define WCD_USBSS_AUD_COEF_R_K2_1               0x488
146 #define WCD_USBSS_AUD_COEF_R_K3_0               0x489
147 #define WCD_USBSS_AUD_COEF_R_K3_1               0x48a
148 #define WCD_USBSS_AUD_COEF_R_K4_0               0x48b
149 #define WCD_USBSS_AUD_COEF_R_K4_1               0x48c
150 #define WCD_USBSS_AUD_COEF_R_K5_0               0x48d
151 #define WCD_USBSS_AUD_COEF_R_K5_1               0x48e
152 #define WCD_USBSS_GND_COEF_L_K0_0               0x48f
153 #define WCD_USBSS_GND_COEF_L_K0_1               0x490
154 #define WCD_USBSS_GND_COEF_L_K0_2               0x491
155 #define WCD_USBSS_GND_COEF_L_K1_0               0x492
156 #define WCD_USBSS_GND_COEF_L_K1_1               0x493
157 #define WCD_USBSS_GND_COEF_L_K2_0               0x494
158 #define WCD_USBSS_GND_COEF_L_K2_1               0x495
159 #define WCD_USBSS_GND_COEF_L_K3_0               0x496
160 #define WCD_USBSS_GND_COEF_L_K3_1               0x497
161 #define WCD_USBSS_GND_COEF_L_K4_0               0x498
162 #define WCD_USBSS_GND_COEF_L_K4_1               0x499
163 #define WCD_USBSS_GND_COEF_L_K5_0               0x49a
164 #define WCD_USBSS_GND_COEF_L_K5_1               0x49b
165 #define WCD_USBSS_GND_COEF_R_K0_0               0x49c
166 #define WCD_USBSS_GND_COEF_R_K0_1               0x49d
167 #define WCD_USBSS_GND_COEF_R_K0_2               0x49e
168 #define WCD_USBSS_GND_COEF_R_K1_0               0x49f
169 #define WCD_USBSS_GND_COEF_R_K1_1               0x4a0
170 #define WCD_USBSS_GND_COEF_R_K2_0               0x4a1
171 #define WCD_USBSS_GND_COEF_R_K2_1               0x4a2
172 #define WCD_USBSS_GND_COEF_R_K3_0               0x4a3
173 #define WCD_USBSS_GND_COEF_R_K3_1               0x4a4
174 #define WCD_USBSS_GND_COEF_R_K4_0               0x4a5
175 #define WCD_USBSS_GND_COEF_R_K4_1               0x4a6
176 #define WCD_USBSS_GND_COEF_R_K5_0               0x4a7
177 #define WCD_USBSS_GND_COEF_R_K5_1               0x4a8
178
179 #define WCD_USBSS_MAX_REGISTER                  0x4c1
180
181 struct wcd939x_usbss {
182         struct i2c_client *client;
183         struct gpio_desc *reset_gpio;
184         struct regulator *vdd_supply;
185
186         /* used to serialize concurrent change requests */
187         struct mutex lock;
188
189         struct typec_switch_dev *sw;
190         struct typec_mux_dev *mux;
191
192         struct regmap *regmap;
193
194         struct typec_mux *codec;
195         struct typec_switch *codec_switch;
196
197         enum typec_orientation orientation;
198         unsigned long mode;
199         unsigned int svid;
200 };
201
202 static const struct regmap_range_cfg wcd939x_usbss_ranges[] = {
203         {
204                 .range_min = 0,
205                 .range_max = WCD_USBSS_MAX_REGISTER,
206                 .selector_reg = 0x0,
207                 .selector_mask = 0xff,
208                 .selector_shift = 0,
209                 .window_start = 0,
210                 .window_len = 0x100,
211         },
212 };
213
214 static const struct regmap_config wcd939x_usbss_regmap_config = {
215         .reg_bits = 8,
216         .val_bits = 8,
217         .max_register = WCD_USBSS_MAX_REGISTER,
218         .ranges = wcd939x_usbss_ranges,
219         .num_ranges = ARRAY_SIZE(wcd939x_usbss_ranges),
220 };
221
222 /* Linearlizer coefficients for 32ohm load */
223 static const struct {
224         unsigned int offset;
225         unsigned int mask;
226         unsigned int value;
227 } wcd939x_usbss_coeff_init[] = {
228         { WCD_USBSS_AUD_COEF_L_K5_0, GENMASK(7, 0), 0x39 },
229         { WCD_USBSS_AUD_COEF_R_K5_0, GENMASK(7, 0), 0x39 },
230         { WCD_USBSS_GND_COEF_L_K2_0, GENMASK(7, 0), 0xe8 },
231         { WCD_USBSS_GND_COEF_L_K4_0, GENMASK(7, 0), 0x73 },
232         { WCD_USBSS_GND_COEF_R_K2_0, GENMASK(7, 0), 0xe8 },
233         { WCD_USBSS_GND_COEF_R_K4_0, GENMASK(7, 0), 0x73 },
234         { WCD_USBSS_RATIO_SPKR_REXT_L_LSB, GENMASK(7, 0), 0x00 },
235         { WCD_USBSS_RATIO_SPKR_REXT_L_MSB, GENMASK(6, 0), 0x04 },
236         { WCD_USBSS_RATIO_SPKR_REXT_R_LSB, GENMASK(7, 0), 0x00 },
237         { WCD_USBSS_RATIO_SPKR_REXT_R_MSB, GENMASK(6, 0), 0x04 },
238 };
239
240 static int wcd939x_usbss_set(struct wcd939x_usbss *usbss)
241 {
242         bool reverse = (usbss->orientation == TYPEC_ORIENTATION_REVERSE);
243         bool enable_audio = false;
244         bool enable_usb = false;
245         bool enable_dp = false;
246         int ret;
247
248         /* USB Mode */
249         if (usbss->mode < TYPEC_STATE_MODAL ||
250             (!usbss->svid && (usbss->mode == TYPEC_MODE_USB2 ||
251                               usbss->mode == TYPEC_MODE_USB3))) {
252                 enable_usb = true;
253         } else if (usbss->svid) {
254                 switch (usbss->mode) {
255                 /* DP Only */
256                 case TYPEC_DP_STATE_C:
257                 case TYPEC_DP_STATE_E:
258                         enable_dp = true;
259                         break;
260
261                 /* DP + USB */
262                 case TYPEC_DP_STATE_D:
263                 case TYPEC_DP_STATE_F:
264                         enable_usb = true;
265                         enable_dp = true;
266                         break;
267
268                 default:
269                         return -EOPNOTSUPP;
270                 }
271         } else if (usbss->mode == TYPEC_MODE_AUDIO) {
272                 enable_audio = true;
273         } else {
274                 return -EOPNOTSUPP;
275         }
276
277         /* Disable all switches */
278         ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE,
279                                 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES |
280                                 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES |
281                                 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES |
282                                 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES |
283                                 WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES |
284                                 WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES |
285                                 WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES);
286         if (ret)
287                 return ret;
288
289         /* Clear switches */
290         ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0,
291                                 WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES |
292                                 WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES |
293                                 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES |
294                                 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES |
295                                 WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES |
296                                 WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES);
297         if (ret)
298                 return ret;
299
300         ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1,
301                                 WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES);
302         if (ret)
303                 return ret;
304
305         /* Enable OVP_MG1_BIAS PCOMP_DYN_BST_EN */
306         ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG1_BIAS,
307                               WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN);
308         if (ret)
309                 return ret;
310
311         /* Enable OVP_MG2_BIAS PCOMP_DYN_BST_EN */
312         ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG2_BIAS,
313                               WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN);
314         if (ret)
315                 return ret;
316
317         /* Disable Equalizer in safe mode */
318         ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_EQUALIZER1,
319                                 WCD_USBSS_EQUALIZER1_EQ_EN);
320         if (ret)
321                 return ret;
322
323         /* Start FSM with all disabled, force write */
324         ret = regmap_write_bits(usbss->regmap, WCD_USBSS_AUDIO_FSM_START,
325                                 WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG,
326                                 WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG);
327
328         /* 35us to allow the SBU switch to turn off */
329         usleep_range(35, 1000);
330
331         /* Setup Audio Accessory mux/switch */
332         if (enable_audio) {
333                 int i;
334
335                 /*
336                  * AATC switch configuration:
337                  * "Normal":
338                  * - R: DNR
339                  * - L: DNL
340                  * - Sense: GSBU2
341                  * - Mic: MG1
342                  * - AGND: MG2
343                  * "Swapped":
344                  * - R: DNR
345                  * - L: DNL
346                  * - Sense: GSBU1
347                  * - Mic: MG2
348                  * - AGND: MG1
349                  * Swapped information is given by the codec MBHC logic
350                  */
351
352                 /* Set AATC mode */
353                 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL,
354                                          WCD_USBSS_USB_SS_CNTL_USB_SS_MODE,
355                                          FIELD_PREP(WCD_USBSS_USB_SS_CNTL_USB_SS_MODE,
356                                                     WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_AATC));
357                 if (ret)
358                         return ret;
359
360                 /* Select L for DNL_SWITCHES and R for DPR_SWITCHES */
361                 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0,
362                                 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES |
363                                 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES,
364                                 FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES,
365                                         WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_L) |
366                                 FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES,
367                                         WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_R));
368                 if (ret)
369                         return ret;
370
371                 if (reverse)
372                         /* Select MG2 for MIC, SBU1 for Sense */
373                         ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0,
374                                                  WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES,
375                                                  WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES);
376                 else
377                         /* Select MG1 for MIC, SBU2 for Sense */
378                         ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0,
379                                                  WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES,
380                                                  WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES);
381                 if (ret)
382                         return ret;
383
384                 if (reverse)
385                         /* Disable OVP_MG1_BIAS PCOMP_DYN_BST_EN */
386                         ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_MG1_BIAS,
387                                                 WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN);
388                 else
389                         /* Disable OVP_MG2_BIAS PCOMP_DYN_BST_EN */
390                         ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_MG2_BIAS,
391                                                 WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN);
392                 if (ret)
393                         return ret;
394
395                 /*  Enable SENSE, MIC switches */
396                 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE,
397                                       WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES |
398                                       WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES);
399                 if (ret)
400                         return ret;
401
402                 if (reverse)
403                         /* Select MG1 for AGND_SWITCHES */
404                         ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1,
405                                                 WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES);
406                 else
407                         /* Select MG2 for AGND_SWITCHES */
408                         ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1,
409                                               WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES);
410                 if (ret)
411                         return ret;
412
413                 /* Enable AGND switches */
414                 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE,
415                                       WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES);
416                 if (ret)
417                         return ret;
418
419                 /* Enable DPR, DNL switches */
420                 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE,
421                                       WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES |
422                                       WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES);
423                 if (ret)
424                         return ret;
425
426                 /* Setup FSM delays */
427                 ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_L_SW, 0x02);
428                 if (ret)
429                         return ret;
430
431                 ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_R_SW, 0x02);
432                 if (ret)
433                         return ret;
434
435                 ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_MIC_SW, 0x01);
436                 if (ret)
437                         return ret;
438
439                 /* Start FSM, force write */
440                 ret = regmap_write_bits(usbss->regmap, WCD_USBSS_AUDIO_FSM_START,
441                                         WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG,
442                                         WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG);
443                 if (ret)
444                         return ret;
445
446                 /* Default Linearlizer coefficients */
447                 for (i = 0; i < ARRAY_SIZE(wcd939x_usbss_coeff_init); ++i)
448                         regmap_update_bits(usbss->regmap,
449                                            wcd939x_usbss_coeff_init[i].offset,
450                                            wcd939x_usbss_coeff_init[i].mask,
451                                            wcd939x_usbss_coeff_init[i].value);
452
453                 return 0;
454         }
455
456         ret = regmap_update_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL,
457                                  WCD_USBSS_USB_SS_CNTL_USB_SS_MODE,
458                                  FIELD_PREP(WCD_USBSS_USB_SS_CNTL_USB_SS_MODE,
459                                             WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_USB));
460         if (ret)
461                 return ret;
462
463         /* Enable USB muxes */
464         if (enable_usb) {
465                 /* Do not enable Equalizer in safe mode */
466                 if (usbss->mode != TYPEC_STATE_SAFE) {
467                         ret = regmap_set_bits(usbss->regmap, WCD_USBSS_EQUALIZER1,
468                                               WCD_USBSS_EQUALIZER1_EQ_EN);
469                         if (ret)
470                                 return ret;
471                 }
472
473                 /* Select DN for DNL_SWITCHES and DP for DPR_SWITCHES */
474                 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0,
475                                          WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES |
476                                          WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES,
477                                          FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES,
478                                                     WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_DN) |
479                                          FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES,
480                                                     WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_DP));
481                 if (ret)
482                         return ret;
483
484                 /* Enable DNL_SWITCHES and DPR_SWITCHES */
485                 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE,
486                                       WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES |
487                                       WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES);
488                 if (ret)
489                         return ret;
490         }
491
492         /* Enable DP AUX muxes */
493         if (enable_dp) {
494                 /* Update Leakage Canceller Coefficient for AUXP pins */
495                 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_DISP_AUXP_CTL,
496                                          WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF,
497                                          FIELD_PREP(WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF,
498                                                     5));
499                 if (ret)
500                         return ret;
501
502                 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_DISP_AUXP_THRESH,
503                                       WCD_USBSS_DISP_AUXP_THRESH_DISP_AUXP_OVPON_CM);
504                 if (ret)
505                         return ret;
506
507                 if (reverse)
508                         /* Select MG2 for AUXP and MG1 for AUXM */
509                         ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0,
510                                                  WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES |
511                                                  WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES,
512                                                  WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES);
513                 else
514                         /* Select MG1 for AUXP and MG2 for AUXM */
515                         ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0,
516                                                  WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES |
517                                                  WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES,
518                                                  WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES);
519                 if (ret)
520                         return ret;
521
522                 /* Enable DP_AUXP_TO_MGX and DP_AUXM_TO_MGX switches */
523                 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE,
524                                       WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES |
525                                       WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES);
526
527                 /* 15us to allow the SBU switch to turn on again */
528                 usleep_range(15, 1000);
529         }
530
531         return 0;
532 }
533
534 static int wcd939x_usbss_switch_set(struct typec_switch_dev *sw,
535                                     enum typec_orientation orientation)
536 {
537         struct wcd939x_usbss *usbss = typec_switch_get_drvdata(sw);
538         int ret = 0;
539
540         mutex_lock(&usbss->lock);
541
542         if (usbss->orientation != orientation) {
543                 usbss->orientation = orientation;
544
545                 ret = wcd939x_usbss_set(usbss);
546         }
547
548         mutex_unlock(&usbss->lock);
549
550         if (ret)
551                 return ret;
552
553         /* Report orientation to codec after switch has been done */
554         return typec_switch_set(usbss->codec_switch, orientation);
555 }
556
557 static int wcd939x_usbss_mux_set(struct typec_mux_dev *mux,
558                                  struct typec_mux_state *state)
559 {
560         struct wcd939x_usbss *usbss = typec_mux_get_drvdata(mux);
561         int ret = 0;
562
563         mutex_lock(&usbss->lock);
564
565         if (usbss->mode != state->mode) {
566                 usbss->mode = state->mode;
567
568                 if (state->alt)
569                         usbss->svid = state->alt->svid;
570                 else
571                         usbss->svid = 0; // No SVID
572
573                 ret = wcd939x_usbss_set(usbss);
574         }
575
576         mutex_unlock(&usbss->lock);
577
578         if (ret)
579                 return ret;
580
581         /* Report event to codec after switch has been done */
582         return typec_mux_set(usbss->codec, state);
583 }
584
585 static int wcd939x_usbss_probe(struct i2c_client *client)
586 {
587         struct device *dev = &client->dev;
588         struct typec_switch_desc sw_desc = { };
589         struct typec_mux_desc mux_desc = { };
590         struct wcd939x_usbss *usbss;
591         int ret;
592
593         usbss = devm_kzalloc(dev, sizeof(*usbss), GFP_KERNEL);
594         if (!usbss)
595                 return -ENOMEM;
596
597         usbss->client = client;
598         mutex_init(&usbss->lock);
599
600         usbss->regmap = devm_regmap_init_i2c(client, &wcd939x_usbss_regmap_config);
601         if (IS_ERR(usbss->regmap))
602                 return dev_err_probe(dev, PTR_ERR(usbss->regmap), "failed to initialize regmap\n");
603
604         usbss->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
605         if (IS_ERR(usbss->reset_gpio))
606                 return dev_err_probe(dev, PTR_ERR(usbss->reset_gpio),
607                                      "unable to acquire reset gpio\n");
608
609         usbss->vdd_supply = devm_regulator_get_optional(dev, "vdd");
610         if (IS_ERR(usbss->vdd_supply))
611                 return PTR_ERR(usbss->vdd_supply);
612
613         /* Get Codec's MUX & Switch devices */
614         usbss->codec = fwnode_typec_mux_get(dev->fwnode);
615         if (IS_ERR(usbss->codec))
616                 return dev_err_probe(dev, PTR_ERR(usbss->codec),
617                                      "failed to acquire codec mode-switch\n");
618
619         usbss->codec_switch = fwnode_typec_switch_get(dev->fwnode);
620         if (IS_ERR(usbss->codec_switch)) {
621                 ret = dev_err_probe(dev, PTR_ERR(usbss->codec_switch),
622                                     "failed to acquire codec orientation-switch\n");
623                 goto err_mux_put;
624         }
625
626         usbss->mode = TYPEC_STATE_SAFE;
627         usbss->orientation = TYPEC_ORIENTATION_NONE;
628
629         gpiod_set_value(usbss->reset_gpio, 1);
630
631         ret = regulator_enable(usbss->vdd_supply);
632         if (ret) {
633                 dev_err(dev, "Failed to enable vdd: %d\n", ret);
634                 goto err_mux_switch;
635         }
636
637         msleep(20);
638
639         gpiod_set_value(usbss->reset_gpio, 0);
640
641         msleep(20);
642
643         /* Disable standby */
644         ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL,
645                                 WCD_USBSS_USB_SS_CNTL_STANDBY_STATE);
646         if (ret)
647                 goto err_regulator_disable;
648
649         /* Set manual mode by default */
650         ret = regmap_update_bits(usbss->regmap, WCD_USBSS_FUNCTION_ENABLE,
651                                  WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT,
652                                  FIELD_PREP(WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT,
653                                             WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT_MANUAL));
654         if (ret)
655                 goto err_regulator_disable;
656
657         /* Enable dynamic boosting for DP and DN */
658         ret = regmap_set_bits(usbss->regmap, WCD_USBSS_DP_DN_MISC1,
659                               WCD_USBSS_DP_DN_MISC1_DP_PCOMP_2X_DYN_BST_ON_EN |
660                               WCD_USBSS_DP_DN_MISC1_DN_PCOMP_2X_DYN_BST_ON_EN);
661         if (ret)
662                 goto err_regulator_disable;
663
664         /* Enable dynamic boosting for MG1 OVP */
665         ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG1_MISC,
666                               WCD_USBSS_MG1_MISC_PCOMP_2X_DYN_BST_ON_EN);
667         if (ret)
668                 goto err_regulator_disable;
669
670         /* Enable dynamic boosting for MG2 OVP */
671         ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG2_MISC,
672                               WCD_USBSS_MG2_MISC_PCOMP_2X_DYN_BST_ON_EN);
673         if (ret)
674                 goto err_regulator_disable;
675
676         /* Write 0xFF to WCD_USBSS_CPLDO_CTL2 */
677         ret = regmap_set_bits(usbss->regmap, WCD_USBSS_CPLDO_CTL2, 0xff);
678         if (ret)
679                 goto err_regulator_disable;
680
681         /* Set RCO_EN: WCD_USBSS_USB_SS_CNTL Bit<3> --> 0x0 --> 0x1 */
682         ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL,
683                                 WCD_USBSS_USB_SS_CNTL_RCO_EN);
684         if (ret)
685                 goto err_regulator_disable;
686
687         ret = regmap_set_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL,
688                               WCD_USBSS_USB_SS_CNTL_RCO_EN);
689         if (ret)
690                 goto err_regulator_disable;
691
692         /* Disable all switches but enable the mux */
693         ret = regmap_write(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE,
694                            WCD_USBSS_SWITCH_SETTINGS_ENABLE_DEVICE_ENABLE);
695         if (ret)
696                 goto err_regulator_disable;
697
698         /* Setup in SAFE mode */
699         ret = wcd939x_usbss_set(usbss);
700         if (ret)
701                 goto err_regulator_disable;
702
703         sw_desc.drvdata = usbss;
704         sw_desc.fwnode = dev_fwnode(dev);
705         sw_desc.set = wcd939x_usbss_switch_set;
706
707         usbss->sw = typec_switch_register(dev, &sw_desc);
708         if (IS_ERR(usbss->sw)) {
709                 ret = dev_err_probe(dev, PTR_ERR(usbss->sw), "failed to register typec switch\n");
710                 goto err_regulator_disable;
711         }
712
713         mux_desc.drvdata = usbss;
714         mux_desc.fwnode = dev_fwnode(dev);
715         mux_desc.set = wcd939x_usbss_mux_set;
716
717         usbss->mux = typec_mux_register(dev, &mux_desc);
718         if (IS_ERR(usbss->mux)) {
719                 ret = dev_err_probe(dev, PTR_ERR(usbss->mux), "failed to register typec mux\n");
720                 goto err_switch_unregister;
721         }
722
723         i2c_set_clientdata(client, usbss);
724
725         return 0;
726
727 err_switch_unregister:
728         typec_switch_unregister(usbss->sw);
729
730 err_regulator_disable:
731         regulator_disable(usbss->vdd_supply);
732
733 err_mux_switch:
734         typec_switch_put(usbss->codec_switch);
735
736 err_mux_put:
737         typec_mux_put(usbss->codec);
738
739         return ret;
740 }
741
742 static void wcd939x_usbss_remove(struct i2c_client *client)
743 {
744         struct wcd939x_usbss *usbss = i2c_get_clientdata(client);
745
746         typec_mux_unregister(usbss->mux);
747         typec_switch_unregister(usbss->sw);
748
749         regulator_disable(usbss->vdd_supply);
750
751         typec_switch_put(usbss->codec_switch);
752         typec_mux_put(usbss->codec);
753 }
754
755 static const struct i2c_device_id wcd939x_usbss_table[] = {
756         { "wcd9390-usbss" },
757         { }
758 };
759 MODULE_DEVICE_TABLE(i2c, wcd939x_usbss_table);
760
761 static const struct of_device_id wcd939x_usbss_of_table[] = {
762         { .compatible = "qcom,wcd9390-usbss" },
763         { }
764 };
765 MODULE_DEVICE_TABLE(of, wcd939x_usbss_of_table);
766
767 static struct i2c_driver wcd939x_usbss_driver = {
768         .driver = {
769                 .name = "wcd939x-usbss",
770                 .of_match_table = wcd939x_usbss_of_table,
771         },
772         .probe          = wcd939x_usbss_probe,
773         .remove         = wcd939x_usbss_remove,
774         .id_table       = wcd939x_usbss_table,
775 };
776 module_i2c_driver(wcd939x_usbss_driver);
777
778 MODULE_DESCRIPTION("Qualcomm WCD939x USBSS driver");
779 MODULE_LICENSE("GPL");