On Wed, Apr 22, 2020 at 04:25:36PM +0300, Heikki Krogerus wrote: > I'm attaching a diff that has all the changes that you should need to > do to the tps6598x.c in order to get the role swapping working on your > board. Trying again... -- heikki
diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c index 0698addd1185..5f51397f0007 100644 --- a/drivers/usb/typec/tps6598x.c +++ b/drivers/usb/typec/tps6598x.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/regmap.h> #include <linux/interrupt.h> +#include <linux/usb/role.h> #include <linux/usb/typec.h> /* Register offsets */ @@ -94,6 +95,8 @@ struct tps6598x { struct typec_port *port; struct typec_partner *partner; struct usb_pd_identity partner_identity; + + struct usb_role_switch *role_sw; }; /* @@ -175,6 +178,18 @@ tps6598x_write_4cc(struct tps6598x *tps, u8 reg, const char *val) return tps6598x_block_write(tps, reg, val, 4); } +static int tps6598x_set_data_role(struct tps6598x *tps, + enum typec_data_role role) +{ + enum usb_role usb_role; + + usb_role = role == TYPEC_HOST ? USB_ROLE_HOST : USB_ROLE_DEVICE; + + typec_set_data_role(tps->port, role); + + return usb_role_switch_set_role(tps->role_sw, usb_role); +} + static int tps6598x_read_partner_identity(struct tps6598x *tps) { struct tps6598x_rx_identity_reg id; @@ -220,7 +235,7 @@ static int tps6598x_connect(struct tps6598x *tps, u32 status) typec_set_pwr_opmode(tps->port, mode); typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status)); typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status)); - typec_set_data_role(tps->port, TPS_STATUS_DATAROLE(status)); + tps6598x_set_data_role(tps, TPS_STATUS_DATAROLE(status)); tps->partner = typec_register_partner(tps->port, &desc); if (IS_ERR(tps->partner)) @@ -241,6 +256,7 @@ static void tps6598x_disconnect(struct tps6598x *tps, u32 status) typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status)); typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status)); typec_set_data_role(tps->port, TPS_STATUS_DATAROLE(status)); + usb_role_switch_set_role(tps->role_sw, USB_ROLE_NONE); } static int tps6598x_exec_cmd(struct tps6598x *tps, const char *cmd, @@ -328,7 +344,7 @@ static int tps6598x_dr_set(struct typec_port *port, enum typec_data_role role) goto out_unlock; } - typec_set_data_role(tps->port, role); + ret = tps6598x_set_data_role(tps, role); out_unlock: mutex_unlock(&tps->lock); @@ -472,6 +488,10 @@ static int tps6598x_probe(struct i2c_client *client) if (ret < 0 || !vid) return -ENODEV; + tps->role_sw = usb_role_switch_get(&client->dev); + if (IS_ERR(tps->role_sw)) + return PTR_ERR(tps->role_sw); + /* * Checking can the adapter handle SMBus protocol. If it can not, the * driver needs to take care of block reads separately.