Commit 6ecc632d authored by Li Jun's avatar Li Jun Committed by Greg Kroah-Hartman

usb: typec: tcpm: set correct data role for non-DRD

Since the typec port data role is separated from power role,
so check the port data capability when setting data role.
Signed-off-by: default avatarLi Jun <jun.li@nxp.com>
Reviewed-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/1581666828-2063-1-git-send-email-jun.li@nxp.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 21d78d86
......@@ -373,6 +373,14 @@ struct pd_rx_event {
((port)->try_src_count == 0 && (port)->try_role == TYPEC_SOURCE && \
(port)->port_type == TYPEC_PORT_DRP)
#define tcpm_data_role_for_source(port) \
((port)->typec_caps.data == TYPEC_PORT_UFP ? \
TYPEC_DEVICE : TYPEC_HOST)
#define tcpm_data_role_for_sink(port) \
((port)->typec_caps.data == TYPEC_PORT_DFP ? \
TYPEC_HOST : TYPEC_DEVICE)
static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
{
if (port->port_type == TYPEC_PORT_DRP) {
......@@ -788,10 +796,30 @@ static int tcpm_set_roles(struct tcpm_port *port, bool attached,
else
orientation = TYPEC_ORIENTATION_REVERSE;
if (data == TYPEC_HOST)
usb_role = USB_ROLE_HOST;
else
usb_role = USB_ROLE_DEVICE;
if (port->typec_caps.data == TYPEC_PORT_DRD) {
if (data == TYPEC_HOST)
usb_role = USB_ROLE_HOST;
else
usb_role = USB_ROLE_DEVICE;
} else if (port->typec_caps.data == TYPEC_PORT_DFP) {
if (data == TYPEC_HOST) {
if (role == TYPEC_SOURCE)
usb_role = USB_ROLE_HOST;
else
usb_role = USB_ROLE_NONE;
} else {
return -ENOTSUPP;
}
} else {
if (data == TYPEC_DEVICE) {
if (role == TYPEC_SINK)
usb_role = USB_ROLE_DEVICE;
else
usb_role = USB_ROLE_NONE;
} else {
return -ENOTSUPP;
}
}
ret = tcpm_mux_set(port, TYPEC_STATE_USB, usb_role, orientation);
if (ret < 0)
......@@ -1817,7 +1845,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
tcpm_set_state(port, SOFT_RESET, 0);
break;
case PD_CTRL_DR_SWAP:
if (port->port_type != TYPEC_PORT_DRP) {
if (port->typec_caps.data != TYPEC_PORT_DRD) {
tcpm_queue_message(port, PD_MSG_CTRL_REJECT);
break;
}
......@@ -2618,7 +2646,8 @@ static int tcpm_src_attach(struct tcpm_port *port)
if (ret < 0)
return ret;
ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST);
ret = tcpm_set_roles(port, true, TYPEC_SOURCE,
tcpm_data_role_for_source(port));
if (ret < 0)
return ret;
......@@ -2740,7 +2769,8 @@ static int tcpm_snk_attach(struct tcpm_port *port)
if (ret < 0)
return ret;
ret = tcpm_set_roles(port, true, TYPEC_SINK, TYPEC_DEVICE);
ret = tcpm_set_roles(port, true, TYPEC_SINK,
tcpm_data_role_for_sink(port));
if (ret < 0)
return ret;
......@@ -2766,7 +2796,8 @@ static int tcpm_acc_attach(struct tcpm_port *port)
if (port->attached)
return 0;
ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST);
ret = tcpm_set_roles(port, true, TYPEC_SOURCE,
tcpm_data_role_for_source(port));
if (ret < 0)
return ret;
......@@ -3293,7 +3324,7 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_vconn(port, true);
tcpm_set_vbus(port, false);
tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE,
TYPEC_HOST);
tcpm_data_role_for_source(port));
tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER);
break;
case SRC_HARD_RESET_VBUS_ON:
......@@ -3308,7 +3339,7 @@ static void run_state_machine(struct tcpm_port *port)
if (port->pd_capable)
tcpm_set_charge(port, false);
tcpm_set_roles(port, port->self_powered, TYPEC_SINK,
TYPEC_DEVICE);
tcpm_data_role_for_sink(port));
/*
* VBUS may or may not toggle, depending on the adapter.
* If it doesn't toggle, transition to SNK_HARD_RESET_SINK_ON
......@@ -3969,7 +4000,7 @@ static int tcpm_dr_set(struct typec_port *p, enum typec_data_role data)
mutex_lock(&port->swap_lock);
mutex_lock(&port->lock);
if (port->port_type != TYPEC_PORT_DRP) {
if (port->typec_caps.data != TYPEC_PORT_DRD) {
ret = -EINVAL;
goto port_unlock;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment