diff options
author | Hans de Goede <hdegoede@redhat.com> | 2018-03-20 08:57:06 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-03-22 08:40:10 -0400 |
commit | c6962c29729cc64177f56a466766daa7de9f87ac (patch) | |
tree | c08521ad2213d5a7086ab56f3dbb7078b17c19b1 | |
parent | ceeb162500c3480b660a47d509db7955a7913271 (diff) |
usb: typec: tcpm: Set USB role switch to device mode when configured as such
Setting the mux to MUX_NONE and the switch to USB_SWITCH_DISCONNECT when
the data-role is device is not correct. Plenty of devices support
operating as USB device through a (separate) USB device controller.
We really need 2 different versions of USB_SWITCH_CONNECT,
USB_SWITCH_CONNECT_HOST and USB_SWITCH_DEVICE. Rather then modifying the
tcpc_usb_switch enum for this, simply remove it and switch to the
usb_role enum which provides exactly this, this will save use needing to
convert betweent the 2 enums when calling an usb-role-switch driver later.
Besides switching to the usb_role type, this commit also actually sets the
mux to TYPEC_MUX_USB and the switch to USB_ROLE_DEVICE instead of setting
both to none when the data-role is device.
This commit also makes tcpm_reset_port() call tcpm_mux_set(port,
TYPEC_MUX_NONE, USB_ROLE_NONE) so that the mux and switch
do _not_ stay in their last mode after a detach.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/typec/tcpm.c | 22 | ||||
-rw-r--r-- | include/linux/usb/tcpm.h | 8 |
2 files changed, 13 insertions, 17 deletions
diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 62e710bb6367..2519b0d17f1f 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c | |||
@@ -604,15 +604,15 @@ void tcpm_pd_transmit_complete(struct tcpm_port *port, | |||
604 | EXPORT_SYMBOL_GPL(tcpm_pd_transmit_complete); | 604 | EXPORT_SYMBOL_GPL(tcpm_pd_transmit_complete); |
605 | 605 | ||
606 | static int tcpm_mux_set(struct tcpm_port *port, enum tcpc_mux_mode mode, | 606 | static int tcpm_mux_set(struct tcpm_port *port, enum tcpc_mux_mode mode, |
607 | enum tcpc_usb_switch config) | 607 | enum usb_role usb_role) |
608 | { | 608 | { |
609 | int ret = 0; | 609 | int ret = 0; |
610 | 610 | ||
611 | tcpm_log(port, "Requesting mux mode %d, config %d, polarity %d", | 611 | tcpm_log(port, "Requesting mux mode %d, usb-role %d, polarity %d", |
612 | mode, config, port->polarity); | 612 | mode, usb_role, port->polarity); |
613 | 613 | ||
614 | if (port->tcpc->mux) | 614 | if (port->tcpc->mux) |
615 | ret = port->tcpc->mux->set(port->tcpc->mux, mode, config, | 615 | ret = port->tcpc->mux->set(port->tcpc->mux, mode, usb_role, |
616 | port->polarity); | 616 | port->polarity); |
617 | 617 | ||
618 | return ret; | 618 | return ret; |
@@ -728,14 +728,15 @@ static int tcpm_set_attached_state(struct tcpm_port *port, bool attached) | |||
728 | static int tcpm_set_roles(struct tcpm_port *port, bool attached, | 728 | static int tcpm_set_roles(struct tcpm_port *port, bool attached, |
729 | enum typec_role role, enum typec_data_role data) | 729 | enum typec_role role, enum typec_data_role data) |
730 | { | 730 | { |
731 | enum usb_role usb_role; | ||
731 | int ret; | 732 | int ret; |
732 | 733 | ||
733 | if (data == TYPEC_HOST) | 734 | if (data == TYPEC_HOST) |
734 | ret = tcpm_mux_set(port, TYPEC_MUX_USB, | 735 | usb_role = USB_ROLE_HOST; |
735 | TCPC_USB_SWITCH_CONNECT); | ||
736 | else | 736 | else |
737 | ret = tcpm_mux_set(port, TYPEC_MUX_NONE, | 737 | usb_role = USB_ROLE_DEVICE; |
738 | TCPC_USB_SWITCH_DISCONNECT); | 738 | |
739 | ret = tcpm_mux_set(port, TYPEC_MUX_USB, usb_role); | ||
739 | if (ret < 0) | 740 | if (ret < 0) |
740 | return ret; | 741 | return ret; |
741 | 742 | ||
@@ -2028,7 +2029,7 @@ out_disable_vconn: | |||
2028 | out_disable_pd: | 2029 | out_disable_pd: |
2029 | port->tcpc->set_pd_rx(port->tcpc, false); | 2030 | port->tcpc->set_pd_rx(port->tcpc, false); |
2030 | out_disable_mux: | 2031 | out_disable_mux: |
2031 | tcpm_mux_set(port, TYPEC_MUX_NONE, TCPC_USB_SWITCH_DISCONNECT); | 2032 | tcpm_mux_set(port, TYPEC_MUX_NONE, USB_ROLE_NONE); |
2032 | return ret; | 2033 | return ret; |
2033 | } | 2034 | } |
2034 | 2035 | ||
@@ -2072,6 +2073,7 @@ static void tcpm_reset_port(struct tcpm_port *port) | |||
2072 | tcpm_init_vconn(port); | 2073 | tcpm_init_vconn(port); |
2073 | tcpm_set_current_limit(port, 0, 0); | 2074 | tcpm_set_current_limit(port, 0, 0); |
2074 | tcpm_set_polarity(port, TYPEC_POLARITY_CC1); | 2075 | tcpm_set_polarity(port, TYPEC_POLARITY_CC1); |
2076 | tcpm_mux_set(port, TYPEC_MUX_NONE, USB_ROLE_NONE); | ||
2075 | tcpm_set_attached_state(port, false); | 2077 | tcpm_set_attached_state(port, false); |
2076 | port->try_src_count = 0; | 2078 | port->try_src_count = 0; |
2077 | port->try_snk_count = 0; | 2079 | port->try_snk_count = 0; |
@@ -2122,8 +2124,6 @@ static int tcpm_snk_attach(struct tcpm_port *port) | |||
2122 | static void tcpm_snk_detach(struct tcpm_port *port) | 2124 | static void tcpm_snk_detach(struct tcpm_port *port) |
2123 | { | 2125 | { |
2124 | tcpm_detach(port); | 2126 | tcpm_detach(port); |
2125 | |||
2126 | /* XXX: (Dis)connect SuperSpeed mux? */ | ||
2127 | } | 2127 | } |
2128 | 2128 | ||
2129 | static int tcpm_acc_attach(struct tcpm_port *port) | 2129 | static int tcpm_acc_attach(struct tcpm_port *port) |
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h index 5a5e1d8c5b65..3e8bdaa5085a 100644 --- a/include/linux/usb/tcpm.h +++ b/include/linux/usb/tcpm.h | |||
@@ -16,6 +16,7 @@ | |||
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> | ||
19 | #include <linux/usb/typec.h> | 20 | #include <linux/usb/typec.h> |
20 | #include "pd.h" | 21 | #include "pd.h" |
21 | 22 | ||
@@ -98,11 +99,6 @@ struct tcpc_config { | |||
98 | const struct typec_altmode_desc *alt_modes; | 99 | const struct typec_altmode_desc *alt_modes; |
99 | }; | 100 | }; |
100 | 101 | ||
101 | enum tcpc_usb_switch { | ||
102 | TCPC_USB_SWITCH_CONNECT, | ||
103 | TCPC_USB_SWITCH_DISCONNECT, | ||
104 | }; | ||
105 | |||
106 | /* Mux state attributes */ | 102 | /* Mux state attributes */ |
107 | #define TCPC_MUX_USB_ENABLED BIT(0) /* USB enabled */ | 103 | #define TCPC_MUX_USB_ENABLED BIT(0) /* USB enabled */ |
108 | #define TCPC_MUX_DP_ENABLED BIT(1) /* DP enabled */ | 104 | #define TCPC_MUX_DP_ENABLED BIT(1) /* DP enabled */ |
@@ -119,7 +115,7 @@ enum tcpc_mux_mode { | |||
119 | 115 | ||
120 | struct tcpc_mux_dev { | 116 | struct tcpc_mux_dev { |
121 | int (*set)(struct tcpc_mux_dev *dev, enum tcpc_mux_mode mux_mode, | 117 | int (*set)(struct tcpc_mux_dev *dev, enum tcpc_mux_mode mux_mode, |
122 | enum tcpc_usb_switch usb_config, | 118 | enum usb_role usb_role, |
123 | enum typec_cc_polarity polarity); | 119 | enum typec_cc_polarity polarity); |
124 | bool dfp_only; | 120 | bool dfp_only; |
125 | void *priv_data; | 121 | void *priv_data; |