GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / usb / typec / tcpm / maxim_contaminant.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2022 Google, Inc
4  *
5  * USB-C module to reduce wakeups due to contaminants.
6  */
7
8 #include <linux/device.h>
9 #include <linux/irqreturn.h>
10 #include <linux/module.h>
11 #include <linux/regmap.h>
12 #include <linux/usb/tcpci.h>
13 #include <linux/usb/tcpm.h>
14 #include <linux/usb/typec.h>
15
16 #include "tcpci_maxim.h"
17
18 enum fladc_select {
19         CC1_SCALE1 = 1,
20         CC1_SCALE2,
21         CC2_SCALE1,
22         CC2_SCALE2,
23         SBU1,
24         SBU2,
25 };
26
27 #define FLADC_1uA_LSB_MV                25
28 /* High range CC */
29 #define FLADC_CC_HIGH_RANGE_LSB_MV      208
30 /* Low range CC */
31 #define FLADC_CC_LOW_RANGE_LSB_MV      126
32
33 /* 1uA current source */
34 #define FLADC_CC_SCALE1                 1
35 /* 5 uA current source */
36 #define FLADC_CC_SCALE2                 5
37
38 #define FLADC_1uA_CC_OFFSET_MV          300
39 #define FLADC_CC_HIGH_RANGE_OFFSET_MV   624
40 #define FLADC_CC_LOW_RANGE_OFFSET_MV    378
41
42 #define CONTAMINANT_THRESHOLD_SBU_K     1000
43 #define CONTAMINANT_THRESHOLD_CC_K      1000
44
45 #define READ1_SLEEP_MS                  10
46 #define READ2_SLEEP_MS                  5
47
48 #define STATUS_CHECK(reg, mask, val)    (((reg) & (mask)) == (val))
49
50 #define IS_CC_OPEN(cc_status) \
51         (STATUS_CHECK((cc_status), TCPC_CC_STATUS_CC1_MASK << TCPC_CC_STATUS_CC1_SHIFT,  \
52                       TCPC_CC_STATE_SRC_OPEN) && STATUS_CHECK((cc_status),               \
53                                                               TCPC_CC_STATUS_CC2_MASK << \
54                                                               TCPC_CC_STATUS_CC2_SHIFT,  \
55                                                               TCPC_CC_STATE_SRC_OPEN))
56
57 static int max_contaminant_adc_to_mv(struct max_tcpci_chip *chip, enum fladc_select channel,
58                                      bool ua_src, u8 fladc)
59 {
60         /* SBU channels only have 1 scale with 1uA. */
61         if ((ua_src && (channel == CC1_SCALE2 || channel == CC2_SCALE2 || channel == SBU1 ||
62                         channel == SBU2)))
63                 /* Mean of range */
64                 return FLADC_1uA_CC_OFFSET_MV + (fladc * FLADC_1uA_LSB_MV);
65         else if (!ua_src && (channel == CC1_SCALE1 || channel == CC2_SCALE1))
66                 return FLADC_CC_HIGH_RANGE_OFFSET_MV + (fladc * FLADC_CC_HIGH_RANGE_LSB_MV);
67         else if (!ua_src && (channel == CC1_SCALE2 || channel == CC2_SCALE2))
68                 return FLADC_CC_LOW_RANGE_OFFSET_MV + (fladc * FLADC_CC_LOW_RANGE_LSB_MV);
69
70         dev_err_once(chip->dev, "ADC ERROR: SCALE UNKNOWN");
71
72         return -EINVAL;
73 }
74
75 static int max_contaminant_read_adc_mv(struct max_tcpci_chip *chip, enum fladc_select channel,
76                                        int sleep_msec, bool raw, bool ua_src)
77 {
78         struct regmap *regmap = chip->data.regmap;
79         u8 fladc;
80         int ret;
81
82         /* Channel & scale select */
83         ret = regmap_update_bits(regmap, TCPC_VENDOR_ADC_CTRL1, ADCINSEL_MASK,
84                                  channel << ADC_CHANNEL_OFFSET);
85         if (ret < 0)
86                 return ret;
87
88         /* Enable ADC */
89         ret = regmap_update_bits(regmap, TCPC_VENDOR_ADC_CTRL1, ADCEN, ADCEN);
90         if (ret < 0)
91                 return ret;
92
93         usleep_range(sleep_msec * 1000, (sleep_msec + 1) * 1000);
94         ret = max_tcpci_read8(chip, TCPC_VENDOR_FLADC_STATUS, &fladc);
95         if (ret < 0)
96                 return ret;
97
98         /* Disable ADC */
99         ret = regmap_update_bits(regmap, TCPC_VENDOR_ADC_CTRL1, ADCEN, 0);
100         if (ret < 0)
101                 return ret;
102
103         ret = regmap_update_bits(regmap, TCPC_VENDOR_ADC_CTRL1, ADCINSEL_MASK, 0);
104         if (ret < 0)
105                 return ret;
106
107         if (!raw)
108                 return max_contaminant_adc_to_mv(chip, channel, ua_src, fladc);
109         else
110                 return fladc;
111 }
112
113 static int max_contaminant_read_resistance_kohm(struct max_tcpci_chip *chip,
114                                                 enum fladc_select channel, int sleep_msec, bool raw)
115 {
116         struct regmap *regmap = chip->data.regmap;
117         int mv;
118         int ret;
119
120         if (channel == CC1_SCALE1 || channel == CC2_SCALE1 || channel == CC1_SCALE2 ||
121             channel == CC2_SCALE2) {
122                 /* Enable 1uA current source */
123                 ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL_MASK,
124                                          ULTRA_LOW_POWER_MODE);
125                 if (ret < 0)
126                         return ret;
127
128                 /* Enable 1uA current source */
129                 ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCRPCTRL_MASK, UA_1_SRC);
130                 if (ret < 0)
131                         return ret;
132
133                 /* OVP disable */
134                 ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCOVPDIS, CCOVPDIS);
135                 if (ret < 0)
136                         return ret;
137
138                 mv = max_contaminant_read_adc_mv(chip, channel, sleep_msec, raw, true);
139                 if (mv < 0)
140                         return ret;
141
142                 /* OVP enable */
143                 ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCOVPDIS, 0);
144                 if (ret < 0)
145                         return ret;
146                 /* returns KOhm as 1uA source is used. */
147                 return mv;
148         }
149
150         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, SBUOVPDIS, SBUOVPDIS);
151         if (ret < 0)
152                 return ret;
153
154         /* SBU switches auto configure when channel is selected. */
155         /* Enable 1ua current source */
156         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, SBURPCTRL, SBURPCTRL);
157         if (ret < 0)
158                 return ret;
159
160         mv = max_contaminant_read_adc_mv(chip, channel, sleep_msec, raw, true);
161         if (mv < 0)
162                 return ret;
163         /* Disable current source */
164         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, SBURPCTRL, 0);
165         if (ret < 0)
166                 return ret;
167
168         /* OVP disable */
169         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, SBUOVPDIS, 0);
170         if (ret < 0)
171                 return ret;
172
173         return mv;
174 }
175
176 static int max_contaminant_read_comparators(struct max_tcpci_chip *chip, u8 *vendor_cc_status2_cc1,
177                                             u8 *vendor_cc_status2_cc2)
178 {
179         struct regmap *regmap = chip->data.regmap;
180         int ret;
181
182         /* Enable 80uA source */
183         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCRPCTRL_MASK, UA_80_SRC);
184         if (ret < 0)
185                 return ret;
186
187         /* Enable comparators */
188         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL1, CCCOMPEN, CCCOMPEN);
189         if (ret < 0)
190                 return ret;
191
192         /* Sleep to allow comparators settle */
193         usleep_range(5000, 6000);
194         ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL, TCPC_TCPC_CTRL_ORIENTATION, PLUG_ORNT_CC1);
195         if (ret < 0)
196                 return ret;
197
198         usleep_range(5000, 6000);
199         ret = max_tcpci_read8(chip, VENDOR_CC_STATUS2, vendor_cc_status2_cc1);
200         if (ret < 0)
201                 return ret;
202
203         ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL, TCPC_TCPC_CTRL_ORIENTATION, PLUG_ORNT_CC2);
204         if (ret < 0)
205                 return ret;
206
207         usleep_range(5000, 6000);
208         ret = max_tcpci_read8(chip, VENDOR_CC_STATUS2, vendor_cc_status2_cc2);
209         if (ret < 0)
210                 return ret;
211
212         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL1, CCCOMPEN, 0);
213         if (ret < 0)
214                 return ret;
215
216         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCRPCTRL_MASK, 0);
217         if (ret < 0)
218                 return ret;
219
220         return 0;
221 }
222
223 static int max_contaminant_detect_contaminant(struct max_tcpci_chip *chip)
224 {
225         int cc1_k, cc2_k, sbu1_k, sbu2_k, ret;
226         u8 vendor_cc_status2_cc1 = 0xff, vendor_cc_status2_cc2 = 0xff;
227         u8 role_ctrl = 0, role_ctrl_backup = 0;
228         int inferred_state = NOT_DETECTED;
229
230         ret = max_tcpci_read8(chip, TCPC_ROLE_CTRL, &role_ctrl);
231         if (ret < 0)
232                 return NOT_DETECTED;
233
234         role_ctrl_backup = role_ctrl;
235         role_ctrl = 0x0F;
236         ret = max_tcpci_write8(chip, TCPC_ROLE_CTRL, role_ctrl);
237         if (ret < 0)
238                 return NOT_DETECTED;
239
240         cc1_k = max_contaminant_read_resistance_kohm(chip, CC1_SCALE2, READ1_SLEEP_MS, false);
241         if (cc1_k < 0)
242                 goto exit;
243
244         cc2_k = max_contaminant_read_resistance_kohm(chip, CC2_SCALE2, READ2_SLEEP_MS, false);
245         if (cc2_k < 0)
246                 goto exit;
247
248         sbu1_k = max_contaminant_read_resistance_kohm(chip, SBU1, READ1_SLEEP_MS, false);
249         if (sbu1_k < 0)
250                 goto exit;
251
252         sbu2_k = max_contaminant_read_resistance_kohm(chip, SBU2, READ2_SLEEP_MS, false);
253         if (sbu2_k < 0)
254                 goto exit;
255
256         ret = max_contaminant_read_comparators(chip, &vendor_cc_status2_cc1,
257                                                &vendor_cc_status2_cc2);
258
259         if (ret < 0)
260                 goto exit;
261
262         if ((!(CC1_VUFP_RD0P5 & vendor_cc_status2_cc1) ||
263              !(CC2_VUFP_RD0P5 & vendor_cc_status2_cc2)) &&
264             !(CC1_VUFP_RD0P5 & vendor_cc_status2_cc1 && CC2_VUFP_RD0P5 & vendor_cc_status2_cc2))
265                 inferred_state = SINK;
266         else if ((cc1_k < CONTAMINANT_THRESHOLD_CC_K || cc2_k < CONTAMINANT_THRESHOLD_CC_K) &&
267                  (sbu1_k < CONTAMINANT_THRESHOLD_SBU_K || sbu2_k < CONTAMINANT_THRESHOLD_SBU_K))
268                 inferred_state = DETECTED;
269
270         if (inferred_state == NOT_DETECTED)
271                 max_tcpci_write8(chip, TCPC_ROLE_CTRL, role_ctrl_backup);
272         else
273                 max_tcpci_write8(chip, TCPC_ROLE_CTRL, (TCPC_ROLE_CTRL_DRP | 0xA));
274
275         return inferred_state;
276 exit:
277         max_tcpci_write8(chip, TCPC_ROLE_CTRL, role_ctrl_backup);
278         return NOT_DETECTED;
279 }
280
281 static int max_contaminant_enable_dry_detection(struct max_tcpci_chip *chip)
282 {
283         struct regmap *regmap = chip->data.regmap;
284         u8 temp;
285         int ret;
286
287         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL3, CCWTRDEB_MASK | CCWTRSEL_MASK
288                                     | WTRCYCLE_MASK, CCWTRDEB_1MS << CCWTRDEB_SHIFT |
289                                     CCWTRSEL_1V << CCWTRSEL_SHIFT | WTRCYCLE_4_8_S <<
290                                     WTRCYCLE_SHIFT);
291         if (ret < 0)
292                 return ret;
293
294         ret = regmap_update_bits(regmap, TCPC_ROLE_CTRL, TCPC_ROLE_CTRL_DRP, TCPC_ROLE_CTRL_DRP);
295         if (ret < 0)
296                 return ret;
297
298         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL1, CCCONNDRY, CCCONNDRY);
299         if (ret < 0)
300                 return ret;
301         ret = max_tcpci_read8(chip, TCPC_VENDOR_CC_CTRL1, &temp);
302         if (ret < 0)
303                 return ret;
304
305         ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL_MASK,
306                                  ULTRA_LOW_POWER_MODE);
307         if (ret < 0)
308                 return ret;
309         ret = max_tcpci_read8(chip, TCPC_VENDOR_CC_CTRL2, &temp);
310         if (ret < 0)
311                 return ret;
312
313         /* Enable Look4Connection before sending the command */
314         ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL, TCPC_TCPC_CTRL_EN_LK4CONN_ALRT,
315                                  TCPC_TCPC_CTRL_EN_LK4CONN_ALRT);
316         if (ret < 0)
317                 return ret;
318
319         ret = max_tcpci_write8(chip, TCPC_COMMAND, TCPC_CMD_LOOK4CONNECTION);
320         if (ret < 0)
321                 return ret;
322         return 0;
323 }
324
325 bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect_while_debounce)
326 {
327         u8 cc_status, pwr_cntl;
328         int ret;
329
330         ret = max_tcpci_read8(chip, TCPC_CC_STATUS, &cc_status);
331         if (ret < 0)
332                 return false;
333
334         ret = max_tcpci_read8(chip, TCPC_POWER_CTRL, &pwr_cntl);
335         if (ret < 0)
336                 return false;
337
338         if (chip->contaminant_state == NOT_DETECTED || chip->contaminant_state == SINK) {
339                 if (!disconnect_while_debounce)
340                         msleep(100);
341
342                 ret = max_tcpci_read8(chip, TCPC_CC_STATUS, &cc_status);
343                 if (ret < 0)
344                         return false;
345
346                 if (IS_CC_OPEN(cc_status)) {
347                         u8 role_ctrl, role_ctrl_backup;
348
349                         ret = max_tcpci_read8(chip, TCPC_ROLE_CTRL, &role_ctrl);
350                         if (ret < 0)
351                                 return false;
352
353                         role_ctrl_backup = role_ctrl;
354                         role_ctrl |= 0x0F;
355                         role_ctrl &= ~(TCPC_ROLE_CTRL_DRP);
356                         ret = max_tcpci_write8(chip, TCPC_ROLE_CTRL, role_ctrl);
357                         if (ret < 0)
358                                 return false;
359
360                         chip->contaminant_state = max_contaminant_detect_contaminant(chip);
361
362                         ret = max_tcpci_write8(chip, TCPC_ROLE_CTRL, role_ctrl_backup);
363                         if (ret < 0)
364                                 return false;
365
366                         if (chip->contaminant_state == DETECTED) {
367                                 max_contaminant_enable_dry_detection(chip);
368                                 return true;
369                         }
370                 }
371                 return false;
372         } else if (chip->contaminant_state == DETECTED) {
373                 if (STATUS_CHECK(cc_status, TCPC_CC_STATUS_TOGGLING, 0)) {
374                         chip->contaminant_state = max_contaminant_detect_contaminant(chip);
375                         if (chip->contaminant_state == DETECTED) {
376                                 max_contaminant_enable_dry_detection(chip);
377                                 return true;
378                         }
379                 }
380         }
381
382         return false;
383 }
384
385 MODULE_DESCRIPTION("MAXIM TCPC CONTAMINANT Module");
386 MODULE_AUTHOR("Badhri Jagan Sridharan <badhri@google.com>");
387 MODULE_LICENSE("GPL");