diff options
-rw-r--r-- | drivers/usb/typec/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/typec/fusb302/fusb302.c | 1 | ||||
-rw-r--r-- | drivers/usb/typec/tcpm.c | 46 | ||||
-rw-r--r-- | include/linux/usb/tcpm.h | 10 |
4 files changed, 36 insertions, 22 deletions
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index bcb2744c5977..a2a0684e7c82 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig | |||
@@ -48,6 +48,7 @@ if TYPEC | |||
48 | config TYPEC_TCPM | 48 | config TYPEC_TCPM |
49 | tristate "USB Type-C Port Controller Manager" | 49 | tristate "USB Type-C Port Controller Manager" |
50 | depends on USB | 50 | depends on USB |
51 | select USB_ROLE_SWITCH | ||
51 | help | 52 | help |
52 | The Type-C Port Controller Manager provides a USB PD and USB Type-C | 53 | The Type-C Port Controller Manager provides a USB PD and USB Type-C |
53 | state machine for use with Type-C Port Controllers. | 54 | state machine for use with Type-C Port Controllers. |
diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 82bf7c0ed53c..703617129067 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c | |||
@@ -1239,7 +1239,6 @@ static void init_tcpc_dev(struct tcpc_dev *fusb302_tcpc_dev) | |||
1239 | fusb302_tcpc_dev->set_roles = tcpm_set_roles; | 1239 | fusb302_tcpc_dev->set_roles = tcpm_set_roles; |
1240 | fusb302_tcpc_dev->start_drp_toggling = tcpm_start_drp_toggling; | 1240 | fusb302_tcpc_dev->start_drp_toggling = tcpm_start_drp_toggling; |
1241 | fusb302_tcpc_dev->pd_transmit = tcpm_pd_transmit; | 1241 | fusb302_tcpc_dev->pd_transmit = tcpm_pd_transmit; |
1242 | fusb302_tcpc_dev->mux = NULL; | ||
1243 | } | 1242 | } |
1244 | 1243 | ||
1245 | static const char * const cc_polarity_name[] = { | 1244 | static const char * const cc_polarity_name[] = { |
diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 2519b0d17f1f..677d12138dbd 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/usb/pd.h> | 20 | #include <linux/usb/pd.h> |
21 | #include <linux/usb/pd_bdo.h> | 21 | #include <linux/usb/pd_bdo.h> |
22 | #include <linux/usb/pd_vdo.h> | 22 | #include <linux/usb/pd_vdo.h> |
23 | #include <linux/usb/role.h> | ||
23 | #include <linux/usb/tcpm.h> | 24 | #include <linux/usb/tcpm.h> |
24 | #include <linux/usb/typec.h> | 25 | #include <linux/usb/typec.h> |
25 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
@@ -176,6 +177,7 @@ struct tcpm_port { | |||
176 | struct typec_port *typec_port; | 177 | struct typec_port *typec_port; |
177 | 178 | ||
178 | struct tcpc_dev *tcpc; | 179 | struct tcpc_dev *tcpc; |
180 | struct usb_role_switch *role_sw; | ||
179 | 181 | ||
180 | enum typec_role vconn_role; | 182 | enum typec_role vconn_role; |
181 | enum typec_role pwr_role; | 183 | enum typec_role pwr_role; |
@@ -604,18 +606,25 @@ void tcpm_pd_transmit_complete(struct tcpm_port *port, | |||
604 | EXPORT_SYMBOL_GPL(tcpm_pd_transmit_complete); | 606 | EXPORT_SYMBOL_GPL(tcpm_pd_transmit_complete); |
605 | 607 | ||
606 | static int tcpm_mux_set(struct tcpm_port *port, enum tcpc_mux_mode mode, | 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", | 614 | tcpm_log(port, "Requesting mux mode %d, usb-role %d, orientation %d", |
612 | mode, usb_role, port->polarity); | 615 | mode, usb_role, orientation); |
613 | 616 | ||
614 | if (port->tcpc->mux) | 617 | ret = typec_set_orientation(port->typec_port, orientation); |
615 | ret = port->tcpc->mux->set(port->tcpc->mux, mode, usb_role, | 618 | if (ret) |
616 | port->polarity); | 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 | static int tcpm_set_polarity(struct tcpm_port *port, | 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 | static int tcpm_set_roles(struct tcpm_port *port, bool attached, | 737 | static int tcpm_set_roles(struct tcpm_port *port, bool attached, |
729 | enum typec_role role, enum typec_data_role data) | 738 | enum typec_role role, enum typec_data_role data) |
730 | { | 739 | { |
740 | enum typec_orientation orientation; | ||
731 | enum usb_role usb_role; | 741 | enum usb_role usb_role; |
732 | int ret; | 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 | if (data == TYPEC_HOST) | 749 | if (data == TYPEC_HOST) |
735 | usb_role = USB_ROLE_HOST; | 750 | usb_role = USB_ROLE_HOST; |
736 | else | 751 | else |
737 | usb_role = USB_ROLE_DEVICE; | 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 | if (ret < 0) | 755 | if (ret < 0) |
741 | return ret; | 756 | return ret; |
742 | 757 | ||
@@ -2029,7 +2044,8 @@ out_disable_vconn: | |||
2029 | out_disable_pd: | 2044 | out_disable_pd: |
2030 | port->tcpc->set_pd_rx(port->tcpc, false); | 2045 | port->tcpc->set_pd_rx(port->tcpc, false); |
2031 | out_disable_mux: | 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 | return ret; | 2049 | return ret; |
2034 | } | 2050 | } |
2035 | 2051 | ||
@@ -2073,7 +2089,8 @@ static void tcpm_reset_port(struct tcpm_port *port) | |||
2073 | tcpm_init_vconn(port); | 2089 | tcpm_init_vconn(port); |
2074 | tcpm_set_current_limit(port, 0, 0); | 2090 | tcpm_set_current_limit(port, 0, 0); |
2075 | tcpm_set_polarity(port, TYPEC_POLARITY_CC1); | 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 | tcpm_set_attached_state(port, false); | 2094 | tcpm_set_attached_state(port, false); |
2078 | port->try_src_count = 0; | 2095 | port->try_src_count = 0; |
2079 | port->try_snk_count = 0; | 2096 | port->try_snk_count = 0; |
@@ -3653,6 +3670,12 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) | |||
3653 | port->partner_desc.identity = &port->partner_ident; | 3670 | port->partner_desc.identity = &port->partner_ident; |
3654 | port->port_type = tcpc->config->type; | 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 | port->typec_port = typec_register_port(port->dev, &port->typec_caps); | 3679 | port->typec_port = typec_register_port(port->dev, &port->typec_caps); |
3657 | if (IS_ERR(port->typec_port)) { | 3680 | if (IS_ERR(port->typec_port)) { |
3658 | err = PTR_ERR(port->typec_port); | 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 | return port; | 3711 | return port; |
3689 | 3712 | ||
3690 | out_destroy_wq: | 3713 | out_destroy_wq: |
3714 | usb_role_switch_put(port->role_sw); | ||
3691 | destroy_workqueue(port->wq); | 3715 | destroy_workqueue(port->wq); |
3692 | return ERR_PTR(err); | 3716 | return ERR_PTR(err); |
3693 | } | 3717 | } |
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h index 3e8bdaa5085a..f0d839daeaea 100644 --- a/include/linux/usb/tcpm.h +++ b/include/linux/usb/tcpm.h | |||
@@ -16,7 +16,6 @@ | |||
16 | #define __LINUX_USB_TCPM_H | 16 | #define __LINUX_USB_TCPM_H |
17 | 17 | ||
18 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
19 | #include <linux/usb/role.h> | ||
20 | #include <linux/usb/typec.h> | 19 | #include <linux/usb/typec.h> |
21 | #include "pd.h" | 20 | #include "pd.h" |
22 | 21 | ||
@@ -113,14 +112,6 @@ enum tcpc_mux_mode { | |||
113 | TCPC_MUX_DP_ENABLED, | 112 | TCPC_MUX_DP_ENABLED, |
114 | }; | 113 | }; |
115 | 114 | ||
116 | struct tcpc_mux_dev { | ||
117 | int (*set)(struct tcpc_mux_dev *dev, enum tcpc_mux_mode mux_mode, | ||
118 | enum usb_role usb_role, | ||
119 | enum typec_cc_polarity polarity); | ||
120 | bool dfp_only; | ||
121 | void *priv_data; | ||
122 | }; | ||
123 | |||
124 | /** | 115 | /** |
125 | * struct tcpc_dev - Port configuration and callback functions | 116 | * struct tcpc_dev - Port configuration and callback functions |
126 | * @config: Pointer to port configuration | 117 | * @config: Pointer to port configuration |
@@ -172,7 +163,6 @@ struct tcpc_dev { | |||
172 | int (*try_role)(struct tcpc_dev *dev, int role); | 163 | int (*try_role)(struct tcpc_dev *dev, int role); |
173 | int (*pd_transmit)(struct tcpc_dev *dev, enum tcpm_transmit_type type, | 164 | int (*pd_transmit)(struct tcpc_dev *dev, enum tcpm_transmit_type type, |
174 | const struct pd_message *msg); | 165 | const struct pd_message *msg); |
175 | struct tcpc_mux_dev *mux; | ||
176 | }; | 166 | }; |
177 | 167 | ||
178 | struct tcpm_port; | 168 | struct tcpm_port; |