|
20 | 20 | #include <linux/usb/pd.h>
|
21 | 21 | #include <linux/usb/pd_bdo.h>
|
22 | 22 | #include <linux/usb/pd_vdo.h>
|
| 23 | +#include <linux/usb/role.h> |
23 | 24 | #include <linux/usb/tcpm.h>
|
24 | 25 | #include <linux/usb/typec.h>
|
25 | 26 | #include <linux/workqueue.h>
|
@@ -176,6 +177,7 @@ struct tcpm_port {
|
176 | 177 | struct typec_port *typec_port;
|
177 | 178 |
|
178 | 179 | struct tcpc_dev *tcpc;
|
| 180 | + struct usb_role_switch *role_sw; |
179 | 181 |
|
180 | 182 | enum typec_role vconn_role;
|
181 | 183 | enum typec_role pwr_role;
|
@@ -604,18 +606,25 @@ void tcpm_pd_transmit_complete(struct tcpm_port *port,
|
604 | 606 | EXPORT_SYMBOL_GPL(tcpm_pd_transmit_complete);
|
605 | 607 |
|
606 | 608 | static int tcpm_mux_set(struct tcpm_port *port, enum tcpc_mux_mode mode,
|
607 |
| - enum usb_role usb_role) |
| 609 | + enum usb_role usb_role, |
| 610 | + enum typec_orientation orientation) |
608 | 611 | {
|
609 |
| - int ret = 0; |
| 612 | + int ret; |
610 | 613 |
|
611 |
| - tcpm_log(port, "Requesting mux mode %d, usb-role %d, polarity %d", |
612 |
| - mode, usb_role, port->polarity); |
| 614 | + tcpm_log(port, "Requesting mux mode %d, usb-role %d, orientation %d", |
| 615 | + mode, usb_role, orientation); |
613 | 616 |
|
614 |
| - if (port->tcpc->mux) |
615 |
| - ret = port->tcpc->mux->set(port->tcpc->mux, mode, usb_role, |
616 |
| - port->polarity); |
| 617 | + ret = typec_set_orientation(port->typec_port, orientation); |
| 618 | + if (ret) |
| 619 | + return ret; |
617 | 620 |
|
618 |
| - return ret; |
| 621 | + if (port->role_sw) { |
| 622 | + ret = usb_role_switch_set_role(port->role_sw, usb_role); |
| 623 | + if (ret) |
| 624 | + return ret; |
| 625 | + } |
| 626 | + |
| 627 | + return typec_set_mode(port->typec_port, mode); |
619 | 628 | }
|
620 | 629 |
|
621 | 630 | static int tcpm_set_polarity(struct tcpm_port *port,
|
@@ -728,15 +737,21 @@ static int tcpm_set_attached_state(struct tcpm_port *port, bool attached)
|
728 | 737 | static int tcpm_set_roles(struct tcpm_port *port, bool attached,
|
729 | 738 | enum typec_role role, enum typec_data_role data)
|
730 | 739 | {
|
| 740 | + enum typec_orientation orientation; |
731 | 741 | enum usb_role usb_role;
|
732 | 742 | int ret;
|
733 | 743 |
|
| 744 | + if (port->polarity == TYPEC_POLARITY_CC1) |
| 745 | + orientation = TYPEC_ORIENTATION_NORMAL; |
| 746 | + else |
| 747 | + orientation = TYPEC_ORIENTATION_REVERSE; |
| 748 | + |
734 | 749 | if (data == TYPEC_HOST)
|
735 | 750 | usb_role = USB_ROLE_HOST;
|
736 | 751 | else
|
737 | 752 | usb_role = USB_ROLE_DEVICE;
|
738 | 753 |
|
739 |
| - ret = tcpm_mux_set(port, TYPEC_MUX_USB, usb_role); |
| 754 | + ret = tcpm_mux_set(port, TYPEC_MUX_USB, usb_role, orientation); |
740 | 755 | if (ret < 0)
|
741 | 756 | return ret;
|
742 | 757 |
|
@@ -2029,7 +2044,8 @@ static int tcpm_src_attach(struct tcpm_port *port)
|
2029 | 2044 | out_disable_pd:
|
2030 | 2045 | port->tcpc->set_pd_rx(port->tcpc, false);
|
2031 | 2046 | out_disable_mux:
|
2032 |
| - tcpm_mux_set(port, TYPEC_MUX_NONE, USB_ROLE_NONE); |
| 2047 | + tcpm_mux_set(port, TYPEC_MUX_NONE, USB_ROLE_NONE, |
| 2048 | + TYPEC_ORIENTATION_NONE); |
2033 | 2049 | return ret;
|
2034 | 2050 | }
|
2035 | 2051 |
|
@@ -2073,7 +2089,8 @@ static void tcpm_reset_port(struct tcpm_port *port)
|
2073 | 2089 | tcpm_init_vconn(port);
|
2074 | 2090 | tcpm_set_current_limit(port, 0, 0);
|
2075 | 2091 | tcpm_set_polarity(port, TYPEC_POLARITY_CC1);
|
2076 |
| - tcpm_mux_set(port, TYPEC_MUX_NONE, USB_ROLE_NONE); |
| 2092 | + tcpm_mux_set(port, TYPEC_MUX_NONE, USB_ROLE_NONE, |
| 2093 | + TYPEC_ORIENTATION_NONE); |
2077 | 2094 | tcpm_set_attached_state(port, false);
|
2078 | 2095 | port->try_src_count = 0;
|
2079 | 2096 | port->try_snk_count = 0;
|
@@ -3653,6 +3670,12 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
|
3653 | 3670 | port->partner_desc.identity = &port->partner_ident;
|
3654 | 3671 | port->port_type = tcpc->config->type;
|
3655 | 3672 |
|
| 3673 | + port->role_sw = usb_role_switch_get(port->dev); |
| 3674 | + if (IS_ERR(port->role_sw)) { |
| 3675 | + err = PTR_ERR(port->role_sw); |
| 3676 | + goto out_destroy_wq; |
| 3677 | + } |
| 3678 | + |
3656 | 3679 | port->typec_port = typec_register_port(port->dev, &port->typec_caps);
|
3657 | 3680 | if (IS_ERR(port->typec_port)) {
|
3658 | 3681 | err = PTR_ERR(port->typec_port);
|
@@ -3688,6 +3711,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
|
3688 | 3711 | return port;
|
3689 | 3712 |
|
3690 | 3713 | out_destroy_wq:
|
| 3714 | + usb_role_switch_put(port->role_sw); |
3691 | 3715 | destroy_workqueue(port->wq);
|
3692 | 3716 | return ERR_PTR(err);
|
3693 | 3717 | }
|
|
0 commit comments