aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/typec/Kconfig1
-rw-r--r--drivers/usb/typec/fusb302/fusb302.c1
-rw-r--r--drivers/usb/typec/tcpm.c46
-rw-r--r--include/linux/usb/tcpm.h10
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
48config TYPEC_TCPM 48config 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
1245static const char * const cc_polarity_name[] = { 1244static 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,
604EXPORT_SYMBOL_GPL(tcpm_pd_transmit_complete); 606EXPORT_SYMBOL_GPL(tcpm_pd_transmit_complete);
605 607
606static int tcpm_mux_set(struct tcpm_port *port, enum tcpc_mux_mode mode, 608static 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
621static int tcpm_set_polarity(struct tcpm_port *port, 630static int tcpm_set_polarity(struct tcpm_port *port,
@@ -728,15 +737,21 @@ static int tcpm_set_attached_state(struct tcpm_port *port, bool attached)
728static int tcpm_set_roles(struct tcpm_port *port, bool attached, 737static 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:
2029out_disable_pd: 2044out_disable_pd:
2030 port->tcpc->set_pd_rx(port->tcpc, false); 2045 port->tcpc->set_pd_rx(port->tcpc, false);
2031out_disable_mux: 2046out_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
3690out_destroy_wq: 3713out_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
116struct 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
178struct tcpm_port; 168struct tcpm_port;