From: Peng Fan <[email protected]> When a sink-only port times out waiting for Source_Capabilities in SNK_WAIT_CAPABILITIES, the current code falls through to hard_reset_state() which sends a Hard Reset. For sink-only ports powered via VBUS, this causes the source to cut VBUS, resetting the board.
Unlike DRP ports which can potentially recover by switching roles, sink-only ports have no recovery path after a Hard Reset induced VBUS loss. Instead, gracefully fall back to SNK_READY to operate at the Type-C default current. Signed-off-by: Peng Fan <[email protected]> --- drivers/usb/tcpm/tcpm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/usb/tcpm/tcpm.c b/drivers/usb/tcpm/tcpm.c index d6c0be82333..25ff0926cdf 100644 --- a/drivers/usb/tcpm/tcpm.c +++ b/drivers/usb/tcpm/tcpm.c @@ -1647,6 +1647,8 @@ static void run_state_machine(struct udevice *dev) port->vbus_never_low = false; tcpm_set_state(dev, SOFT_RESET_SEND, PD_T_SINK_WAIT_CAP); + } else if (port->port_type == TYPEC_PORT_SNK) { + tcpm_set_state(dev, SNK_READY, 0); } else { tcpm_set_state(dev, hard_reset_state(port), PD_T_SINK_WAIT_CAP); @@ -1770,9 +1772,13 @@ static void run_state_machine(struct udevice *dev) port->message_id = 0; port->rx_msgid = -1; if (tcpm_pd_send_control(dev, PD_CTRL_SOFT_RESET)) - tcpm_set_state_cond(dev, hard_reset_state(port), 0); + tcpm_set_state_cond(dev, + port->port_type == TYPEC_PORT_SNK ? + SNK_READY : hard_reset_state(port), 0); else - tcpm_set_state_cond(dev, hard_reset_state(port), + tcpm_set_state_cond(dev, + port->port_type == TYPEC_PORT_SNK ? + SNK_READY : hard_reset_state(port), PD_T_SENDER_RESPONSE); break; -- 2.51.0

