Hi,

On Wed, Jun 17, 2026 at 04:23:01PM +0800, Peng Fan (OSS) wrote:
> 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]>
> ---

This violates the USB-PD specification, which says a reset should
be done in this case. The Rock 5B has the same limitation as your
board, but that's not true for all sink-only USB-C ports. A board
might have a battery (then self-powered property *should* be set
in the connector). A board might also be capable of being powered
over a different power source (e.g. Rock 5B supports PoE).

My suggestion would be to introduce a new property in the USB
connector DT binding for usb-connector and then divert from the
spec if that property is set:

main-power-source:
  description: This port is the main power source of the board.
    Setting this might result in diverting from the USB-PD
    specification to avoid disabling VBUS as that would usually
    reset the whole board.
  type: boolean

Greetings,

-- Sebastian

>  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
> 

Attachment: signature.asc
Description: PGP signature

Reply via email to