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: Li Jun <jun.li@nxp.com> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/1581666828-2063-1-git-send-email-jun.li@nxp.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
21d78d860c
commit
6ecc632d4b
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user