1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * USB Type-C Connector System Software Interface driver |
4 | * |
5 | * Copyright (C) 2017, Intel Corporation |
6 | * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> |
7 | */ |
8 | |
9 | #include <linux/completion.h> |
10 | #include <linux/property.h> |
11 | #include <linux/device.h> |
12 | #include <linux/module.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/usb/typec_dp.h> |
16 | |
17 | #include "ucsi.h" |
18 | #include "trace.h" |
19 | |
20 | /* |
21 | * UCSI_TIMEOUT_MS - PPM communication timeout |
22 | * |
23 | * Ideally we could use MIN_TIME_TO_RESPOND_WITH_BUSY (which is defined in UCSI |
24 | * specification) here as reference, but unfortunately we can't. It is very |
25 | * difficult to estimate the time it takes for the system to process the command |
26 | * before it is actually passed to the PPM. |
27 | */ |
28 | #define UCSI_TIMEOUT_MS 5000 |
29 | |
30 | /* |
31 | * UCSI_SWAP_TIMEOUT_MS - Timeout for role swap requests |
32 | * |
33 | * 5 seconds is close to the time it takes for CapsCounter to reach 0, so even |
34 | * if the PPM does not generate Connector Change events before that with |
35 | * partners that do not support USB Power Delivery, this should still work. |
36 | */ |
37 | #define UCSI_SWAP_TIMEOUT_MS 5000 |
38 | |
39 | static int ucsi_read_message_in(struct ucsi *ucsi, void *buf, |
40 | size_t buf_size) |
41 | { |
42 | /* |
43 | * Below UCSI 2.0, MESSAGE_IN was limited to 16 bytes. Truncate the |
44 | * reads here. |
45 | */ |
46 | if (ucsi->version <= UCSI_VERSION_1_2) |
47 | buf_size = clamp(buf_size, 0, 16); |
48 | |
49 | return ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, buf, buf_size); |
50 | } |
51 | |
52 | static int ucsi_acknowledge_command(struct ucsi *ucsi) |
53 | { |
54 | u64 ctrl; |
55 | |
56 | ctrl = UCSI_ACK_CC_CI; |
57 | ctrl |= UCSI_ACK_COMMAND_COMPLETE; |
58 | |
59 | return ucsi->ops->sync_write(ucsi, UCSI_CONTROL, &ctrl, sizeof(ctrl)); |
60 | } |
61 | |
62 | static int ucsi_acknowledge_connector_change(struct ucsi *ucsi) |
63 | { |
64 | u64 ctrl; |
65 | |
66 | ctrl = UCSI_ACK_CC_CI; |
67 | ctrl |= UCSI_ACK_CONNECTOR_CHANGE; |
68 | |
69 | return ucsi->ops->sync_write(ucsi, UCSI_CONTROL, &ctrl, sizeof(ctrl)); |
70 | } |
71 | |
72 | static int ucsi_exec_command(struct ucsi *ucsi, u64 command); |
73 | |
74 | static int ucsi_read_error(struct ucsi *ucsi) |
75 | { |
76 | u16 error; |
77 | int ret; |
78 | |
79 | /* Acknowledge the command that failed */ |
80 | ret = ucsi_acknowledge_command(ucsi); |
81 | if (ret) |
82 | return ret; |
83 | |
84 | ret = ucsi_exec_command(ucsi, UCSI_GET_ERROR_STATUS); |
85 | if (ret < 0) |
86 | return ret; |
87 | |
88 | ret = ucsi_read_message_in(ucsi, buf: &error, buf_size: sizeof(error)); |
89 | if (ret) |
90 | return ret; |
91 | |
92 | ret = ucsi_acknowledge_command(ucsi); |
93 | if (ret) |
94 | return ret; |
95 | |
96 | switch (error) { |
97 | case UCSI_ERROR_INCOMPATIBLE_PARTNER: |
98 | return -EOPNOTSUPP; |
99 | case UCSI_ERROR_CC_COMMUNICATION_ERR: |
100 | return -ECOMM; |
101 | case UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL: |
102 | return -EPROTO; |
103 | case UCSI_ERROR_DEAD_BATTERY: |
104 | dev_warn(ucsi->dev, "Dead battery condition!\n" ); |
105 | return -EPERM; |
106 | case UCSI_ERROR_INVALID_CON_NUM: |
107 | case UCSI_ERROR_UNREGONIZED_CMD: |
108 | case UCSI_ERROR_INVALID_CMD_ARGUMENT: |
109 | dev_err(ucsi->dev, "possible UCSI driver bug %u\n" , error); |
110 | return -EINVAL; |
111 | case UCSI_ERROR_OVERCURRENT: |
112 | dev_warn(ucsi->dev, "Overcurrent condition\n" ); |
113 | break; |
114 | case UCSI_ERROR_PARTNER_REJECTED_SWAP: |
115 | dev_warn(ucsi->dev, "Partner rejected swap\n" ); |
116 | break; |
117 | case UCSI_ERROR_HARD_RESET: |
118 | dev_warn(ucsi->dev, "Hard reset occurred\n" ); |
119 | break; |
120 | case UCSI_ERROR_PPM_POLICY_CONFLICT: |
121 | dev_warn(ucsi->dev, "PPM Policy conflict\n" ); |
122 | break; |
123 | case UCSI_ERROR_SWAP_REJECTED: |
124 | dev_warn(ucsi->dev, "Swap rejected\n" ); |
125 | break; |
126 | case UCSI_ERROR_UNDEFINED: |
127 | default: |
128 | dev_err(ucsi->dev, "unknown error %u\n" , error); |
129 | break; |
130 | } |
131 | |
132 | return -EIO; |
133 | } |
134 | |
135 | static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd) |
136 | { |
137 | u32 cci; |
138 | int ret; |
139 | |
140 | ret = ucsi->ops->sync_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); |
141 | if (ret) |
142 | return ret; |
143 | |
144 | ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); |
145 | if (ret) |
146 | return ret; |
147 | |
148 | if (cmd != UCSI_CANCEL && cci & UCSI_CCI_BUSY) |
149 | return ucsi_exec_command(ucsi, UCSI_CANCEL); |
150 | |
151 | if (!(cci & UCSI_CCI_COMMAND_COMPLETE)) |
152 | return -EIO; |
153 | |
154 | if (cci & UCSI_CCI_NOT_SUPPORTED) { |
155 | if (ucsi_acknowledge_command(ucsi) < 0) |
156 | dev_err(ucsi->dev, |
157 | "ACK of unsupported command failed\n" ); |
158 | return -EOPNOTSUPP; |
159 | } |
160 | |
161 | if (cci & UCSI_CCI_ERROR) { |
162 | if (cmd == UCSI_GET_ERROR_STATUS) |
163 | return -EIO; |
164 | return ucsi_read_error(ucsi); |
165 | } |
166 | |
167 | if (cmd == UCSI_CANCEL && cci & UCSI_CCI_CANCEL_COMPLETE) { |
168 | ret = ucsi_acknowledge_command(ucsi); |
169 | return ret ? ret : -EBUSY; |
170 | } |
171 | |
172 | return UCSI_CCI_LENGTH(cci); |
173 | } |
174 | |
175 | int ucsi_send_command(struct ucsi *ucsi, u64 command, |
176 | void *data, size_t size) |
177 | { |
178 | u8 length; |
179 | int ret; |
180 | |
181 | mutex_lock(&ucsi->ppm_lock); |
182 | |
183 | ret = ucsi_exec_command(ucsi, cmd: command); |
184 | if (ret < 0) |
185 | goto out; |
186 | |
187 | length = ret; |
188 | |
189 | if (data) { |
190 | ret = ucsi_read_message_in(ucsi, buf: data, buf_size: size); |
191 | if (ret) |
192 | goto out; |
193 | } |
194 | |
195 | ret = ucsi_acknowledge_command(ucsi); |
196 | if (ret) |
197 | goto out; |
198 | |
199 | ret = length; |
200 | out: |
201 | mutex_unlock(lock: &ucsi->ppm_lock); |
202 | return ret; |
203 | } |
204 | EXPORT_SYMBOL_GPL(ucsi_send_command); |
205 | |
206 | /* -------------------------------------------------------------------------- */ |
207 | |
208 | struct ucsi_work { |
209 | struct delayed_work work; |
210 | struct list_head node; |
211 | unsigned long delay; |
212 | unsigned int count; |
213 | struct ucsi_connector *con; |
214 | int (*cb)(struct ucsi_connector *); |
215 | }; |
216 | |
217 | static void ucsi_poll_worker(struct work_struct *work) |
218 | { |
219 | struct ucsi_work *uwork = container_of(work, struct ucsi_work, work.work); |
220 | struct ucsi_connector *con = uwork->con; |
221 | int ret; |
222 | |
223 | mutex_lock(&con->lock); |
224 | |
225 | if (!con->partner) { |
226 | list_del(entry: &uwork->node); |
227 | mutex_unlock(lock: &con->lock); |
228 | kfree(objp: uwork); |
229 | return; |
230 | } |
231 | |
232 | ret = uwork->cb(con); |
233 | |
234 | if (uwork->count-- && (ret == -EBUSY || ret == -ETIMEDOUT)) { |
235 | queue_delayed_work(wq: con->wq, dwork: &uwork->work, delay: uwork->delay); |
236 | } else { |
237 | list_del(entry: &uwork->node); |
238 | kfree(objp: uwork); |
239 | } |
240 | |
241 | mutex_unlock(lock: &con->lock); |
242 | } |
243 | |
244 | static int ucsi_partner_task(struct ucsi_connector *con, |
245 | int (*cb)(struct ucsi_connector *), |
246 | int retries, unsigned long delay) |
247 | { |
248 | struct ucsi_work *uwork; |
249 | |
250 | if (!con->partner) |
251 | return 0; |
252 | |
253 | uwork = kzalloc(size: sizeof(*uwork), GFP_KERNEL); |
254 | if (!uwork) |
255 | return -ENOMEM; |
256 | |
257 | INIT_DELAYED_WORK(&uwork->work, ucsi_poll_worker); |
258 | uwork->count = retries; |
259 | uwork->delay = delay; |
260 | uwork->con = con; |
261 | uwork->cb = cb; |
262 | |
263 | list_add_tail(new: &uwork->node, head: &con->partner_tasks); |
264 | queue_delayed_work(wq: con->wq, dwork: &uwork->work, delay); |
265 | |
266 | return 0; |
267 | } |
268 | |
269 | /* -------------------------------------------------------------------------- */ |
270 | |
271 | void ucsi_altmode_update_active(struct ucsi_connector *con) |
272 | { |
273 | const struct typec_altmode *altmode = NULL; |
274 | u64 command; |
275 | int ret; |
276 | u8 cur; |
277 | int i; |
278 | |
279 | command = UCSI_GET_CURRENT_CAM | UCSI_CONNECTOR_NUMBER(con->num); |
280 | ret = ucsi_send_command(con->ucsi, command, &cur, sizeof(cur)); |
281 | if (ret < 0) { |
282 | if (con->ucsi->version > 0x0100) { |
283 | dev_err(con->ucsi->dev, |
284 | "GET_CURRENT_CAM command failed\n" ); |
285 | return; |
286 | } |
287 | cur = 0xff; |
288 | } |
289 | |
290 | if (cur < UCSI_MAX_ALTMODES) |
291 | altmode = typec_altmode_get_partner(altmode: con->port_altmode[cur]); |
292 | |
293 | for (i = 0; con->partner_altmode[i]; i++) |
294 | typec_altmode_update_active(alt: con->partner_altmode[i], |
295 | active: con->partner_altmode[i] == altmode); |
296 | } |
297 | |
298 | static int ucsi_altmode_next_mode(struct typec_altmode **alt, u16 svid) |
299 | { |
300 | u8 mode = 1; |
301 | int i; |
302 | |
303 | for (i = 0; alt[i]; i++) { |
304 | if (i > MODE_DISCOVERY_MAX) |
305 | return -ERANGE; |
306 | |
307 | if (alt[i]->svid == svid) |
308 | mode++; |
309 | } |
310 | |
311 | return mode; |
312 | } |
313 | |
314 | static int ucsi_next_altmode(struct typec_altmode **alt) |
315 | { |
316 | int i = 0; |
317 | |
318 | for (i = 0; i < UCSI_MAX_ALTMODES; i++) |
319 | if (!alt[i]) |
320 | return i; |
321 | |
322 | return -ENOENT; |
323 | } |
324 | |
325 | static int ucsi_get_num_altmode(struct typec_altmode **alt) |
326 | { |
327 | int i; |
328 | |
329 | for (i = 0; i < UCSI_MAX_ALTMODES; i++) |
330 | if (!alt[i]) |
331 | break; |
332 | |
333 | return i; |
334 | } |
335 | |
336 | static int ucsi_register_altmode(struct ucsi_connector *con, |
337 | struct typec_altmode_desc *desc, |
338 | u8 recipient) |
339 | { |
340 | struct typec_altmode *alt; |
341 | bool override; |
342 | int ret; |
343 | int i; |
344 | |
345 | override = !!(con->ucsi->cap.features & UCSI_CAP_ALT_MODE_OVERRIDE); |
346 | |
347 | switch (recipient) { |
348 | case UCSI_RECIPIENT_CON: |
349 | i = ucsi_next_altmode(alt: con->port_altmode); |
350 | if (i < 0) { |
351 | ret = i; |
352 | goto err; |
353 | } |
354 | |
355 | ret = ucsi_altmode_next_mode(alt: con->port_altmode, svid: desc->svid); |
356 | if (ret < 0) |
357 | return ret; |
358 | |
359 | desc->mode = ret; |
360 | |
361 | switch (desc->svid) { |
362 | case USB_TYPEC_DP_SID: |
363 | alt = ucsi_register_displayport(con, override, offset: i, desc); |
364 | break; |
365 | case USB_TYPEC_NVIDIA_VLINK_SID: |
366 | if (desc->vdo == USB_TYPEC_NVIDIA_VLINK_DBG_VDO) |
367 | alt = typec_port_register_altmode(port: con->port, |
368 | desc); |
369 | else |
370 | alt = ucsi_register_displayport(con, override, |
371 | offset: i, desc); |
372 | break; |
373 | default: |
374 | alt = typec_port_register_altmode(port: con->port, desc); |
375 | break; |
376 | } |
377 | |
378 | if (IS_ERR(ptr: alt)) { |
379 | ret = PTR_ERR(ptr: alt); |
380 | goto err; |
381 | } |
382 | |
383 | con->port_altmode[i] = alt; |
384 | break; |
385 | case UCSI_RECIPIENT_SOP: |
386 | i = ucsi_next_altmode(alt: con->partner_altmode); |
387 | if (i < 0) { |
388 | ret = i; |
389 | goto err; |
390 | } |
391 | |
392 | ret = ucsi_altmode_next_mode(alt: con->partner_altmode, svid: desc->svid); |
393 | if (ret < 0) |
394 | return ret; |
395 | |
396 | desc->mode = ret; |
397 | |
398 | alt = typec_partner_register_altmode(partner: con->partner, desc); |
399 | if (IS_ERR(ptr: alt)) { |
400 | ret = PTR_ERR(ptr: alt); |
401 | goto err; |
402 | } |
403 | |
404 | con->partner_altmode[i] = alt; |
405 | break; |
406 | case UCSI_RECIPIENT_SOP_P: |
407 | i = ucsi_next_altmode(alt: con->plug_altmode); |
408 | if (i < 0) { |
409 | ret = i; |
410 | goto err; |
411 | } |
412 | |
413 | ret = ucsi_altmode_next_mode(alt: con->plug_altmode, svid: desc->svid); |
414 | if (ret < 0) |
415 | return ret; |
416 | |
417 | desc->mode = ret; |
418 | |
419 | alt = typec_plug_register_altmode(plug: con->plug, desc); |
420 | if (IS_ERR(ptr: alt)) { |
421 | ret = PTR_ERR(ptr: alt); |
422 | goto err; |
423 | } |
424 | |
425 | con->plug_altmode[i] = alt; |
426 | break; |
427 | default: |
428 | return -EINVAL; |
429 | } |
430 | |
431 | trace_ucsi_register_altmode(recipient, alt); |
432 | |
433 | return 0; |
434 | |
435 | err: |
436 | dev_err(con->ucsi->dev, "failed to registers svid 0x%04x mode %d\n" , |
437 | desc->svid, desc->mode); |
438 | |
439 | return ret; |
440 | } |
441 | |
442 | static int |
443 | ucsi_register_altmodes_nvidia(struct ucsi_connector *con, u8 recipient) |
444 | { |
445 | int max_altmodes = UCSI_MAX_ALTMODES; |
446 | struct typec_altmode_desc desc; |
447 | struct ucsi_altmode alt; |
448 | struct ucsi_altmode orig[UCSI_MAX_ALTMODES]; |
449 | struct ucsi_altmode updated[UCSI_MAX_ALTMODES]; |
450 | struct ucsi *ucsi = con->ucsi; |
451 | bool multi_dp = false; |
452 | u64 command; |
453 | int ret; |
454 | int len; |
455 | int i; |
456 | int k = 0; |
457 | |
458 | if (recipient == UCSI_RECIPIENT_CON) |
459 | max_altmodes = con->ucsi->cap.num_alt_modes; |
460 | |
461 | memset(orig, 0, sizeof(orig)); |
462 | memset(updated, 0, sizeof(updated)); |
463 | |
464 | /* First get all the alternate modes */ |
465 | for (i = 0; i < max_altmodes; i++) { |
466 | memset(&alt, 0, sizeof(alt)); |
467 | command = UCSI_GET_ALTERNATE_MODES; |
468 | command |= UCSI_GET_ALTMODE_RECIPIENT(recipient); |
469 | command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num); |
470 | command |= UCSI_GET_ALTMODE_OFFSET(i); |
471 | len = ucsi_send_command(con->ucsi, command, &alt, sizeof(alt)); |
472 | /* |
473 | * We are collecting all altmodes first and then registering. |
474 | * Some type-C device will return zero length data beyond last |
475 | * alternate modes. We should not return if length is zero. |
476 | */ |
477 | if (len < 0) |
478 | return len; |
479 | |
480 | /* We got all altmodes, now break out and register them */ |
481 | if (!len || !alt.svid) |
482 | break; |
483 | |
484 | orig[k].mid = alt.mid; |
485 | orig[k].svid = alt.svid; |
486 | k++; |
487 | } |
488 | /* |
489 | * Update the original altmode table as some ppms may report |
490 | * multiple DP altmodes. |
491 | */ |
492 | if (recipient == UCSI_RECIPIENT_CON) |
493 | multi_dp = ucsi->ops->update_altmodes(ucsi, orig, updated); |
494 | |
495 | /* now register altmodes */ |
496 | for (i = 0; i < max_altmodes; i++) { |
497 | memset(&desc, 0, sizeof(desc)); |
498 | if (multi_dp && recipient == UCSI_RECIPIENT_CON) { |
499 | desc.svid = updated[i].svid; |
500 | desc.vdo = updated[i].mid; |
501 | } else { |
502 | desc.svid = orig[i].svid; |
503 | desc.vdo = orig[i].mid; |
504 | } |
505 | desc.roles = TYPEC_PORT_DRD; |
506 | |
507 | if (!desc.svid) |
508 | return 0; |
509 | |
510 | ret = ucsi_register_altmode(con, desc: &desc, recipient); |
511 | if (ret) |
512 | return ret; |
513 | } |
514 | |
515 | return 0; |
516 | } |
517 | |
518 | static int ucsi_register_altmodes(struct ucsi_connector *con, u8 recipient) |
519 | { |
520 | int max_altmodes = UCSI_MAX_ALTMODES; |
521 | struct typec_altmode_desc desc; |
522 | struct ucsi_altmode alt[2]; |
523 | u64 command; |
524 | int num; |
525 | int ret; |
526 | int len; |
527 | int j; |
528 | int i; |
529 | |
530 | if (!(con->ucsi->cap.features & UCSI_CAP_ALT_MODE_DETAILS)) |
531 | return 0; |
532 | |
533 | if (recipient == UCSI_RECIPIENT_SOP && con->partner_altmode[0]) |
534 | return 0; |
535 | |
536 | if (con->ucsi->ops->update_altmodes) |
537 | return ucsi_register_altmodes_nvidia(con, recipient); |
538 | |
539 | if (recipient == UCSI_RECIPIENT_CON) |
540 | max_altmodes = con->ucsi->cap.num_alt_modes; |
541 | |
542 | for (i = 0; i < max_altmodes;) { |
543 | memset(alt, 0, sizeof(alt)); |
544 | command = UCSI_GET_ALTERNATE_MODES; |
545 | command |= UCSI_GET_ALTMODE_RECIPIENT(recipient); |
546 | command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num); |
547 | command |= UCSI_GET_ALTMODE_OFFSET(i); |
548 | len = ucsi_send_command(con->ucsi, command, alt, sizeof(alt)); |
549 | if (len == -EBUSY) |
550 | continue; |
551 | if (len <= 0) |
552 | return len; |
553 | |
554 | /* |
555 | * This code is requesting one alt mode at a time, but some PPMs |
556 | * may still return two. If that happens both alt modes need be |
557 | * registered and the offset for the next alt mode has to be |
558 | * incremented. |
559 | */ |
560 | num = len / sizeof(alt[0]); |
561 | i += num; |
562 | |
563 | for (j = 0; j < num; j++) { |
564 | if (!alt[j].svid) |
565 | return 0; |
566 | |
567 | memset(&desc, 0, sizeof(desc)); |
568 | desc.vdo = alt[j].mid; |
569 | desc.svid = alt[j].svid; |
570 | desc.roles = TYPEC_PORT_DRD; |
571 | |
572 | ret = ucsi_register_altmode(con, desc: &desc, recipient); |
573 | if (ret) |
574 | return ret; |
575 | } |
576 | } |
577 | |
578 | return 0; |
579 | } |
580 | |
581 | static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient) |
582 | { |
583 | const struct typec_altmode *pdev; |
584 | struct typec_altmode **adev; |
585 | int i = 0; |
586 | |
587 | switch (recipient) { |
588 | case UCSI_RECIPIENT_CON: |
589 | adev = con->port_altmode; |
590 | break; |
591 | case UCSI_RECIPIENT_SOP: |
592 | adev = con->partner_altmode; |
593 | break; |
594 | case UCSI_RECIPIENT_SOP_P: |
595 | adev = con->plug_altmode; |
596 | break; |
597 | default: |
598 | return; |
599 | } |
600 | |
601 | while (adev[i]) { |
602 | if (recipient == UCSI_RECIPIENT_SOP && |
603 | (adev[i]->svid == USB_TYPEC_DP_SID || |
604 | (adev[i]->svid == USB_TYPEC_NVIDIA_VLINK_SID && |
605 | adev[i]->vdo != USB_TYPEC_NVIDIA_VLINK_DBG_VDO))) { |
606 | pdev = typec_altmode_get_partner(altmode: adev[i]); |
607 | ucsi_displayport_remove_partner(adev: (void *)pdev); |
608 | } |
609 | typec_unregister_altmode(altmode: adev[i]); |
610 | adev[i++] = NULL; |
611 | } |
612 | } |
613 | |
614 | static int ucsi_read_pdos(struct ucsi_connector *con, |
615 | enum typec_role role, int is_partner, |
616 | u32 *pdos, int offset, int num_pdos) |
617 | { |
618 | struct ucsi *ucsi = con->ucsi; |
619 | u64 command; |
620 | int ret; |
621 | |
622 | if (ucsi->quirks & UCSI_NO_PARTNER_PDOS) |
623 | return 0; |
624 | |
625 | command = UCSI_COMMAND(UCSI_GET_PDOS) | UCSI_CONNECTOR_NUMBER(con->num); |
626 | command |= UCSI_GET_PDOS_PARTNER_PDO(is_partner); |
627 | command |= UCSI_GET_PDOS_PDO_OFFSET(offset); |
628 | command |= UCSI_GET_PDOS_NUM_PDOS(num_pdos - 1); |
629 | command |= is_source(role) ? UCSI_GET_PDOS_SRC_PDOS : 0; |
630 | ret = ucsi_send_command(ucsi, command, pdos + offset, |
631 | num_pdos * sizeof(u32)); |
632 | if (ret < 0 && ret != -ETIMEDOUT) |
633 | dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n" , ret); |
634 | |
635 | return ret; |
636 | } |
637 | |
638 | static int ucsi_get_pdos(struct ucsi_connector *con, enum typec_role role, |
639 | int is_partner, u32 *pdos) |
640 | { |
641 | u8 num_pdos; |
642 | int ret; |
643 | |
644 | /* UCSI max payload means only getting at most 4 PDOs at a time */ |
645 | ret = ucsi_read_pdos(con, role, is_partner, pdos, offset: 0, UCSI_MAX_PDOS); |
646 | if (ret < 0) |
647 | return ret; |
648 | |
649 | num_pdos = ret / sizeof(u32); /* number of bytes to 32-bit PDOs */ |
650 | if (num_pdos < UCSI_MAX_PDOS) |
651 | return num_pdos; |
652 | |
653 | /* get the remaining PDOs, if any */ |
654 | ret = ucsi_read_pdos(con, role, is_partner, pdos, UCSI_MAX_PDOS, |
655 | PDO_MAX_OBJECTS - UCSI_MAX_PDOS); |
656 | if (ret < 0) |
657 | return ret; |
658 | |
659 | return ret / sizeof(u32) + num_pdos; |
660 | } |
661 | |
662 | static int ucsi_get_src_pdos(struct ucsi_connector *con) |
663 | { |
664 | int ret; |
665 | |
666 | ret = ucsi_get_pdos(con, role: TYPEC_SOURCE, is_partner: 1, pdos: con->src_pdos); |
667 | if (ret < 0) |
668 | return ret; |
669 | |
670 | con->num_pdos = ret; |
671 | |
672 | ucsi_port_psy_changed(con); |
673 | |
674 | return ret; |
675 | } |
676 | |
677 | static int ucsi_read_identity(struct ucsi_connector *con, u8 recipient, |
678 | u8 offset, u8 bytes, void *resp) |
679 | { |
680 | struct ucsi *ucsi = con->ucsi; |
681 | u64 command; |
682 | int ret; |
683 | |
684 | command = UCSI_COMMAND(UCSI_GET_PD_MESSAGE) | |
685 | UCSI_CONNECTOR_NUMBER(con->num); |
686 | command |= UCSI_GET_PD_MESSAGE_RECIPIENT(recipient); |
687 | command |= UCSI_GET_PD_MESSAGE_OFFSET(offset); |
688 | command |= UCSI_GET_PD_MESSAGE_BYTES(bytes); |
689 | command |= UCSI_GET_PD_MESSAGE_TYPE(UCSI_GET_PD_MESSAGE_TYPE_IDENTITY); |
690 | |
691 | ret = ucsi_send_command(ucsi, command, resp, bytes); |
692 | if (ret < 0) |
693 | dev_err(ucsi->dev, "UCSI_GET_PD_MESSAGE failed (%d)\n" , ret); |
694 | |
695 | return ret; |
696 | } |
697 | |
698 | static int ucsi_get_identity(struct ucsi_connector *con, u8 recipient, |
699 | struct usb_pd_identity *id) |
700 | { |
701 | struct ucsi *ucsi = con->ucsi; |
702 | struct ucsi_pd_message_disc_id resp = {}; |
703 | int ret; |
704 | |
705 | if (ucsi->version < UCSI_VERSION_2_0) { |
706 | /* |
707 | * Before UCSI v2.0, MESSAGE_IN is 16 bytes which cannot fit |
708 | * the 28 byte identity response including the VDM header. |
709 | * First request the VDM header, ID Header VDO, Cert Stat VDO |
710 | * and Product VDO. |
711 | */ |
712 | ret = ucsi_read_identity(con, recipient, offset: 0, bytes: 0x10, resp: &resp); |
713 | if (ret < 0) |
714 | return ret; |
715 | |
716 | |
717 | /* Then request Product Type VDO1 through Product Type VDO3. */ |
718 | ret = ucsi_read_identity(con, recipient, offset: 0x10, bytes: 0xc, |
719 | resp: &resp.vdo[0]); |
720 | if (ret < 0) |
721 | return ret; |
722 | |
723 | } else { |
724 | /* |
725 | * In UCSI v2.0 and after, MESSAGE_IN is large enough to request |
726 | * the large enough to request the full Discover Identity |
727 | * response at once. |
728 | */ |
729 | ret = ucsi_read_identity(con, recipient, offset: 0x0, bytes: 0x1c, resp: &resp); |
730 | if (ret < 0) |
731 | return ret; |
732 | } |
733 | |
734 | id->id_header = resp.id_header; |
735 | id->cert_stat = resp.cert_stat; |
736 | id->product = resp.product; |
737 | id->vdo[0] = resp.vdo[0]; |
738 | id->vdo[1] = resp.vdo[1]; |
739 | id->vdo[2] = resp.vdo[2]; |
740 | return 0; |
741 | } |
742 | |
743 | static int ucsi_get_partner_identity(struct ucsi_connector *con) |
744 | { |
745 | int ret; |
746 | |
747 | ret = ucsi_get_identity(con, UCSI_RECIPIENT_SOP, |
748 | id: &con->partner_identity); |
749 | if (ret < 0) |
750 | return ret; |
751 | |
752 | ret = typec_partner_set_identity(partner: con->partner); |
753 | if (ret < 0) { |
754 | dev_err(con->ucsi->dev, "Failed to set partner identity (%d)\n" , |
755 | ret); |
756 | } |
757 | |
758 | return ret; |
759 | } |
760 | |
761 | static int ucsi_get_cable_identity(struct ucsi_connector *con) |
762 | { |
763 | int ret; |
764 | |
765 | ret = ucsi_get_identity(con, UCSI_RECIPIENT_SOP_P, |
766 | id: &con->cable_identity); |
767 | if (ret < 0) |
768 | return ret; |
769 | |
770 | ret = typec_cable_set_identity(cable: con->cable); |
771 | if (ret < 0) { |
772 | dev_err(con->ucsi->dev, "Failed to set cable identity (%d)\n" , |
773 | ret); |
774 | } |
775 | |
776 | return ret; |
777 | } |
778 | |
779 | static int ucsi_check_altmodes(struct ucsi_connector *con) |
780 | { |
781 | int ret, num_partner_am; |
782 | |
783 | ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP); |
784 | if (ret && ret != -ETIMEDOUT) |
785 | dev_err(con->ucsi->dev, |
786 | "con%d: failed to register partner alt modes (%d)\n" , |
787 | con->num, ret); |
788 | |
789 | /* Ignoring the errors in this case. */ |
790 | if (con->partner_altmode[0]) { |
791 | num_partner_am = ucsi_get_num_altmode(alt: con->partner_altmode); |
792 | if (num_partner_am > 0) |
793 | typec_partner_set_num_altmodes(partner: con->partner, num_altmodes: num_partner_am); |
794 | ucsi_altmode_update_active(con); |
795 | return 0; |
796 | } |
797 | |
798 | return ret; |
799 | } |
800 | |
801 | static int ucsi_register_partner_pdos(struct ucsi_connector *con) |
802 | { |
803 | struct usb_power_delivery_desc desc = { con->ucsi->cap.pd_version }; |
804 | struct usb_power_delivery_capabilities_desc caps; |
805 | struct usb_power_delivery_capabilities *cap; |
806 | int ret; |
807 | |
808 | if (con->partner_pd) |
809 | return 0; |
810 | |
811 | con->partner_pd = usb_power_delivery_register(NULL, desc: &desc); |
812 | if (IS_ERR(ptr: con->partner_pd)) |
813 | return PTR_ERR(ptr: con->partner_pd); |
814 | |
815 | ret = ucsi_get_pdos(con, role: TYPEC_SOURCE, is_partner: 1, pdos: caps.pdo); |
816 | if (ret > 0) { |
817 | if (ret < PDO_MAX_OBJECTS) |
818 | caps.pdo[ret] = 0; |
819 | |
820 | caps.role = TYPEC_SOURCE; |
821 | cap = usb_power_delivery_register_capabilities(pd: con->partner_pd, desc: &caps); |
822 | if (IS_ERR(ptr: cap)) |
823 | return PTR_ERR(ptr: cap); |
824 | |
825 | con->partner_source_caps = cap; |
826 | |
827 | ret = typec_partner_set_usb_power_delivery(partner: con->partner, pd: con->partner_pd); |
828 | if (ret) { |
829 | usb_power_delivery_unregister_capabilities(cap: con->partner_source_caps); |
830 | return ret; |
831 | } |
832 | } |
833 | |
834 | ret = ucsi_get_pdos(con, role: TYPEC_SINK, is_partner: 1, pdos: caps.pdo); |
835 | if (ret > 0) { |
836 | if (ret < PDO_MAX_OBJECTS) |
837 | caps.pdo[ret] = 0; |
838 | |
839 | caps.role = TYPEC_SINK; |
840 | |
841 | cap = usb_power_delivery_register_capabilities(pd: con->partner_pd, desc: &caps); |
842 | if (IS_ERR(ptr: cap)) |
843 | return PTR_ERR(ptr: cap); |
844 | |
845 | con->partner_sink_caps = cap; |
846 | |
847 | ret = typec_partner_set_usb_power_delivery(partner: con->partner, pd: con->partner_pd); |
848 | if (ret) { |
849 | usb_power_delivery_unregister_capabilities(cap: con->partner_sink_caps); |
850 | return ret; |
851 | } |
852 | } |
853 | |
854 | return 0; |
855 | } |
856 | |
857 | static void ucsi_unregister_partner_pdos(struct ucsi_connector *con) |
858 | { |
859 | usb_power_delivery_unregister_capabilities(cap: con->partner_sink_caps); |
860 | con->partner_sink_caps = NULL; |
861 | usb_power_delivery_unregister_capabilities(cap: con->partner_source_caps); |
862 | con->partner_source_caps = NULL; |
863 | usb_power_delivery_unregister(pd: con->partner_pd); |
864 | con->partner_pd = NULL; |
865 | } |
866 | |
867 | static int ucsi_register_plug(struct ucsi_connector *con) |
868 | { |
869 | struct typec_plug *plug; |
870 | struct typec_plug_desc desc = {.index = TYPEC_PLUG_SOP_P}; |
871 | |
872 | plug = typec_register_plug(cable: con->cable, desc: &desc); |
873 | if (IS_ERR(ptr: plug)) { |
874 | dev_err(con->ucsi->dev, |
875 | "con%d: failed to register plug (%ld)\n" , con->num, |
876 | PTR_ERR(plug)); |
877 | return PTR_ERR(ptr: plug); |
878 | } |
879 | |
880 | con->plug = plug; |
881 | return 0; |
882 | } |
883 | |
884 | static void ucsi_unregister_plug(struct ucsi_connector *con) |
885 | { |
886 | if (!con->plug) |
887 | return; |
888 | |
889 | ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP_P); |
890 | typec_unregister_plug(plug: con->plug); |
891 | con->plug = NULL; |
892 | } |
893 | |
894 | static int ucsi_register_cable(struct ucsi_connector *con) |
895 | { |
896 | struct typec_cable *cable; |
897 | struct typec_cable_desc desc = {}; |
898 | |
899 | switch (UCSI_CABLE_PROP_FLAG_PLUG_TYPE(con->cable_prop.flags)) { |
900 | case UCSI_CABLE_PROPERTY_PLUG_TYPE_A: |
901 | desc.type = USB_PLUG_TYPE_A; |
902 | break; |
903 | case UCSI_CABLE_PROPERTY_PLUG_TYPE_B: |
904 | desc.type = USB_PLUG_TYPE_B; |
905 | break; |
906 | case UCSI_CABLE_PROPERTY_PLUG_TYPE_C: |
907 | desc.type = USB_PLUG_TYPE_C; |
908 | break; |
909 | default: |
910 | desc.type = USB_PLUG_NONE; |
911 | break; |
912 | } |
913 | |
914 | desc.identity = &con->cable_identity; |
915 | desc.active = !!(UCSI_CABLE_PROP_FLAG_ACTIVE_CABLE & |
916 | con->cable_prop.flags); |
917 | desc.pd_revision = UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV_AS_BCD( |
918 | con->cable_prop.flags); |
919 | |
920 | cable = typec_register_cable(port: con->port, desc: &desc); |
921 | if (IS_ERR(ptr: cable)) { |
922 | dev_err(con->ucsi->dev, |
923 | "con%d: failed to register cable (%ld)\n" , con->num, |
924 | PTR_ERR(cable)); |
925 | return PTR_ERR(ptr: cable); |
926 | } |
927 | |
928 | con->cable = cable; |
929 | return 0; |
930 | } |
931 | |
932 | static void ucsi_unregister_cable(struct ucsi_connector *con) |
933 | { |
934 | if (!con->cable) |
935 | return; |
936 | |
937 | ucsi_unregister_plug(con); |
938 | typec_unregister_cable(cable: con->cable); |
939 | memset(&con->cable_identity, 0, sizeof(con->cable_identity)); |
940 | con->cable = NULL; |
941 | } |
942 | |
943 | static void ucsi_pwr_opmode_change(struct ucsi_connector *con) |
944 | { |
945 | switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { |
946 | case UCSI_CONSTAT_PWR_OPMODE_PD: |
947 | con->rdo = con->status.request_data_obj; |
948 | typec_set_pwr_opmode(port: con->port, mode: TYPEC_PWR_MODE_PD); |
949 | ucsi_partner_task(con, cb: ucsi_get_src_pdos, retries: 30, delay: 0); |
950 | ucsi_partner_task(con, cb: ucsi_check_altmodes, retries: 30, delay: 0); |
951 | ucsi_partner_task(con, cb: ucsi_register_partner_pdos, retries: 1, HZ); |
952 | break; |
953 | case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: |
954 | con->rdo = 0; |
955 | typec_set_pwr_opmode(port: con->port, mode: TYPEC_PWR_MODE_1_5A); |
956 | break; |
957 | case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0: |
958 | con->rdo = 0; |
959 | typec_set_pwr_opmode(port: con->port, mode: TYPEC_PWR_MODE_3_0A); |
960 | break; |
961 | default: |
962 | con->rdo = 0; |
963 | typec_set_pwr_opmode(port: con->port, mode: TYPEC_PWR_MODE_USB); |
964 | break; |
965 | } |
966 | } |
967 | |
968 | static int ucsi_register_partner(struct ucsi_connector *con) |
969 | { |
970 | u8 pwr_opmode = UCSI_CONSTAT_PWR_OPMODE(con->status.flags); |
971 | struct typec_partner_desc desc; |
972 | struct typec_partner *partner; |
973 | |
974 | if (con->partner) |
975 | return 0; |
976 | |
977 | memset(&desc, 0, sizeof(desc)); |
978 | |
979 | switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { |
980 | case UCSI_CONSTAT_PARTNER_TYPE_DEBUG: |
981 | desc.accessory = TYPEC_ACCESSORY_DEBUG; |
982 | break; |
983 | case UCSI_CONSTAT_PARTNER_TYPE_AUDIO: |
984 | desc.accessory = TYPEC_ACCESSORY_AUDIO; |
985 | break; |
986 | default: |
987 | break; |
988 | } |
989 | |
990 | desc.identity = &con->partner_identity; |
991 | desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD; |
992 | desc.pd_revision = UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags); |
993 | |
994 | partner = typec_register_partner(port: con->port, desc: &desc); |
995 | if (IS_ERR(ptr: partner)) { |
996 | dev_err(con->ucsi->dev, |
997 | "con%d: failed to register partner (%ld)\n" , con->num, |
998 | PTR_ERR(partner)); |
999 | return PTR_ERR(ptr: partner); |
1000 | } |
1001 | |
1002 | con->partner = partner; |
1003 | |
1004 | return 0; |
1005 | } |
1006 | |
1007 | static void ucsi_unregister_partner(struct ucsi_connector *con) |
1008 | { |
1009 | if (!con->partner) |
1010 | return; |
1011 | |
1012 | typec_set_mode(port: con->port, mode: TYPEC_STATE_SAFE); |
1013 | |
1014 | typec_partner_set_usb_power_delivery(partner: con->partner, NULL); |
1015 | ucsi_unregister_partner_pdos(con); |
1016 | ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP); |
1017 | ucsi_unregister_cable(con); |
1018 | typec_unregister_partner(partner: con->partner); |
1019 | memset(&con->partner_identity, 0, sizeof(con->partner_identity)); |
1020 | con->partner = NULL; |
1021 | } |
1022 | |
1023 | static void ucsi_partner_change(struct ucsi_connector *con) |
1024 | { |
1025 | enum usb_role u_role = USB_ROLE_NONE; |
1026 | int ret; |
1027 | |
1028 | switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { |
1029 | case UCSI_CONSTAT_PARTNER_TYPE_UFP: |
1030 | case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP: |
1031 | u_role = USB_ROLE_HOST; |
1032 | fallthrough; |
1033 | case UCSI_CONSTAT_PARTNER_TYPE_CABLE: |
1034 | typec_set_data_role(port: con->port, role: TYPEC_HOST); |
1035 | break; |
1036 | case UCSI_CONSTAT_PARTNER_TYPE_DFP: |
1037 | u_role = USB_ROLE_DEVICE; |
1038 | typec_set_data_role(port: con->port, role: TYPEC_DEVICE); |
1039 | break; |
1040 | default: |
1041 | break; |
1042 | } |
1043 | |
1044 | if (con->status.flags & UCSI_CONSTAT_CONNECTED) { |
1045 | switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { |
1046 | case UCSI_CONSTAT_PARTNER_TYPE_DEBUG: |
1047 | typec_set_mode(port: con->port, mode: TYPEC_MODE_DEBUG); |
1048 | break; |
1049 | case UCSI_CONSTAT_PARTNER_TYPE_AUDIO: |
1050 | typec_set_mode(port: con->port, mode: TYPEC_MODE_AUDIO); |
1051 | break; |
1052 | default: |
1053 | if (UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) == |
1054 | UCSI_CONSTAT_PARTNER_FLAG_USB) |
1055 | typec_set_mode(port: con->port, mode: TYPEC_STATE_USB); |
1056 | } |
1057 | } |
1058 | |
1059 | /* Only notify USB controller if partner supports USB data */ |
1060 | if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB)) |
1061 | u_role = USB_ROLE_NONE; |
1062 | |
1063 | ret = usb_role_switch_set_role(sw: con->usb_role_sw, role: u_role); |
1064 | if (ret) |
1065 | dev_err(con->ucsi->dev, "con:%d: failed to set usb role:%d\n" , |
1066 | con->num, u_role); |
1067 | } |
1068 | |
1069 | static int ucsi_check_connector_capability(struct ucsi_connector *con) |
1070 | { |
1071 | u64 command; |
1072 | int ret; |
1073 | |
1074 | if (!con->partner || con->ucsi->version < UCSI_VERSION_2_0) |
1075 | return 0; |
1076 | |
1077 | command = UCSI_GET_CONNECTOR_CAPABILITY | UCSI_CONNECTOR_NUMBER(con->num); |
1078 | ret = ucsi_send_command(con->ucsi, command, &con->cap, sizeof(con->cap)); |
1079 | if (ret < 0) { |
1080 | dev_err(con->ucsi->dev, "GET_CONNECTOR_CAPABILITY failed (%d)\n" , ret); |
1081 | return ret; |
1082 | } |
1083 | |
1084 | typec_partner_set_pd_revision(partner: con->partner, |
1085 | UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags)); |
1086 | |
1087 | return ret; |
1088 | } |
1089 | |
1090 | static int ucsi_check_connection(struct ucsi_connector *con) |
1091 | { |
1092 | u8 prev_flags = con->status.flags; |
1093 | u64 command; |
1094 | int ret; |
1095 | |
1096 | command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); |
1097 | ret = ucsi_send_command(con->ucsi, command, &con->status, sizeof(con->status)); |
1098 | if (ret < 0) { |
1099 | dev_err(con->ucsi->dev, "GET_CONNECTOR_STATUS failed (%d)\n" , ret); |
1100 | return ret; |
1101 | } |
1102 | |
1103 | if (con->status.flags == prev_flags) |
1104 | return 0; |
1105 | |
1106 | if (con->status.flags & UCSI_CONSTAT_CONNECTED) { |
1107 | ucsi_register_partner(con); |
1108 | ucsi_pwr_opmode_change(con); |
1109 | ucsi_partner_change(con); |
1110 | } else { |
1111 | ucsi_partner_change(con); |
1112 | ucsi_port_psy_changed(con); |
1113 | ucsi_unregister_partner(con); |
1114 | } |
1115 | |
1116 | return 0; |
1117 | } |
1118 | |
1119 | static int ucsi_check_cable(struct ucsi_connector *con) |
1120 | { |
1121 | u64 command; |
1122 | int ret; |
1123 | |
1124 | if (con->cable) |
1125 | return 0; |
1126 | |
1127 | command = UCSI_GET_CABLE_PROPERTY | UCSI_CONNECTOR_NUMBER(con->num); |
1128 | ret = ucsi_send_command(con->ucsi, command, &con->cable_prop, |
1129 | sizeof(con->cable_prop)); |
1130 | if (ret < 0) { |
1131 | dev_err(con->ucsi->dev, "GET_CABLE_PROPERTY failed (%d)\n" , |
1132 | ret); |
1133 | return ret; |
1134 | } |
1135 | |
1136 | ret = ucsi_register_cable(con); |
1137 | if (ret < 0) |
1138 | return ret; |
1139 | |
1140 | if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) { |
1141 | ret = ucsi_get_cable_identity(con); |
1142 | if (ret < 0) |
1143 | return ret; |
1144 | } |
1145 | |
1146 | if (con->ucsi->cap.features & UCSI_CAP_ALT_MODE_DETAILS) { |
1147 | ret = ucsi_register_plug(con); |
1148 | if (ret < 0) |
1149 | return ret; |
1150 | |
1151 | ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP_P); |
1152 | if (ret < 0) |
1153 | return ret; |
1154 | } |
1155 | |
1156 | return 0; |
1157 | } |
1158 | |
1159 | static void ucsi_handle_connector_change(struct work_struct *work) |
1160 | { |
1161 | struct ucsi_connector *con = container_of(work, struct ucsi_connector, |
1162 | work); |
1163 | struct ucsi *ucsi = con->ucsi; |
1164 | enum typec_role role; |
1165 | u64 command; |
1166 | int ret; |
1167 | |
1168 | mutex_lock(&con->lock); |
1169 | |
1170 | command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); |
1171 | ret = ucsi_send_command(ucsi, command, &con->status, sizeof(con->status)); |
1172 | if (ret < 0) { |
1173 | dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n" , |
1174 | __func__, ret); |
1175 | clear_bit(EVENT_PENDING, addr: &con->ucsi->flags); |
1176 | goto out_unlock; |
1177 | } |
1178 | |
1179 | trace_ucsi_connector_change(port: con->num, status: &con->status); |
1180 | |
1181 | role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR); |
1182 | |
1183 | if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) { |
1184 | typec_set_pwr_role(port: con->port, role); |
1185 | |
1186 | /* Complete pending power role swap */ |
1187 | if (!completion_done(x: &con->complete)) |
1188 | complete(&con->complete); |
1189 | } |
1190 | |
1191 | if (con->status.change & UCSI_CONSTAT_CONNECT_CHANGE) { |
1192 | typec_set_pwr_role(port: con->port, role); |
1193 | ucsi_port_psy_changed(con); |
1194 | ucsi_partner_change(con); |
1195 | |
1196 | if (con->status.flags & UCSI_CONSTAT_CONNECTED) { |
1197 | ucsi_register_partner(con); |
1198 | ucsi_partner_task(con, cb: ucsi_check_connection, retries: 1, HZ); |
1199 | ucsi_partner_task(con, cb: ucsi_check_connector_capability, retries: 1, HZ); |
1200 | if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) |
1201 | ucsi_partner_task(con, cb: ucsi_get_partner_identity, retries: 1, HZ); |
1202 | if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS) |
1203 | ucsi_partner_task(con, cb: ucsi_check_cable, retries: 1, HZ); |
1204 | |
1205 | if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) == |
1206 | UCSI_CONSTAT_PWR_OPMODE_PD) |
1207 | ucsi_partner_task(con, cb: ucsi_register_partner_pdos, retries: 1, HZ); |
1208 | } else { |
1209 | ucsi_unregister_partner(con); |
1210 | } |
1211 | } |
1212 | |
1213 | if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE || |
1214 | con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE) |
1215 | ucsi_pwr_opmode_change(con); |
1216 | |
1217 | if (con->partner && con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) { |
1218 | ucsi_partner_change(con); |
1219 | |
1220 | /* Complete pending data role swap */ |
1221 | if (!completion_done(x: &con->complete)) |
1222 | complete(&con->complete); |
1223 | } |
1224 | |
1225 | if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) |
1226 | ucsi_partner_task(con, cb: ucsi_check_altmodes, retries: 1, delay: 0); |
1227 | |
1228 | mutex_lock(&ucsi->ppm_lock); |
1229 | clear_bit(EVENT_PENDING, addr: &con->ucsi->flags); |
1230 | ret = ucsi_acknowledge_connector_change(ucsi); |
1231 | mutex_unlock(lock: &ucsi->ppm_lock); |
1232 | |
1233 | if (ret) |
1234 | dev_err(ucsi->dev, "%s: ACK failed (%d)" , __func__, ret); |
1235 | |
1236 | out_unlock: |
1237 | mutex_unlock(lock: &con->lock); |
1238 | } |
1239 | |
1240 | /** |
1241 | * ucsi_connector_change - Process Connector Change Event |
1242 | * @ucsi: UCSI Interface |
1243 | * @num: Connector number |
1244 | */ |
1245 | void ucsi_connector_change(struct ucsi *ucsi, u8 num) |
1246 | { |
1247 | struct ucsi_connector *con = &ucsi->connector[num - 1]; |
1248 | |
1249 | if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) { |
1250 | dev_dbg(ucsi->dev, "Early connector change event\n" ); |
1251 | return; |
1252 | } |
1253 | |
1254 | if (!test_and_set_bit(EVENT_PENDING, addr: &ucsi->flags)) |
1255 | schedule_work(work: &con->work); |
1256 | } |
1257 | EXPORT_SYMBOL_GPL(ucsi_connector_change); |
1258 | |
1259 | /* -------------------------------------------------------------------------- */ |
1260 | |
1261 | static int ucsi_reset_connector(struct ucsi_connector *con, bool hard) |
1262 | { |
1263 | u64 command; |
1264 | |
1265 | command = UCSI_CONNECTOR_RESET | UCSI_CONNECTOR_NUMBER(con->num); |
1266 | command |= hard ? UCSI_CONNECTOR_RESET_HARD : 0; |
1267 | |
1268 | return ucsi_send_command(con->ucsi, command, NULL, 0); |
1269 | } |
1270 | |
1271 | static int ucsi_reset_ppm(struct ucsi *ucsi) |
1272 | { |
1273 | u64 command; |
1274 | unsigned long tmo; |
1275 | u32 cci; |
1276 | int ret; |
1277 | |
1278 | mutex_lock(&ucsi->ppm_lock); |
1279 | |
1280 | ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); |
1281 | if (ret < 0) |
1282 | goto out; |
1283 | |
1284 | /* |
1285 | * If UCSI_CCI_RESET_COMPLETE is already set we must clear |
1286 | * the flag before we start another reset. Send a |
1287 | * UCSI_SET_NOTIFICATION_ENABLE command to achieve this. |
1288 | * Ignore a timeout and try the reset anyway if this fails. |
1289 | */ |
1290 | if (cci & UCSI_CCI_RESET_COMPLETE) { |
1291 | command = UCSI_SET_NOTIFICATION_ENABLE; |
1292 | ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command, |
1293 | sizeof(command)); |
1294 | if (ret < 0) |
1295 | goto out; |
1296 | |
1297 | tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS); |
1298 | do { |
1299 | ret = ucsi->ops->read(ucsi, UCSI_CCI, |
1300 | &cci, sizeof(cci)); |
1301 | if (ret < 0) |
1302 | goto out; |
1303 | if (cci & UCSI_CCI_COMMAND_COMPLETE) |
1304 | break; |
1305 | if (time_is_before_jiffies(tmo)) |
1306 | break; |
1307 | msleep(msecs: 20); |
1308 | } while (1); |
1309 | |
1310 | WARN_ON(cci & UCSI_CCI_RESET_COMPLETE); |
1311 | } |
1312 | |
1313 | command = UCSI_PPM_RESET; |
1314 | ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command, |
1315 | sizeof(command)); |
1316 | if (ret < 0) |
1317 | goto out; |
1318 | |
1319 | tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS); |
1320 | |
1321 | do { |
1322 | if (time_is_before_jiffies(tmo)) { |
1323 | ret = -ETIMEDOUT; |
1324 | goto out; |
1325 | } |
1326 | |
1327 | ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); |
1328 | if (ret) |
1329 | goto out; |
1330 | |
1331 | /* If the PPM is still doing something else, reset it again. */ |
1332 | if (cci & ~UCSI_CCI_RESET_COMPLETE) { |
1333 | ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, |
1334 | &command, |
1335 | sizeof(command)); |
1336 | if (ret < 0) |
1337 | goto out; |
1338 | } |
1339 | |
1340 | msleep(msecs: 20); |
1341 | } while (!(cci & UCSI_CCI_RESET_COMPLETE)); |
1342 | |
1343 | out: |
1344 | mutex_unlock(lock: &ucsi->ppm_lock); |
1345 | return ret; |
1346 | } |
1347 | |
1348 | static int ucsi_role_cmd(struct ucsi_connector *con, u64 command) |
1349 | { |
1350 | int ret; |
1351 | |
1352 | ret = ucsi_send_command(con->ucsi, command, NULL, 0); |
1353 | if (ret == -ETIMEDOUT) { |
1354 | u64 c; |
1355 | |
1356 | /* PPM most likely stopped responding. Resetting everything. */ |
1357 | ucsi_reset_ppm(ucsi: con->ucsi); |
1358 | |
1359 | c = UCSI_SET_NOTIFICATION_ENABLE | con->ucsi->ntfy; |
1360 | ucsi_send_command(con->ucsi, c, NULL, 0); |
1361 | |
1362 | ucsi_reset_connector(con, hard: true); |
1363 | } |
1364 | |
1365 | return ret; |
1366 | } |
1367 | |
1368 | static int ucsi_dr_swap(struct typec_port *port, enum typec_data_role role) |
1369 | { |
1370 | struct ucsi_connector *con = typec_get_drvdata(port); |
1371 | u8 partner_type; |
1372 | u64 command; |
1373 | int ret = 0; |
1374 | |
1375 | mutex_lock(&con->lock); |
1376 | |
1377 | if (!con->partner) { |
1378 | ret = -ENOTCONN; |
1379 | goto out_unlock; |
1380 | } |
1381 | |
1382 | partner_type = UCSI_CONSTAT_PARTNER_TYPE(con->status.flags); |
1383 | if ((partner_type == UCSI_CONSTAT_PARTNER_TYPE_DFP && |
1384 | role == TYPEC_DEVICE) || |
1385 | (partner_type == UCSI_CONSTAT_PARTNER_TYPE_UFP && |
1386 | role == TYPEC_HOST)) |
1387 | goto out_unlock; |
1388 | |
1389 | reinit_completion(x: &con->complete); |
1390 | |
1391 | command = UCSI_SET_UOR | UCSI_CONNECTOR_NUMBER(con->num); |
1392 | command |= UCSI_SET_UOR_ROLE(role); |
1393 | command |= UCSI_SET_UOR_ACCEPT_ROLE_SWAPS; |
1394 | ret = ucsi_role_cmd(con, command); |
1395 | if (ret < 0) |
1396 | goto out_unlock; |
1397 | |
1398 | mutex_unlock(lock: &con->lock); |
1399 | |
1400 | if (!wait_for_completion_timeout(x: &con->complete, |
1401 | timeout: msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) |
1402 | return -ETIMEDOUT; |
1403 | |
1404 | return 0; |
1405 | |
1406 | out_unlock: |
1407 | mutex_unlock(lock: &con->lock); |
1408 | |
1409 | return ret; |
1410 | } |
1411 | |
1412 | static int ucsi_pr_swap(struct typec_port *port, enum typec_role role) |
1413 | { |
1414 | struct ucsi_connector *con = typec_get_drvdata(port); |
1415 | enum typec_role cur_role; |
1416 | u64 command; |
1417 | int ret = 0; |
1418 | |
1419 | mutex_lock(&con->lock); |
1420 | |
1421 | if (!con->partner) { |
1422 | ret = -ENOTCONN; |
1423 | goto out_unlock; |
1424 | } |
1425 | |
1426 | cur_role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR); |
1427 | |
1428 | if (cur_role == role) |
1429 | goto out_unlock; |
1430 | |
1431 | reinit_completion(x: &con->complete); |
1432 | |
1433 | command = UCSI_SET_PDR | UCSI_CONNECTOR_NUMBER(con->num); |
1434 | command |= UCSI_SET_PDR_ROLE(role); |
1435 | command |= UCSI_SET_PDR_ACCEPT_ROLE_SWAPS; |
1436 | ret = ucsi_role_cmd(con, command); |
1437 | if (ret < 0) |
1438 | goto out_unlock; |
1439 | |
1440 | mutex_unlock(lock: &con->lock); |
1441 | |
1442 | if (!wait_for_completion_timeout(x: &con->complete, |
1443 | timeout: msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) |
1444 | return -ETIMEDOUT; |
1445 | |
1446 | mutex_lock(&con->lock); |
1447 | |
1448 | /* Something has gone wrong while swapping the role */ |
1449 | if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) != |
1450 | UCSI_CONSTAT_PWR_OPMODE_PD) { |
1451 | ucsi_reset_connector(con, hard: true); |
1452 | ret = -EPROTO; |
1453 | } |
1454 | |
1455 | out_unlock: |
1456 | mutex_unlock(lock: &con->lock); |
1457 | |
1458 | return ret; |
1459 | } |
1460 | |
1461 | static const struct typec_operations ucsi_ops = { |
1462 | .dr_set = ucsi_dr_swap, |
1463 | .pr_set = ucsi_pr_swap |
1464 | }; |
1465 | |
1466 | /* Caller must call fwnode_handle_put() after use */ |
1467 | static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con) |
1468 | { |
1469 | struct fwnode_handle *fwnode; |
1470 | int i = 1; |
1471 | |
1472 | device_for_each_child_node(con->ucsi->dev, fwnode) |
1473 | if (i++ == con->num) |
1474 | return fwnode; |
1475 | return NULL; |
1476 | } |
1477 | |
1478 | static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con) |
1479 | { |
1480 | struct usb_power_delivery_desc desc = { ucsi->cap.pd_version}; |
1481 | struct usb_power_delivery_capabilities_desc pd_caps; |
1482 | struct usb_power_delivery_capabilities *pd_cap; |
1483 | struct typec_capability *cap = &con->typec_cap; |
1484 | enum typec_accessory *accessory = cap->accessory; |
1485 | enum usb_role u_role = USB_ROLE_NONE; |
1486 | u64 command; |
1487 | char *name; |
1488 | int ret; |
1489 | |
1490 | name = kasprintf(GFP_KERNEL, fmt: "%s-con%d" , dev_name(dev: ucsi->dev), con->num); |
1491 | if (!name) |
1492 | return -ENOMEM; |
1493 | |
1494 | con->wq = create_singlethread_workqueue(name); |
1495 | kfree(objp: name); |
1496 | if (!con->wq) |
1497 | return -ENOMEM; |
1498 | |
1499 | INIT_WORK(&con->work, ucsi_handle_connector_change); |
1500 | init_completion(x: &con->complete); |
1501 | mutex_init(&con->lock); |
1502 | INIT_LIST_HEAD(list: &con->partner_tasks); |
1503 | con->ucsi = ucsi; |
1504 | |
1505 | cap->fwnode = ucsi_find_fwnode(con); |
1506 | con->usb_role_sw = fwnode_usb_role_switch_get(node: cap->fwnode); |
1507 | if (IS_ERR(ptr: con->usb_role_sw)) |
1508 | return dev_err_probe(dev: ucsi->dev, err: PTR_ERR(ptr: con->usb_role_sw), |
1509 | fmt: "con%d: failed to get usb role switch\n" , con->num); |
1510 | |
1511 | /* Delay other interactions with the con until registration is complete */ |
1512 | mutex_lock(&con->lock); |
1513 | |
1514 | /* Get connector capability */ |
1515 | command = UCSI_GET_CONNECTOR_CAPABILITY; |
1516 | command |= UCSI_CONNECTOR_NUMBER(con->num); |
1517 | ret = ucsi_send_command(ucsi, command, &con->cap, sizeof(con->cap)); |
1518 | if (ret < 0) |
1519 | goto out_unlock; |
1520 | |
1521 | if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP) |
1522 | cap->data = TYPEC_PORT_DRD; |
1523 | else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DFP) |
1524 | cap->data = TYPEC_PORT_DFP; |
1525 | else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_UFP) |
1526 | cap->data = TYPEC_PORT_UFP; |
1527 | |
1528 | if ((con->cap.flags & UCSI_CONCAP_FLAG_PROVIDER) && |
1529 | (con->cap.flags & UCSI_CONCAP_FLAG_CONSUMER)) |
1530 | cap->type = TYPEC_PORT_DRP; |
1531 | else if (con->cap.flags & UCSI_CONCAP_FLAG_PROVIDER) |
1532 | cap->type = TYPEC_PORT_SRC; |
1533 | else if (con->cap.flags & UCSI_CONCAP_FLAG_CONSUMER) |
1534 | cap->type = TYPEC_PORT_SNK; |
1535 | |
1536 | cap->revision = ucsi->cap.typec_version; |
1537 | cap->pd_revision = ucsi->cap.pd_version; |
1538 | cap->svdm_version = SVDM_VER_2_0; |
1539 | cap->prefer_role = TYPEC_NO_PREFERRED_ROLE; |
1540 | |
1541 | if (con->cap.op_mode & UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY) |
1542 | *accessory++ = TYPEC_ACCESSORY_AUDIO; |
1543 | if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY) |
1544 | *accessory = TYPEC_ACCESSORY_DEBUG; |
1545 | |
1546 | cap->driver_data = con; |
1547 | cap->ops = &ucsi_ops; |
1548 | |
1549 | ret = ucsi_register_port_psy(con); |
1550 | if (ret) |
1551 | goto out; |
1552 | |
1553 | /* Register the connector */ |
1554 | con->port = typec_register_port(parent: ucsi->dev, cap); |
1555 | if (IS_ERR(ptr: con->port)) { |
1556 | ret = PTR_ERR(ptr: con->port); |
1557 | goto out; |
1558 | } |
1559 | |
1560 | con->pd = usb_power_delivery_register(parent: ucsi->dev, desc: &desc); |
1561 | |
1562 | ret = ucsi_get_pdos(con, role: TYPEC_SOURCE, is_partner: 0, pdos: pd_caps.pdo); |
1563 | if (ret > 0) { |
1564 | if (ret < PDO_MAX_OBJECTS) |
1565 | pd_caps.pdo[ret] = 0; |
1566 | |
1567 | pd_caps.role = TYPEC_SOURCE; |
1568 | pd_cap = usb_power_delivery_register_capabilities(pd: con->pd, desc: &pd_caps); |
1569 | if (IS_ERR(ptr: pd_cap)) { |
1570 | ret = PTR_ERR(ptr: pd_cap); |
1571 | goto out; |
1572 | } |
1573 | |
1574 | con->port_source_caps = pd_cap; |
1575 | typec_port_set_usb_power_delivery(port: con->port, pd: con->pd); |
1576 | } |
1577 | |
1578 | memset(&pd_caps, 0, sizeof(pd_caps)); |
1579 | ret = ucsi_get_pdos(con, role: TYPEC_SINK, is_partner: 0, pdos: pd_caps.pdo); |
1580 | if (ret > 0) { |
1581 | if (ret < PDO_MAX_OBJECTS) |
1582 | pd_caps.pdo[ret] = 0; |
1583 | |
1584 | pd_caps.role = TYPEC_SINK; |
1585 | pd_cap = usb_power_delivery_register_capabilities(pd: con->pd, desc: &pd_caps); |
1586 | if (IS_ERR(ptr: pd_cap)) { |
1587 | ret = PTR_ERR(ptr: pd_cap); |
1588 | goto out; |
1589 | } |
1590 | |
1591 | con->port_sink_caps = pd_cap; |
1592 | typec_port_set_usb_power_delivery(port: con->port, pd: con->pd); |
1593 | } |
1594 | |
1595 | /* Alternate modes */ |
1596 | ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_CON); |
1597 | if (ret) { |
1598 | dev_err(ucsi->dev, "con%d: failed to register alt modes\n" , |
1599 | con->num); |
1600 | goto out; |
1601 | } |
1602 | |
1603 | /* Get the status */ |
1604 | command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); |
1605 | ret = ucsi_send_command(ucsi, command, &con->status, sizeof(con->status)); |
1606 | if (ret < 0) { |
1607 | dev_err(ucsi->dev, "con%d: failed to get status\n" , con->num); |
1608 | ret = 0; |
1609 | goto out; |
1610 | } |
1611 | ret = 0; /* ucsi_send_command() returns length on success */ |
1612 | |
1613 | switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { |
1614 | case UCSI_CONSTAT_PARTNER_TYPE_UFP: |
1615 | case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP: |
1616 | u_role = USB_ROLE_HOST; |
1617 | fallthrough; |
1618 | case UCSI_CONSTAT_PARTNER_TYPE_CABLE: |
1619 | typec_set_data_role(port: con->port, role: TYPEC_HOST); |
1620 | break; |
1621 | case UCSI_CONSTAT_PARTNER_TYPE_DFP: |
1622 | u_role = USB_ROLE_DEVICE; |
1623 | typec_set_data_role(port: con->port, role: TYPEC_DEVICE); |
1624 | break; |
1625 | default: |
1626 | break; |
1627 | } |
1628 | |
1629 | /* Check if there is already something connected */ |
1630 | if (con->status.flags & UCSI_CONSTAT_CONNECTED) { |
1631 | typec_set_pwr_role(port: con->port, |
1632 | role: !!(con->status.flags & UCSI_CONSTAT_PWR_DIR)); |
1633 | ucsi_register_partner(con); |
1634 | ucsi_pwr_opmode_change(con); |
1635 | ucsi_port_psy_changed(con); |
1636 | if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) |
1637 | ucsi_get_partner_identity(con); |
1638 | if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS) |
1639 | ucsi_check_cable(con); |
1640 | } |
1641 | |
1642 | /* Only notify USB controller if partner supports USB data */ |
1643 | if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB)) |
1644 | u_role = USB_ROLE_NONE; |
1645 | |
1646 | ret = usb_role_switch_set_role(sw: con->usb_role_sw, role: u_role); |
1647 | if (ret) { |
1648 | dev_err(ucsi->dev, "con:%d: failed to set usb role:%d\n" , |
1649 | con->num, u_role); |
1650 | ret = 0; |
1651 | } |
1652 | |
1653 | if (con->partner && |
1654 | UCSI_CONSTAT_PWR_OPMODE(con->status.flags) == |
1655 | UCSI_CONSTAT_PWR_OPMODE_PD) { |
1656 | ucsi_get_src_pdos(con); |
1657 | ucsi_check_altmodes(con); |
1658 | } |
1659 | |
1660 | trace_ucsi_register_port(port: con->num, status: &con->status); |
1661 | |
1662 | out: |
1663 | fwnode_handle_put(fwnode: cap->fwnode); |
1664 | out_unlock: |
1665 | mutex_unlock(lock: &con->lock); |
1666 | |
1667 | if (ret && con->wq) { |
1668 | destroy_workqueue(wq: con->wq); |
1669 | con->wq = NULL; |
1670 | } |
1671 | |
1672 | return ret; |
1673 | } |
1674 | |
1675 | /** |
1676 | * ucsi_init - Initialize UCSI interface |
1677 | * @ucsi: UCSI to be initialized |
1678 | * |
1679 | * Registers all ports @ucsi has and enables all notification events. |
1680 | */ |
1681 | static int ucsi_init(struct ucsi *ucsi) |
1682 | { |
1683 | struct ucsi_connector *con, *connector; |
1684 | u64 command, ntfy; |
1685 | u32 cci; |
1686 | int ret; |
1687 | int i; |
1688 | |
1689 | /* Reset the PPM */ |
1690 | ret = ucsi_reset_ppm(ucsi); |
1691 | if (ret) { |
1692 | dev_err(ucsi->dev, "failed to reset PPM!\n" ); |
1693 | goto err; |
1694 | } |
1695 | |
1696 | /* Enable basic notifications */ |
1697 | ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR; |
1698 | command = UCSI_SET_NOTIFICATION_ENABLE | ntfy; |
1699 | ret = ucsi_send_command(ucsi, command, NULL, 0); |
1700 | if (ret < 0) |
1701 | goto err_reset; |
1702 | |
1703 | /* Get PPM capabilities */ |
1704 | command = UCSI_GET_CAPABILITY; |
1705 | ret = ucsi_send_command(ucsi, command, &ucsi->cap, sizeof(ucsi->cap)); |
1706 | if (ret < 0) |
1707 | goto err_reset; |
1708 | |
1709 | if (!ucsi->cap.num_connectors) { |
1710 | ret = -ENODEV; |
1711 | goto err_reset; |
1712 | } |
1713 | |
1714 | /* Allocate the connectors. Released in ucsi_unregister() */ |
1715 | connector = kcalloc(n: ucsi->cap.num_connectors + 1, size: sizeof(*connector), GFP_KERNEL); |
1716 | if (!connector) { |
1717 | ret = -ENOMEM; |
1718 | goto err_reset; |
1719 | } |
1720 | |
1721 | /* Register all connectors */ |
1722 | for (i = 0; i < ucsi->cap.num_connectors; i++) { |
1723 | connector[i].num = i + 1; |
1724 | ret = ucsi_register_port(ucsi, con: &connector[i]); |
1725 | if (ret) |
1726 | goto err_unregister; |
1727 | } |
1728 | |
1729 | /* Enable all notifications */ |
1730 | ntfy = UCSI_ENABLE_NTFY_ALL; |
1731 | command = UCSI_SET_NOTIFICATION_ENABLE | ntfy; |
1732 | ret = ucsi_send_command(ucsi, command, NULL, 0); |
1733 | if (ret < 0) |
1734 | goto err_unregister; |
1735 | |
1736 | ucsi->connector = connector; |
1737 | ucsi->ntfy = ntfy; |
1738 | |
1739 | mutex_lock(&ucsi->ppm_lock); |
1740 | ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); |
1741 | mutex_unlock(lock: &ucsi->ppm_lock); |
1742 | if (ret) |
1743 | return ret; |
1744 | if (UCSI_CCI_CONNECTOR(cci)) |
1745 | ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci)); |
1746 | |
1747 | return 0; |
1748 | |
1749 | err_unregister: |
1750 | for (con = connector; con->port; con++) { |
1751 | ucsi_unregister_partner(con); |
1752 | ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON); |
1753 | ucsi_unregister_port_psy(con); |
1754 | if (con->wq) |
1755 | destroy_workqueue(wq: con->wq); |
1756 | |
1757 | usb_power_delivery_unregister_capabilities(cap: con->port_sink_caps); |
1758 | con->port_sink_caps = NULL; |
1759 | usb_power_delivery_unregister_capabilities(cap: con->port_source_caps); |
1760 | con->port_source_caps = NULL; |
1761 | usb_power_delivery_unregister(pd: con->pd); |
1762 | con->pd = NULL; |
1763 | typec_unregister_port(port: con->port); |
1764 | con->port = NULL; |
1765 | } |
1766 | kfree(objp: connector); |
1767 | err_reset: |
1768 | memset(&ucsi->cap, 0, sizeof(ucsi->cap)); |
1769 | ucsi_reset_ppm(ucsi); |
1770 | err: |
1771 | return ret; |
1772 | } |
1773 | |
1774 | static void ucsi_resume_work(struct work_struct *work) |
1775 | { |
1776 | struct ucsi *ucsi = container_of(work, struct ucsi, resume_work); |
1777 | struct ucsi_connector *con; |
1778 | u64 command; |
1779 | int ret; |
1780 | |
1781 | /* Restore UCSI notification enable mask after system resume */ |
1782 | command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; |
1783 | ret = ucsi_send_command(ucsi, command, NULL, 0); |
1784 | if (ret < 0) { |
1785 | dev_err(ucsi->dev, "failed to re-enable notifications (%d)\n" , ret); |
1786 | return; |
1787 | } |
1788 | |
1789 | for (con = ucsi->connector; con->port; con++) { |
1790 | mutex_lock(&con->lock); |
1791 | ucsi_partner_task(con, cb: ucsi_check_connection, retries: 1, delay: 0); |
1792 | mutex_unlock(lock: &con->lock); |
1793 | } |
1794 | } |
1795 | |
1796 | int ucsi_resume(struct ucsi *ucsi) |
1797 | { |
1798 | if (ucsi->connector) |
1799 | queue_work(wq: system_long_wq, work: &ucsi->resume_work); |
1800 | return 0; |
1801 | } |
1802 | EXPORT_SYMBOL_GPL(ucsi_resume); |
1803 | |
1804 | static void ucsi_init_work(struct work_struct *work) |
1805 | { |
1806 | struct ucsi *ucsi = container_of(work, struct ucsi, work.work); |
1807 | int ret; |
1808 | |
1809 | ret = ucsi_init(ucsi); |
1810 | if (ret) |
1811 | dev_err_probe(dev: ucsi->dev, err: ret, fmt: "PPM init failed\n" ); |
1812 | |
1813 | if (ret == -EPROBE_DEFER) { |
1814 | if (ucsi->work_count++ > UCSI_ROLE_SWITCH_WAIT_COUNT) { |
1815 | dev_err(ucsi->dev, "PPM init failed, stop trying\n" ); |
1816 | return; |
1817 | } |
1818 | |
1819 | queue_delayed_work(wq: system_long_wq, dwork: &ucsi->work, |
1820 | UCSI_ROLE_SWITCH_INTERVAL); |
1821 | } |
1822 | } |
1823 | |
1824 | /** |
1825 | * ucsi_get_drvdata - Return private driver data pointer |
1826 | * @ucsi: UCSI interface |
1827 | */ |
1828 | void *ucsi_get_drvdata(struct ucsi *ucsi) |
1829 | { |
1830 | return ucsi->driver_data; |
1831 | } |
1832 | EXPORT_SYMBOL_GPL(ucsi_get_drvdata); |
1833 | |
1834 | /** |
1835 | * ucsi_set_drvdata - Assign private driver data pointer |
1836 | * @ucsi: UCSI interface |
1837 | * @data: Private data pointer |
1838 | */ |
1839 | void ucsi_set_drvdata(struct ucsi *ucsi, void *data) |
1840 | { |
1841 | ucsi->driver_data = data; |
1842 | } |
1843 | EXPORT_SYMBOL_GPL(ucsi_set_drvdata); |
1844 | |
1845 | /** |
1846 | * ucsi_create - Allocate UCSI instance |
1847 | * @dev: Device interface to the PPM (Platform Policy Manager) |
1848 | * @ops: I/O routines |
1849 | */ |
1850 | struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops) |
1851 | { |
1852 | struct ucsi *ucsi; |
1853 | |
1854 | if (!ops || !ops->read || !ops->sync_write || !ops->async_write) |
1855 | return ERR_PTR(error: -EINVAL); |
1856 | |
1857 | ucsi = kzalloc(size: sizeof(*ucsi), GFP_KERNEL); |
1858 | if (!ucsi) |
1859 | return ERR_PTR(error: -ENOMEM); |
1860 | |
1861 | INIT_WORK(&ucsi->resume_work, ucsi_resume_work); |
1862 | INIT_DELAYED_WORK(&ucsi->work, ucsi_init_work); |
1863 | mutex_init(&ucsi->ppm_lock); |
1864 | ucsi->dev = dev; |
1865 | ucsi->ops = ops; |
1866 | |
1867 | return ucsi; |
1868 | } |
1869 | EXPORT_SYMBOL_GPL(ucsi_create); |
1870 | |
1871 | /** |
1872 | * ucsi_destroy - Free UCSI instance |
1873 | * @ucsi: UCSI instance to be freed |
1874 | */ |
1875 | void ucsi_destroy(struct ucsi *ucsi) |
1876 | { |
1877 | ucsi_debugfs_unregister(ucsi); |
1878 | kfree(objp: ucsi); |
1879 | } |
1880 | EXPORT_SYMBOL_GPL(ucsi_destroy); |
1881 | |
1882 | /** |
1883 | * ucsi_register - Register UCSI interface |
1884 | * @ucsi: UCSI instance |
1885 | */ |
1886 | int ucsi_register(struct ucsi *ucsi) |
1887 | { |
1888 | int ret; |
1889 | |
1890 | ret = ucsi->ops->read(ucsi, UCSI_VERSION, &ucsi->version, |
1891 | sizeof(ucsi->version)); |
1892 | if (ret) |
1893 | return ret; |
1894 | |
1895 | if (!ucsi->version) |
1896 | return -ENODEV; |
1897 | |
1898 | /* |
1899 | * Version format is JJ.M.N (JJ = Major version, M = Minor version, |
1900 | * N = sub-minor version). |
1901 | */ |
1902 | dev_dbg(ucsi->dev, "Registered UCSI interface with version %x.%x.%x" , |
1903 | UCSI_BCD_GET_MAJOR(ucsi->version), |
1904 | UCSI_BCD_GET_MINOR(ucsi->version), |
1905 | UCSI_BCD_GET_SUBMINOR(ucsi->version)); |
1906 | |
1907 | queue_delayed_work(wq: system_long_wq, dwork: &ucsi->work, delay: 0); |
1908 | |
1909 | ucsi_debugfs_register(ucsi); |
1910 | return 0; |
1911 | } |
1912 | EXPORT_SYMBOL_GPL(ucsi_register); |
1913 | |
1914 | /** |
1915 | * ucsi_unregister - Unregister UCSI interface |
1916 | * @ucsi: UCSI interface to be unregistered |
1917 | * |
1918 | * Unregister UCSI interface that was created with ucsi_register(). |
1919 | */ |
1920 | void ucsi_unregister(struct ucsi *ucsi) |
1921 | { |
1922 | u64 cmd = UCSI_SET_NOTIFICATION_ENABLE; |
1923 | int i; |
1924 | |
1925 | /* Make sure that we are not in the middle of driver initialization */ |
1926 | cancel_delayed_work_sync(dwork: &ucsi->work); |
1927 | cancel_work_sync(work: &ucsi->resume_work); |
1928 | |
1929 | /* Disable notifications */ |
1930 | ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); |
1931 | |
1932 | if (!ucsi->connector) |
1933 | return; |
1934 | |
1935 | for (i = 0; i < ucsi->cap.num_connectors; i++) { |
1936 | cancel_work_sync(work: &ucsi->connector[i].work); |
1937 | ucsi_unregister_partner(con: &ucsi->connector[i]); |
1938 | ucsi_unregister_altmodes(con: &ucsi->connector[i], |
1939 | UCSI_RECIPIENT_CON); |
1940 | ucsi_unregister_port_psy(con: &ucsi->connector[i]); |
1941 | |
1942 | if (ucsi->connector[i].wq) { |
1943 | struct ucsi_work *uwork; |
1944 | |
1945 | mutex_lock(&ucsi->connector[i].lock); |
1946 | /* |
1947 | * queue delayed items immediately so they can execute |
1948 | * and free themselves before the wq is destroyed |
1949 | */ |
1950 | list_for_each_entry(uwork, &ucsi->connector[i].partner_tasks, node) |
1951 | mod_delayed_work(wq: ucsi->connector[i].wq, dwork: &uwork->work, delay: 0); |
1952 | mutex_unlock(lock: &ucsi->connector[i].lock); |
1953 | destroy_workqueue(wq: ucsi->connector[i].wq); |
1954 | } |
1955 | |
1956 | usb_power_delivery_unregister_capabilities(cap: ucsi->connector[i].port_sink_caps); |
1957 | ucsi->connector[i].port_sink_caps = NULL; |
1958 | usb_power_delivery_unregister_capabilities(cap: ucsi->connector[i].port_source_caps); |
1959 | ucsi->connector[i].port_source_caps = NULL; |
1960 | usb_power_delivery_unregister(pd: ucsi->connector[i].pd); |
1961 | ucsi->connector[i].pd = NULL; |
1962 | typec_unregister_port(port: ucsi->connector[i].port); |
1963 | } |
1964 | |
1965 | kfree(objp: ucsi->connector); |
1966 | } |
1967 | EXPORT_SYMBOL_GPL(ucsi_unregister); |
1968 | |
1969 | static int __init ucsi_module_init(void) |
1970 | { |
1971 | ucsi_debugfs_init(); |
1972 | return 0; |
1973 | } |
1974 | module_init(ucsi_module_init); |
1975 | |
1976 | static void __exit ucsi_module_exit(void) |
1977 | { |
1978 | ucsi_debugfs_exit(); |
1979 | } |
1980 | module_exit(ucsi_module_exit); |
1981 | |
1982 | MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>" ); |
1983 | MODULE_LICENSE("GPL v2" ); |
1984 | MODULE_DESCRIPTION("USB Type-C Connector System Software Interface driver" ); |
1985 | |