|
@@ -20,6 +20,7 @@
|
|
|
#include <linux/usb/pd.h>
|
|
|
#include <linux/usb/pd_bdo.h>
|
|
|
#include <linux/usb/pd_vdo.h>
|
|
|
+#include <linux/usb/role.h>
|
|
|
#include <linux/usb/tcpm.h>
|
|
|
#include <linux/usb/typec.h>
|
|
|
#include <linux/workqueue.h>
|
|
@@ -176,6 +177,7 @@ struct tcpm_port {
|
|
|
struct typec_port *typec_port;
|
|
|
|
|
|
struct tcpc_dev *tcpc;
|
|
|
+ struct usb_role_switch *role_sw;
|
|
|
|
|
|
enum typec_role vconn_role;
|
|
|
enum typec_role pwr_role;
|
|
@@ -604,18 +606,25 @@ void tcpm_pd_transmit_complete(struct tcpm_port *port,
|
|
|
EXPORT_SYMBOL_GPL(tcpm_pd_transmit_complete);
|
|
|
|
|
|
static int tcpm_mux_set(struct tcpm_port *port, enum tcpc_mux_mode mode,
|
|
|
- enum usb_role usb_role)
|
|
|
+ enum usb_role usb_role,
|
|
|
+ enum typec_orientation orientation)
|
|
|
{
|
|
|
- int ret = 0;
|
|
|
+ int ret;
|
|
|
|
|
|
- tcpm_log(port, "Requesting mux mode %d, usb-role %d, polarity %d",
|
|
|
- mode, usb_role, port->polarity);
|
|
|
+ tcpm_log(port, "Requesting mux mode %d, usb-role %d, orientation %d",
|
|
|
+ mode, usb_role, orientation);
|
|
|
|
|
|
- if (port->tcpc->mux)
|
|
|
- ret = port->tcpc->mux->set(port->tcpc->mux, mode, usb_role,
|
|
|
- port->polarity);
|
|
|
+ ret = typec_set_orientation(port->typec_port, orientation);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
|
|
|
- return ret;
|
|
|
+ if (port->role_sw) {
|
|
|
+ ret = usb_role_switch_set_role(port->role_sw, usb_role);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ return typec_set_mode(port->typec_port, mode);
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
static int tcpm_set_roles(struct tcpm_port *port, bool attached,
|
|
|
enum typec_role role, enum typec_data_role data)
|
|
|
{
|
|
|
+ enum typec_orientation orientation;
|
|
|
enum usb_role usb_role;
|
|
|
int ret;
|
|
|
|
|
|
+ if (port->polarity == TYPEC_POLARITY_CC1)
|
|
|
+ orientation = TYPEC_ORIENTATION_NORMAL;
|
|
|
+ else
|
|
|
+ orientation = TYPEC_ORIENTATION_REVERSE;
|
|
|
+
|
|
|
if (data == TYPEC_HOST)
|
|
|
usb_role = USB_ROLE_HOST;
|
|
|
else
|
|
|
usb_role = USB_ROLE_DEVICE;
|
|
|
|
|
|
- ret = tcpm_mux_set(port, TYPEC_MUX_USB, usb_role);
|
|
|
+ ret = tcpm_mux_set(port, TYPEC_MUX_USB, usb_role, orientation);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
@@ -2029,7 +2044,8 @@ out_disable_vconn:
|
|
|
out_disable_pd:
|
|
|
port->tcpc->set_pd_rx(port->tcpc, false);
|
|
|
out_disable_mux:
|
|
|
- tcpm_mux_set(port, TYPEC_MUX_NONE, USB_ROLE_NONE);
|
|
|
+ tcpm_mux_set(port, TYPEC_MUX_NONE, USB_ROLE_NONE,
|
|
|
+ TYPEC_ORIENTATION_NONE);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -2073,7 +2089,8 @@ static void tcpm_reset_port(struct tcpm_port *port)
|
|
|
tcpm_init_vconn(port);
|
|
|
tcpm_set_current_limit(port, 0, 0);
|
|
|
tcpm_set_polarity(port, TYPEC_POLARITY_CC1);
|
|
|
- tcpm_mux_set(port, TYPEC_MUX_NONE, USB_ROLE_NONE);
|
|
|
+ tcpm_mux_set(port, TYPEC_MUX_NONE, USB_ROLE_NONE,
|
|
|
+ TYPEC_ORIENTATION_NONE);
|
|
|
tcpm_set_attached_state(port, false);
|
|
|
port->try_src_count = 0;
|
|
|
port->try_snk_count = 0;
|
|
@@ -3653,6 +3670,12 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
|
|
|
port->partner_desc.identity = &port->partner_ident;
|
|
|
port->port_type = tcpc->config->type;
|
|
|
|
|
|
+ port->role_sw = usb_role_switch_get(port->dev);
|
|
|
+ if (IS_ERR(port->role_sw)) {
|
|
|
+ err = PTR_ERR(port->role_sw);
|
|
|
+ goto out_destroy_wq;
|
|
|
+ }
|
|
|
+
|
|
|
port->typec_port = typec_register_port(port->dev, &port->typec_caps);
|
|
|
if (IS_ERR(port->typec_port)) {
|
|
|
err = PTR_ERR(port->typec_port);
|
|
@@ -3688,6 +3711,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
|
|
|
return port;
|
|
|
|
|
|
out_destroy_wq:
|
|
|
+ usb_role_switch_put(port->role_sw);
|
|
|
destroy_workqueue(port->wq);
|
|
|
return ERR_PTR(err);
|
|
|
}
|