1 | // SPDX-License-Identifier: GPL-2.0 |
2 | |
3 | #include <linux/bitfield.h> |
4 | #include <linux/completion.h> |
5 | #include <linux/i2c.h> |
6 | #include <linux/interrupt.h> |
7 | #include <linux/kernel.h> |
8 | #include <linux/module.h> |
9 | #include <linux/power_supply.h> |
10 | #include <linux/regmap.h> |
11 | #include <linux/usb/pd.h> |
12 | #include <linux/usb/role.h> |
13 | #include <linux/usb/typec.h> |
14 | |
15 | #define RT1719_REG_TXCTRL1 0x03 |
16 | #define RT1719_REG_TXCTRL2 0x04 |
17 | #define RT1719_REG_POLICYINFO 0x0E |
18 | #define RT1719_REG_SRCPDO1 0x11 |
19 | #define RT1719_REG_MASKS 0x2D |
20 | #define RT1719_REG_EVENTS 0x33 |
21 | #define RT1719_REG_STATS 0x37 |
22 | #define RT1719_REG_PSELINFO 0x3C |
23 | #define RT1719_REG_USBSETINFO 0x3E |
24 | #define RT1719_REG_VENID 0x82 |
25 | |
26 | #define RT1719_UNIQUE_PID 0x1719 |
27 | #define RT1719_REQDRSWAP_MASK BIT(7) |
28 | #define RT1719_EVALMODE_MASK BIT(4) |
29 | #define RT1719_REQSRCPDO_MASK GENMASK(2, 0) |
30 | #define RT1719_TXSPDOREQ_MASK BIT(7) |
31 | #define RT1719_INT_DRSW_ACCEPT BIT(23) |
32 | #define RT1719_INT_RX_SRCCAP BIT(21) |
33 | #define RT1719_INT_VBUS_DCT BIT(6) |
34 | #define RT1719_INT_VBUS_PRESENT BIT(5) |
35 | #define RT1719_INT_PE_SNK_RDY BIT(2) |
36 | #define RT1719_CC1_STAT GENMASK(9, 8) |
37 | #define RT1719_CC2_STAT GENMASK(11, 10) |
38 | #define RT1719_POLARITY_MASK BIT(23) |
39 | #define RT1719_DATAROLE_MASK BIT(22) |
40 | #define RT1719_PDSPECREV_MASK GENMASK(21, 20) |
41 | #define RT1719_SPDOSEL_MASK GENMASK(18, 16) |
42 | #define RT1719_SPDONUM_MASK GENMASK(15, 13) |
43 | #define RT1719_ATTACH_VBUS BIT(12) |
44 | #define RT1719_ATTACH_DBG BIT(10) |
45 | #define RT1719_ATTACH_SNK BIT(9) |
46 | #define RT1719_ATTACHDEV_MASK (RT1719_ATTACH_VBUS | RT1719_ATTACH_DBG | \ |
47 | RT1719_ATTACH_SNK) |
48 | #define RT1719_PE_EXP_CONTRACT BIT(2) |
49 | #define RT1719_PSEL_SUPPORT BIT(15) |
50 | #define RT1719_TBLSEL_MASK BIT(6) |
51 | #define RT1719_LATPSEL_MASK GENMASK(5, 0) |
52 | #define RT1719_USBINFO_MASK GENMASK(1, 0) |
53 | #define RT1719_USB_DFPUFP 3 |
54 | #define RT1719_MAX_SRCPDO 7 |
55 | |
56 | enum { |
57 | SNK_PWR_OPEN = 0, |
58 | SNK_PWR_DEF, |
59 | SNK_PWR_1P5A, |
60 | SNK_PWR_3A |
61 | }; |
62 | |
63 | enum { |
64 | USBPD_SPECREV_1_0 = 0, |
65 | USBPD_SPECREV_2_0, |
66 | USBPD_SPECREV_3_0 |
67 | }; |
68 | |
69 | enum rt1719_snkcap { |
70 | RT1719_SNKCAP_5V = 0, |
71 | RT1719_SNKCAP_9V, |
72 | RT1719_SNKCAP_12V, |
73 | RT1719_SNKCAP_15V, |
74 | RT1719_SNKCAP_20V, |
75 | RT1719_MAX_SNKCAP |
76 | }; |
77 | |
78 | struct rt1719_psel_cap { |
79 | u8 lomask; |
80 | u8 himask; |
81 | u32 milliwatt; |
82 | u32 milliamp; |
83 | }; |
84 | |
85 | struct rt1719_data { |
86 | struct device *dev; |
87 | struct regmap *regmap; |
88 | struct typec_port *port; |
89 | struct usb_role_switch *role_sw; |
90 | struct power_supply *psy; |
91 | struct typec_partner *partner; |
92 | struct power_supply_desc psy_desc; |
93 | struct usb_pd_identity partner_ident; |
94 | struct typec_partner_desc partner_desc; |
95 | struct completion req_completion; |
96 | enum power_supply_usb_type usb_type; |
97 | bool attached; |
98 | bool pd_capable; |
99 | bool drswap_support; |
100 | u32 voltage; |
101 | u32 req_voltage; |
102 | u32 max_current; |
103 | u32 op_current; |
104 | u32 spdos[RT1719_MAX_SRCPDO]; |
105 | u16 snkcaps[RT1719_MAX_SNKCAP]; |
106 | int spdo_num; |
107 | int spdo_sel; |
108 | u32 conn_info; |
109 | u16 conn_stat; |
110 | }; |
111 | |
112 | static const enum power_supply_usb_type rt1719_psy_usb_types[] = { |
113 | POWER_SUPPLY_USB_TYPE_C, |
114 | POWER_SUPPLY_USB_TYPE_PD, |
115 | POWER_SUPPLY_USB_TYPE_PD_PPS |
116 | }; |
117 | |
118 | static const enum power_supply_property rt1719_psy_properties[] = { |
119 | POWER_SUPPLY_PROP_ONLINE, |
120 | POWER_SUPPLY_PROP_USB_TYPE, |
121 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
122 | POWER_SUPPLY_PROP_CURRENT_MAX, |
123 | POWER_SUPPLY_PROP_CURRENT_NOW |
124 | }; |
125 | |
126 | static int rt1719_read16(struct rt1719_data *data, unsigned int reg, u16 *val) |
127 | { |
128 | __le16 regval; |
129 | int ret; |
130 | |
131 | ret = regmap_raw_read(map: data->regmap, reg, val: ®val, val_len: sizeof(regval)); |
132 | if (ret) |
133 | return ret; |
134 | |
135 | *val = le16_to_cpu(regval); |
136 | return 0; |
137 | } |
138 | |
139 | static int rt1719_read32(struct rt1719_data *data, unsigned int reg, u32 *val) |
140 | { |
141 | __le32 regval; |
142 | int ret; |
143 | |
144 | ret = regmap_raw_read(map: data->regmap, reg, val: ®val, val_len: sizeof(regval)); |
145 | if (ret) |
146 | return ret; |
147 | |
148 | *val = le32_to_cpu(regval); |
149 | return 0; |
150 | } |
151 | |
152 | static int rt1719_write32(struct rt1719_data *data, unsigned int reg, u32 val) |
153 | { |
154 | __le32 regval = cpu_to_le32(val); |
155 | |
156 | return regmap_raw_write(map: data->regmap, reg, val: ®val, val_len: sizeof(regval)); |
157 | } |
158 | |
159 | static enum typec_pwr_opmode rt1719_get_pwr_opmode(u32 conn, u16 stat) |
160 | { |
161 | u16 cc1, cc2, cc_stat; |
162 | |
163 | cc1 = FIELD_GET(RT1719_CC1_STAT, stat); |
164 | cc2 = FIELD_GET(RT1719_CC2_STAT, stat); |
165 | |
166 | if (conn & RT1719_ATTACH_SNK) { |
167 | if (conn & RT1719_POLARITY_MASK) |
168 | cc_stat = cc2; |
169 | else |
170 | cc_stat = cc1; |
171 | |
172 | switch (cc_stat) { |
173 | case SNK_PWR_3A: |
174 | return TYPEC_PWR_MODE_3_0A; |
175 | case SNK_PWR_1P5A: |
176 | return TYPEC_PWR_MODE_1_5A; |
177 | } |
178 | } else if (conn & RT1719_ATTACH_DBG) { |
179 | if ((cc1 == SNK_PWR_1P5A && cc2 == SNK_PWR_DEF) || |
180 | (cc1 == SNK_PWR_DEF && cc2 == SNK_PWR_1P5A)) |
181 | return TYPEC_PWR_MODE_1_5A; |
182 | else if ((cc1 == SNK_PWR_3A && cc2 == SNK_PWR_DEF) || |
183 | (cc1 == SNK_PWR_DEF && cc2 == SNK_PWR_3A)) |
184 | return TYPEC_PWR_MODE_3_0A; |
185 | } |
186 | |
187 | return TYPEC_PWR_MODE_USB; |
188 | } |
189 | |
190 | static enum typec_data_role rt1719_get_data_role(u32 conn) |
191 | { |
192 | if (conn & RT1719_DATAROLE_MASK) |
193 | return TYPEC_HOST; |
194 | return TYPEC_DEVICE; |
195 | } |
196 | |
197 | static void rt1719_set_data_role(struct rt1719_data *data, |
198 | enum typec_data_role data_role, |
199 | bool attached) |
200 | { |
201 | enum usb_role usb_role = USB_ROLE_NONE; |
202 | |
203 | if (attached) { |
204 | if (data_role == TYPEC_HOST) |
205 | usb_role = USB_ROLE_HOST; |
206 | else |
207 | usb_role = USB_ROLE_DEVICE; |
208 | } |
209 | |
210 | usb_role_switch_set_role(sw: data->role_sw, role: usb_role); |
211 | typec_set_data_role(port: data->port, role: data_role); |
212 | } |
213 | |
214 | static void rt1719_update_data_role(struct rt1719_data *data) |
215 | { |
216 | if (!data->attached) |
217 | return; |
218 | |
219 | rt1719_set_data_role(data, data_role: rt1719_get_data_role(conn: data->conn_info), attached: true); |
220 | } |
221 | |
222 | static void rt1719_register_partner(struct rt1719_data *data) |
223 | { |
224 | u16 spec_rev = 0; |
225 | |
226 | if (data->pd_capable) { |
227 | u32 rev; |
228 | |
229 | rev = FIELD_GET(RT1719_PDSPECREV_MASK, data->conn_info); |
230 | switch (rev) { |
231 | case USBPD_SPECREV_3_0: |
232 | spec_rev = 0x0300; |
233 | break; |
234 | case USBPD_SPECREV_2_0: |
235 | spec_rev = 0x0200; |
236 | break; |
237 | default: |
238 | spec_rev = 0x0100; |
239 | break; |
240 | } |
241 | } |
242 | |
243 | /* Just to prevent multiple times attach */ |
244 | if (data->partner) |
245 | typec_unregister_partner(partner: data->partner); |
246 | |
247 | memset(&data->partner_ident, 0, sizeof(data->partner_ident)); |
248 | data->partner_desc.usb_pd = data->pd_capable; |
249 | data->partner_desc.pd_revision = spec_rev; |
250 | |
251 | if (data->conn_info & RT1719_ATTACH_DBG) |
252 | data->partner_desc.accessory = TYPEC_ACCESSORY_DEBUG; |
253 | else |
254 | data->partner_desc.accessory = TYPEC_ACCESSORY_NONE; |
255 | |
256 | data->partner = typec_register_partner(port: data->port, desc: &data->partner_desc); |
257 | } |
258 | |
259 | static void rt1719_attach(struct rt1719_data *data) |
260 | { |
261 | enum typec_pwr_opmode pwr_opmode; |
262 | enum typec_data_role data_role; |
263 | u32 volt = 5000, curr = 500; |
264 | |
265 | if (!(data->conn_info & RT1719_ATTACHDEV_MASK)) |
266 | return; |
267 | |
268 | pwr_opmode = rt1719_get_pwr_opmode(conn: data->conn_info, stat: data->conn_stat); |
269 | data_role = rt1719_get_data_role(conn: data->conn_info); |
270 | |
271 | typec_set_pwr_opmode(port: data->port, mode: pwr_opmode); |
272 | rt1719_set_data_role(data, data_role, attached: true); |
273 | |
274 | if (data->conn_info & RT1719_ATTACH_SNK) |
275 | rt1719_register_partner(data); |
276 | |
277 | if (pwr_opmode == TYPEC_PWR_MODE_3_0A) |
278 | curr = 3000; |
279 | else if (pwr_opmode == TYPEC_PWR_MODE_1_5A) |
280 | curr = 1500; |
281 | |
282 | data->voltage = volt * 1000; |
283 | data->max_current = data->op_current = curr * 1000; |
284 | data->attached = true; |
285 | |
286 | power_supply_changed(psy: data->psy); |
287 | } |
288 | |
289 | static void rt1719_detach(struct rt1719_data *data) |
290 | { |
291 | if (!data->attached || (data->conn_info & RT1719_ATTACHDEV_MASK)) |
292 | return; |
293 | |
294 | typec_unregister_partner(partner: data->partner); |
295 | data->partner = NULL; |
296 | |
297 | typec_set_pwr_opmode(port: data->port, mode: TYPEC_PWR_MODE_USB); |
298 | rt1719_set_data_role(data, data_role: TYPEC_DEVICE, attached: false); |
299 | |
300 | memset32(s: data->spdos, v: 0, RT1719_MAX_SRCPDO); |
301 | data->spdo_num = 0; |
302 | data->voltage = data->max_current = data->op_current = 0; |
303 | data->attached = data->pd_capable = false; |
304 | |
305 | data->usb_type = POWER_SUPPLY_USB_TYPE_C; |
306 | |
307 | power_supply_changed(psy: data->psy); |
308 | } |
309 | |
310 | static void rt1719_update_operating_status(struct rt1719_data *data) |
311 | { |
312 | enum power_supply_usb_type usb_type = POWER_SUPPLY_USB_TYPE_PD; |
313 | u32 voltage, max_current, op_current; |
314 | int i, snk_sel; |
315 | |
316 | for (i = 0; i < data->spdo_num; i++) { |
317 | u32 pdo = data->spdos[i]; |
318 | enum pd_pdo_type type = pdo_type(pdo); |
319 | |
320 | if (type == PDO_TYPE_APDO) { |
321 | usb_type = POWER_SUPPLY_USB_TYPE_PD_PPS; |
322 | break; |
323 | } |
324 | } |
325 | |
326 | data->spdo_sel = FIELD_GET(RT1719_SPDOSEL_MASK, data->conn_info); |
327 | if (data->spdo_sel <= 0) |
328 | return; |
329 | |
330 | data->usb_type = usb_type; |
331 | |
332 | voltage = pdo_fixed_voltage(pdo: data->spdos[data->spdo_sel - 1]); |
333 | max_current = pdo_max_current(pdo: data->spdos[data->spdo_sel - 1]); |
334 | |
335 | switch (voltage) { |
336 | case 5000: |
337 | snk_sel = RT1719_SNKCAP_5V; |
338 | break; |
339 | case 9000: |
340 | snk_sel = RT1719_SNKCAP_9V; |
341 | break; |
342 | case 12000: |
343 | snk_sel = RT1719_SNKCAP_12V; |
344 | break; |
345 | case 15000: |
346 | snk_sel = RT1719_SNKCAP_15V; |
347 | break; |
348 | case 20000: |
349 | snk_sel = RT1719_SNKCAP_20V; |
350 | break; |
351 | default: |
352 | return; |
353 | } |
354 | |
355 | op_current = min(max_current, pdo_max_current(data->snkcaps[snk_sel])); |
356 | |
357 | /* covert mV/mA to uV/uA */ |
358 | data->voltage = voltage * 1000; |
359 | data->max_current = max_current * 1000; |
360 | data->op_current = op_current * 1000; |
361 | |
362 | power_supply_changed(psy: data->psy); |
363 | } |
364 | |
365 | static void rt1719_update_pwr_opmode(struct rt1719_data *data) |
366 | { |
367 | if (!data->attached) |
368 | return; |
369 | |
370 | if (!data->pd_capable) { |
371 | data->pd_capable = true; |
372 | |
373 | typec_set_pwr_opmode(port: data->port, mode: TYPEC_PWR_MODE_PD); |
374 | rt1719_register_partner(data); |
375 | } |
376 | |
377 | rt1719_update_operating_status(data); |
378 | } |
379 | |
380 | static void rt1719_update_source_pdos(struct rt1719_data *data) |
381 | { |
382 | int spdo_num = FIELD_GET(RT1719_SPDONUM_MASK, data->conn_info); |
383 | __le32 src_pdos[RT1719_MAX_SRCPDO] = { }; |
384 | int i, ret; |
385 | |
386 | if (!data->attached) |
387 | return; |
388 | |
389 | ret = regmap_raw_read(map: data->regmap, RT1719_REG_SRCPDO1, val: src_pdos, |
390 | val_len: sizeof(__le32) * spdo_num); |
391 | if (ret) |
392 | return; |
393 | |
394 | data->spdo_num = spdo_num; |
395 | for (i = 0; i < spdo_num; i++) |
396 | data->spdos[i] = le32_to_cpu(src_pdos[i]); |
397 | } |
398 | |
399 | static int rt1719_dr_set(struct typec_port *port, enum typec_data_role role) |
400 | { |
401 | struct rt1719_data *data = typec_get_drvdata(port); |
402 | enum typec_data_role cur_role; |
403 | int ret; |
404 | |
405 | if (!data->attached || !data->pd_capable || !data->drswap_support) |
406 | return -EOPNOTSUPP; |
407 | |
408 | if (data->spdo_num > 0 && !(data->spdos[0] & PDO_FIXED_DATA_SWAP)) |
409 | return -EINVAL; |
410 | |
411 | cur_role = rt1719_get_data_role(conn: data->conn_info); |
412 | if (cur_role == role) |
413 | return 0; |
414 | |
415 | ret = regmap_update_bits(map: data->regmap, RT1719_REG_TXCTRL1, |
416 | RT1719_REQDRSWAP_MASK, RT1719_REQDRSWAP_MASK); |
417 | if (ret) |
418 | return ret; |
419 | |
420 | reinit_completion(x: &data->req_completion); |
421 | ret = wait_for_completion_timeout(x: &data->req_completion, |
422 | timeout: msecs_to_jiffies(m: 400)); |
423 | if (ret == 0) |
424 | return -ETIMEDOUT; |
425 | |
426 | cur_role = rt1719_get_data_role(conn: data->conn_info); |
427 | if (cur_role != role) |
428 | return -EAGAIN; |
429 | |
430 | rt1719_set_data_role(data, data_role: role, attached: true); |
431 | return 0; |
432 | } |
433 | |
434 | static const struct typec_operations rt1719_port_ops = { |
435 | .dr_set = rt1719_dr_set, |
436 | }; |
437 | |
438 | static int rt1719_usbpd_request_voltage(struct rt1719_data *data) |
439 | { |
440 | u32 src_voltage; |
441 | int snk_sel, src_sel = -1; |
442 | int i, ret; |
443 | |
444 | if (!data->attached || !data->pd_capable || data->spdo_sel <= 0) |
445 | return -EINVAL; |
446 | |
447 | src_voltage = pdo_fixed_voltage(pdo: data->spdos[data->spdo_sel - 1]); |
448 | if (src_voltage == data->req_voltage) |
449 | return 0; |
450 | |
451 | switch (data->req_voltage) { |
452 | case 5000: |
453 | snk_sel = RT1719_SNKCAP_5V; |
454 | break; |
455 | case 9000: |
456 | snk_sel = RT1719_SNKCAP_9V; |
457 | break; |
458 | case 12000: |
459 | snk_sel = RT1719_SNKCAP_12V; |
460 | break; |
461 | case 15000: |
462 | snk_sel = RT1719_SNKCAP_15V; |
463 | break; |
464 | case 20000: |
465 | snk_sel = RT1719_SNKCAP_20V; |
466 | break; |
467 | default: |
468 | return -EINVAL; |
469 | } |
470 | |
471 | if (!(data->snkcaps[snk_sel] & RT1719_PSEL_SUPPORT)) |
472 | return -EINVAL; |
473 | |
474 | for (i = 0; i < data->spdo_num; i++) { |
475 | enum pd_pdo_type type = pdo_type(pdo: data->spdos[i]); |
476 | |
477 | if (type != PDO_TYPE_FIXED) |
478 | continue; |
479 | |
480 | src_voltage = pdo_fixed_voltage(pdo: data->spdos[i]); |
481 | if (src_voltage == data->req_voltage) { |
482 | src_sel = i; |
483 | break; |
484 | } |
485 | } |
486 | |
487 | if (src_sel == -1) |
488 | return -EOPNOTSUPP; |
489 | |
490 | ret = regmap_update_bits(map: data->regmap, RT1719_REG_TXCTRL1, |
491 | RT1719_EVALMODE_MASK | RT1719_REQSRCPDO_MASK, |
492 | RT1719_EVALMODE_MASK | (src_sel + 1)); |
493 | ret |= regmap_update_bits(map: data->regmap, RT1719_REG_TXCTRL2, |
494 | RT1719_TXSPDOREQ_MASK, RT1719_TXSPDOREQ_MASK); |
495 | if (ret) |
496 | return ret; |
497 | |
498 | reinit_completion(x: &data->req_completion); |
499 | ret = wait_for_completion_timeout(x: &data->req_completion, |
500 | timeout: msecs_to_jiffies(m: 400)); |
501 | if (!ret) |
502 | return -ETIMEDOUT; |
503 | |
504 | return 0; |
505 | } |
506 | |
507 | static int rt1719_psy_set_property(struct power_supply *psy, |
508 | enum power_supply_property psp, |
509 | const union power_supply_propval *val) |
510 | { |
511 | struct rt1719_data *data = power_supply_get_drvdata(psy); |
512 | |
513 | if (psp == POWER_SUPPLY_PROP_VOLTAGE_NOW) { |
514 | data->req_voltage = val->intval / 1000; |
515 | return rt1719_usbpd_request_voltage(data); |
516 | } |
517 | |
518 | return -EINVAL; |
519 | } |
520 | |
521 | static int rt1719_psy_get_property(struct power_supply *psy, |
522 | enum power_supply_property psp, |
523 | union power_supply_propval *val) |
524 | { |
525 | struct rt1719_data *data = power_supply_get_drvdata(psy); |
526 | int ret = 0; |
527 | |
528 | switch (psp) { |
529 | case POWER_SUPPLY_PROP_ONLINE: |
530 | val->intval = data->attached ? 1 : 0; |
531 | break; |
532 | case POWER_SUPPLY_PROP_USB_TYPE: |
533 | val->intval = data->usb_type; |
534 | break; |
535 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
536 | val->intval = data->voltage; |
537 | break; |
538 | case POWER_SUPPLY_PROP_CURRENT_MAX: |
539 | val->intval = data->max_current; |
540 | break; |
541 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
542 | val->intval = data->op_current; |
543 | break; |
544 | default: |
545 | ret = -EINVAL; |
546 | break; |
547 | } |
548 | |
549 | return ret; |
550 | } |
551 | |
552 | static int rt1719_psy_property_is_writeable(struct power_supply *psy, |
553 | enum power_supply_property psp) |
554 | { |
555 | if (psp == POWER_SUPPLY_PROP_VOLTAGE_NOW) |
556 | return 1; |
557 | return 0; |
558 | } |
559 | |
560 | static int devm_rt1719_psy_register(struct rt1719_data *data) |
561 | { |
562 | struct power_supply_config psy_cfg = { }; |
563 | char *psy_name; |
564 | |
565 | psy_cfg.fwnode = dev_fwnode(data->dev); |
566 | psy_cfg.drv_data = data; |
567 | |
568 | psy_name = devm_kasprintf(dev: data->dev, GFP_KERNEL, fmt: "rt1719-source-psy-%s" , |
569 | dev_name(dev: data->dev)); |
570 | if (!psy_name) |
571 | return -ENOMEM; |
572 | |
573 | data->psy_desc.name = psy_name; |
574 | data->psy_desc.type = POWER_SUPPLY_TYPE_USB; |
575 | data->psy_desc.usb_types = rt1719_psy_usb_types; |
576 | data->psy_desc.num_usb_types = ARRAY_SIZE(rt1719_psy_usb_types); |
577 | data->psy_desc.properties = rt1719_psy_properties; |
578 | data->psy_desc.num_properties = ARRAY_SIZE(rt1719_psy_properties); |
579 | data->psy_desc.get_property = rt1719_psy_get_property; |
580 | data->psy_desc.set_property = rt1719_psy_set_property; |
581 | data->psy_desc.property_is_writeable = rt1719_psy_property_is_writeable; |
582 | |
583 | data->usb_type = POWER_SUPPLY_USB_TYPE_C; |
584 | |
585 | data->psy = devm_power_supply_register(parent: data->dev, desc: &data->psy_desc, |
586 | cfg: &psy_cfg); |
587 | |
588 | return PTR_ERR_OR_ZERO(ptr: data->psy); |
589 | } |
590 | |
591 | static irqreturn_t rt1719_irq_handler(int irq, void *priv) |
592 | { |
593 | struct rt1719_data *data = priv; |
594 | u32 events, conn_info; |
595 | u16 conn_stat; |
596 | int ret; |
597 | |
598 | ret = rt1719_read32(data, RT1719_REG_EVENTS, val: &events); |
599 | ret |= rt1719_read32(data, RT1719_REG_POLICYINFO, val: &conn_info); |
600 | ret |= rt1719_read16(data, RT1719_REG_STATS, val: &conn_stat); |
601 | if (ret) |
602 | return IRQ_NONE; |
603 | |
604 | data->conn_info = conn_info; |
605 | data->conn_stat = conn_stat; |
606 | |
607 | events &= (RT1719_INT_DRSW_ACCEPT | RT1719_INT_RX_SRCCAP | |
608 | RT1719_INT_VBUS_PRESENT | RT1719_INT_VBUS_DCT | |
609 | RT1719_INT_PE_SNK_RDY); |
610 | |
611 | if (events & RT1719_INT_DRSW_ACCEPT) |
612 | rt1719_update_data_role(data); |
613 | |
614 | if (events & RT1719_INT_VBUS_PRESENT) |
615 | rt1719_attach(data); |
616 | |
617 | if (events & RT1719_INT_VBUS_DCT) |
618 | rt1719_detach(data); |
619 | |
620 | if (events & RT1719_INT_RX_SRCCAP) |
621 | rt1719_update_source_pdos(data); |
622 | |
623 | if (events & RT1719_INT_PE_SNK_RDY) { |
624 | complete(&data->req_completion); |
625 | rt1719_update_pwr_opmode(data); |
626 | } |
627 | |
628 | /* Write 1 to clear already handled events */ |
629 | rt1719_write32(data, RT1719_REG_EVENTS, val: events); |
630 | |
631 | return IRQ_HANDLED; |
632 | } |
633 | |
634 | static int rt1719_irq_init(struct rt1719_data *data) |
635 | { |
636 | struct i2c_client *i2c = to_i2c_client(data->dev); |
637 | u32 irq_enable; |
638 | int ret; |
639 | |
640 | irq_enable = RT1719_INT_DRSW_ACCEPT | RT1719_INT_RX_SRCCAP | |
641 | RT1719_INT_VBUS_DCT | RT1719_INT_VBUS_PRESENT | |
642 | RT1719_INT_PE_SNK_RDY; |
643 | |
644 | ret = rt1719_write32(data, RT1719_REG_MASKS, val: irq_enable); |
645 | if (ret) { |
646 | dev_err(&i2c->dev, "Failed to config irq enable\n" ); |
647 | return ret; |
648 | } |
649 | |
650 | return devm_request_threaded_irq(dev: &i2c->dev, irq: i2c->irq, NULL, |
651 | thread_fn: rt1719_irq_handler, IRQF_ONESHOT, |
652 | devname: dev_name(dev: &i2c->dev), dev_id: data); |
653 | } |
654 | |
655 | static int rt1719_init_attach_state(struct rt1719_data *data) |
656 | { |
657 | u32 conn_info, irq_clear; |
658 | u16 conn_stat; |
659 | int ret; |
660 | |
661 | irq_clear = RT1719_INT_DRSW_ACCEPT | RT1719_INT_RX_SRCCAP | |
662 | RT1719_INT_VBUS_DCT | RT1719_INT_VBUS_PRESENT | |
663 | RT1719_INT_PE_SNK_RDY; |
664 | |
665 | ret = rt1719_read32(data, RT1719_REG_POLICYINFO, val: &conn_info); |
666 | ret |= rt1719_read16(data, RT1719_REG_STATS, val: &conn_stat); |
667 | ret |= rt1719_write32(data, RT1719_REG_EVENTS, val: irq_clear); |
668 | if (ret) |
669 | return ret; |
670 | |
671 | data->conn_info = conn_info; |
672 | data->conn_stat = conn_stat; |
673 | |
674 | if (conn_info & RT1719_ATTACHDEV_MASK) |
675 | rt1719_attach(data); |
676 | |
677 | if (conn_info & RT1719_PE_EXP_CONTRACT) { |
678 | rt1719_update_source_pdos(data); |
679 | rt1719_update_pwr_opmode(data); |
680 | } |
681 | |
682 | return 0; |
683 | } |
684 | |
685 | #define RT1719_PSEL_CAPINFO(_lomask, _milliwatt, _himask, _milliamp) { \ |
686 | .lomask = _lomask, \ |
687 | .milliwatt = _milliwatt, \ |
688 | .himask = _himask, \ |
689 | .milliamp = _milliamp, \ |
690 | } |
691 | |
692 | static const struct rt1719_psel_cap rt1719_psel_caps[] = { |
693 | RT1719_PSEL_CAPINFO(0x18, 75000, 0x10, 5000), |
694 | RT1719_PSEL_CAPINFO(0x18, 60000, 0x10, 4500), |
695 | RT1719_PSEL_CAPINFO(0x18, 45000, 0x10, 4000), |
696 | RT1719_PSEL_CAPINFO(0x18, 30000, 0x10, 3500), |
697 | RT1719_PSEL_CAPINFO(0x18, 25000, 0x10, 3000), |
698 | RT1719_PSEL_CAPINFO(0x18, 20000, 0x10, 2500), |
699 | RT1719_PSEL_CAPINFO(0x18, 15000, 0x10, 2000), |
700 | RT1719_PSEL_CAPINFO(0x18, 10000, 0x10, 1000), |
701 | RT1719_PSEL_CAPINFO(0x1C, 60000, 0x1F, 5000), |
702 | RT1719_PSEL_CAPINFO(0x1C, 45000, 0x1F, 4500), |
703 | RT1719_PSEL_CAPINFO(0x1C, 30000, 0x1F, 4000), |
704 | RT1719_PSEL_CAPINFO(0x1C, 24000, 0x1F, 3500), |
705 | RT1719_PSEL_CAPINFO(0x1C, 15000, 0x1F, 3000), |
706 | RT1719_PSEL_CAPINFO(0x1C, 10000, 0x1F, 2500), |
707 | RT1719_PSEL_CAPINFO(0x0C, 60000, 0x1F, 2000), |
708 | RT1719_PSEL_CAPINFO(0x0C, 45000, 0x1F, 1000), |
709 | RT1719_PSEL_CAPINFO(0x0C, 36000, 0x08, 5000), |
710 | RT1719_PSEL_CAPINFO(0x0C, 30000, 0x08, 4500), |
711 | RT1719_PSEL_CAPINFO(0x0C, 24000, 0x08, 4000), |
712 | RT1719_PSEL_CAPINFO(0x0C, 15000, 0x08, 3500), |
713 | RT1719_PSEL_CAPINFO(0x0C, 10000, 0x08, 3000), |
714 | RT1719_PSEL_CAPINFO(0x1E, 45000, 0x08, 2500), |
715 | RT1719_PSEL_CAPINFO(0x1E, 36000, 0x08, 2000), |
716 | RT1719_PSEL_CAPINFO(0x1E, 27000, 0x08, 1500), |
717 | RT1719_PSEL_CAPINFO(0x1E, 20000, 0x08, 1000), |
718 | RT1719_PSEL_CAPINFO(0x1E, 15000, 0x0F, 5000), |
719 | RT1719_PSEL_CAPINFO(0x1E, 9000, 0x0F, 4500), |
720 | RT1719_PSEL_CAPINFO(0x0E, 45000, 0x0F, 4000), |
721 | RT1719_PSEL_CAPINFO(0x0E, 36000, 0x0F, 3500), |
722 | RT1719_PSEL_CAPINFO(0x0E, 27000, 0x0F, 3000), |
723 | RT1719_PSEL_CAPINFO(0x0E, 20000, 0x0F, 2500), |
724 | RT1719_PSEL_CAPINFO(0x0E, 15000, 0x0F, 2000), |
725 | RT1719_PSEL_CAPINFO(0x0E, 9000, 0x0F, 1500), |
726 | RT1719_PSEL_CAPINFO(0x06, 45000, 0x0F, 1000), |
727 | RT1719_PSEL_CAPINFO(0x06, 36000, 0x0F, 500), |
728 | RT1719_PSEL_CAPINFO(0x06, 27000, 0x04, 5000), |
729 | RT1719_PSEL_CAPINFO(0x06, 24000, 0x04, 4500), |
730 | RT1719_PSEL_CAPINFO(0x06, 18000, 0x04, 4000), |
731 | RT1719_PSEL_CAPINFO(0x06, 12000, 0x04, 3500), |
732 | RT1719_PSEL_CAPINFO(0x06, 9000, 0x04, 3000), |
733 | RT1719_PSEL_CAPINFO(0x1F, 25000, 0x04, 2500), |
734 | RT1719_PSEL_CAPINFO(0x1F, 20000, 0x04, 2000), |
735 | RT1719_PSEL_CAPINFO(0x1F, 15000, 0x04, 1500), |
736 | RT1719_PSEL_CAPINFO(0x1F, 10000, 0x04, 1000), |
737 | RT1719_PSEL_CAPINFO(0x1F, 7500, 0x07, 5000), |
738 | RT1719_PSEL_CAPINFO(0x0F, 25000, 0x07, 4500), |
739 | RT1719_PSEL_CAPINFO(0x0F, 20000, 0x07, 4000), |
740 | RT1719_PSEL_CAPINFO(0x0F, 15000, 0x07, 3500), |
741 | RT1719_PSEL_CAPINFO(0x0F, 10000, 0x07, 3000), |
742 | RT1719_PSEL_CAPINFO(0x0F, 7500, 0x07, 2500), |
743 | RT1719_PSEL_CAPINFO(0x07, 25000, 0x07, 2000), |
744 | RT1719_PSEL_CAPINFO(0x07, 20000, 0x07, 1500), |
745 | RT1719_PSEL_CAPINFO(0x07, 15000, 0x07, 1000), |
746 | RT1719_PSEL_CAPINFO(0x07, 10000, 0x07, 500), |
747 | RT1719_PSEL_CAPINFO(0x07, 7500, 0x03, 5000), |
748 | RT1719_PSEL_CAPINFO(0x03, 25000, 0x03, 4500), |
749 | RT1719_PSEL_CAPINFO(0x03, 20000, 0x03, 4000), |
750 | RT1719_PSEL_CAPINFO(0x03, 15000, 0x03, 3500), |
751 | RT1719_PSEL_CAPINFO(0x03, 10000, 0x03, 3000), |
752 | RT1719_PSEL_CAPINFO(0x03, 7500, 0x03, 2500), |
753 | RT1719_PSEL_CAPINFO(0x01, 15000, 0x03, 2000), |
754 | RT1719_PSEL_CAPINFO(0x01, 10000, 0x03, 1500), |
755 | RT1719_PSEL_CAPINFO(0x01, 7500, 0x03, 1000), |
756 | RT1719_PSEL_CAPINFO(0x01, 2500, 0x03, 500) |
757 | }; |
758 | |
759 | static u16 rt1719_gen_snkcap_by_current(const struct rt1719_psel_cap *psel_cap, |
760 | enum rt1719_snkcap capsel) |
761 | { |
762 | u16 cap = RT1719_PSEL_SUPPORT; |
763 | |
764 | if (!(psel_cap->himask & BIT(capsel))) |
765 | return 0; |
766 | |
767 | cap |= psel_cap->milliamp / 10; |
768 | return cap; |
769 | } |
770 | |
771 | static u16 rt1719_gen_snkcap_by_watt(const struct rt1719_psel_cap *psel_cap, |
772 | enum rt1719_snkcap capsel) |
773 | { |
774 | u32 volt_div[RT1719_MAX_SNKCAP] = { 5, 9, 12, 15, 20 }; |
775 | u16 cap = RT1719_PSEL_SUPPORT; |
776 | |
777 | if (!(psel_cap->lomask & BIT(capsel))) |
778 | return 0; |
779 | |
780 | cap |= min(psel_cap->milliwatt / volt_div[capsel], (u32)5000) / 10; |
781 | return cap; |
782 | } |
783 | |
784 | static u16 rt1719_gen_snkcap(unsigned int pselinfo, enum rt1719_snkcap capsel) |
785 | { |
786 | int psel = FIELD_GET(RT1719_LATPSEL_MASK, pselinfo); |
787 | const struct rt1719_psel_cap *psel_cap; |
788 | bool by_current = false; |
789 | |
790 | if (pselinfo & RT1719_TBLSEL_MASK) |
791 | by_current = true; |
792 | |
793 | psel_cap = rt1719_psel_caps + psel; |
794 | if (by_current) |
795 | return rt1719_gen_snkcap_by_current(psel_cap, capsel); |
796 | |
797 | return rt1719_gen_snkcap_by_watt(psel_cap, capsel); |
798 | } |
799 | |
800 | static int rt1719_get_caps(struct rt1719_data *data) |
801 | { |
802 | unsigned int pselinfo, usbinfo; |
803 | int i, ret; |
804 | |
805 | ret = regmap_read(map: data->regmap, RT1719_REG_PSELINFO, val: &pselinfo); |
806 | ret |= regmap_read(map: data->regmap, RT1719_REG_USBSETINFO, val: &usbinfo); |
807 | if (ret) |
808 | return ret; |
809 | |
810 | for (i = 0; i < RT1719_MAX_SNKCAP; i++) |
811 | data->snkcaps[i] = rt1719_gen_snkcap(pselinfo, capsel: i); |
812 | |
813 | usbinfo = FIELD_GET(RT1719_USBINFO_MASK, usbinfo); |
814 | if (usbinfo == RT1719_USB_DFPUFP) |
815 | data->drswap_support = true; |
816 | |
817 | return 0; |
818 | } |
819 | |
820 | static int rt1719_check_exist(struct rt1719_data *data) |
821 | { |
822 | u16 pid; |
823 | int ret; |
824 | |
825 | ret = rt1719_read16(data, RT1719_REG_VENID, val: &pid); |
826 | if (ret) |
827 | return ret; |
828 | |
829 | if (pid != RT1719_UNIQUE_PID) { |
830 | dev_err(data->dev, "Incorrect PID 0x%04x\n" , pid); |
831 | return -ENODEV; |
832 | } |
833 | |
834 | return 0; |
835 | } |
836 | |
837 | static const struct regmap_config rt1719_regmap_config = { |
838 | .reg_bits = 8, |
839 | .val_bits = 8, |
840 | .max_register = 0xff, |
841 | }; |
842 | |
843 | static int rt1719_probe(struct i2c_client *i2c) |
844 | { |
845 | struct rt1719_data *data; |
846 | struct fwnode_handle *fwnode; |
847 | struct typec_capability typec_cap = { }; |
848 | int ret; |
849 | |
850 | data = devm_kzalloc(dev: &i2c->dev, size: sizeof(*data), GFP_KERNEL); |
851 | if (!data) |
852 | return -ENOMEM; |
853 | |
854 | data->dev = &i2c->dev; |
855 | init_completion(x: &data->req_completion); |
856 | |
857 | data->regmap = devm_regmap_init_i2c(i2c, &rt1719_regmap_config); |
858 | if (IS_ERR(ptr: data->regmap)) { |
859 | ret = PTR_ERR(ptr: data->regmap); |
860 | dev_err(&i2c->dev, "Failed to init regmap (%d)\n" , ret); |
861 | return ret; |
862 | } |
863 | |
864 | ret = rt1719_check_exist(data); |
865 | if (ret) |
866 | return ret; |
867 | |
868 | ret = rt1719_get_caps(data); |
869 | if (ret) |
870 | return ret; |
871 | |
872 | fwnode = device_get_named_child_node(dev: &i2c->dev, childname: "connector" ); |
873 | if (!fwnode) |
874 | return -ENODEV; |
875 | |
876 | data->role_sw = fwnode_usb_role_switch_get(node: fwnode); |
877 | if (IS_ERR(ptr: data->role_sw)) { |
878 | ret = PTR_ERR(ptr: data->role_sw); |
879 | dev_err(&i2c->dev, "Failed to get usb role switch (%d)\n" , ret); |
880 | goto err_fwnode_put; |
881 | } |
882 | |
883 | ret = devm_rt1719_psy_register(data); |
884 | if (ret) { |
885 | dev_err(&i2c->dev, "Failed to register psy (%d)\n" , ret); |
886 | goto err_role_put; |
887 | } |
888 | |
889 | typec_cap.revision = USB_TYPEC_REV_1_2; |
890 | typec_cap.pd_revision = 0x300; /* USB-PD spec release 3.0 */ |
891 | typec_cap.type = TYPEC_PORT_SNK; |
892 | typec_cap.data = TYPEC_PORT_DRD; |
893 | typec_cap.ops = &rt1719_port_ops; |
894 | typec_cap.fwnode = fwnode; |
895 | typec_cap.driver_data = data; |
896 | typec_cap.accessory[0] = TYPEC_ACCESSORY_DEBUG; |
897 | |
898 | data->partner_desc.identity = &data->partner_ident; |
899 | |
900 | data->port = typec_register_port(parent: &i2c->dev, cap: &typec_cap); |
901 | if (IS_ERR(ptr: data->port)) { |
902 | ret = PTR_ERR(ptr: data->port); |
903 | dev_err(&i2c->dev, "Failed to register typec port (%d)\n" , ret); |
904 | goto err_role_put; |
905 | } |
906 | |
907 | ret = rt1719_init_attach_state(data); |
908 | if (ret) { |
909 | dev_err(&i2c->dev, "Failed to init attach state (%d)\n" , ret); |
910 | goto err_role_put; |
911 | } |
912 | |
913 | ret = rt1719_irq_init(data); |
914 | if (ret) { |
915 | dev_err(&i2c->dev, "Failed to init irq\n" ); |
916 | goto err_role_put; |
917 | } |
918 | |
919 | fwnode_handle_put(fwnode); |
920 | |
921 | i2c_set_clientdata(client: i2c, data); |
922 | |
923 | return 0; |
924 | |
925 | err_role_put: |
926 | usb_role_switch_put(sw: data->role_sw); |
927 | err_fwnode_put: |
928 | fwnode_handle_put(fwnode); |
929 | |
930 | return ret; |
931 | } |
932 | |
933 | static void rt1719_remove(struct i2c_client *i2c) |
934 | { |
935 | struct rt1719_data *data = i2c_get_clientdata(client: i2c); |
936 | |
937 | typec_unregister_port(port: data->port); |
938 | usb_role_switch_put(sw: data->role_sw); |
939 | } |
940 | |
941 | static const struct of_device_id __maybe_unused rt1719_device_table[] = { |
942 | { .compatible = "richtek,rt1719" , }, |
943 | { } |
944 | }; |
945 | MODULE_DEVICE_TABLE(of, rt1719_device_table); |
946 | |
947 | static struct i2c_driver rt1719_driver = { |
948 | .driver = { |
949 | .name = "rt1719" , |
950 | .of_match_table = rt1719_device_table, |
951 | }, |
952 | .probe = rt1719_probe, |
953 | .remove = rt1719_remove, |
954 | }; |
955 | module_i2c_driver(rt1719_driver); |
956 | |
957 | MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>" ); |
958 | MODULE_DESCRIPTION("Richtek RT1719 Sink Only USBPD Controller Driver" ); |
959 | MODULE_LICENSE("GPL v2" ); |
960 | |