Hi, On Tue, Nov 03, 2026 at 03:21:25PM +0400, Alexey Charkov wrote: > The driver sends every message with the SOP ordered set and reports > every received one as SOP, which leaves TCPM no way to reach the cable > plug. Start a message with the SOP' ordered set when TCPM asks for it, > and report a received message as SOP' when its RX FIFO token says so. > > SOP' is Sync-1, Sync-1, Sync-3, Sync-3 in USB PD. The Sync-3 TX token > and the RX FIFO token codes are from the token tables of the FUSB302B > datasheet. > > Nothing changes yet: TCPM asks for SOP' only from a port that claims > cable communication, and the chip drops SOP' packets until ENSOP1 is > set. > > Signed-off-by: Alexey Charkov > --- Reviewed-by: Sebastian Reichel Greetings, -- Sebastian > drivers/usb/typec/tcpm/fusb302.c | 26 ++++++++++++++++++++------ > drivers/usb/typec/tcpm/fusb302_reg.h | 10 ++++++++++ > 2 files changed, 30 insertions(+), 6 deletions(-) > > diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c > index 3319f6a2b0c9..8b3a2e095ef8 100644 > --- a/drivers/usb/typec/tcpm/fusb302.c > +++ b/drivers/usb/typec/tcpm/fusb302.c > @@ -961,7 +961,20 @@ static int tcpm_start_toggling(struct tcpc_dev *dev, > return ret; > } > > +/* K-codes of the ordered set that starts each kind of packet */ > +static const u8 fusb302_sop_tokens[][4] = { > + [TCPC_TX_SOP] = { > + FUSB302_TKN_SYNC1, FUSB302_TKN_SYNC1, > + FUSB302_TKN_SYNC1, FUSB302_TKN_SYNC2, > + }, > + [TCPC_TX_SOP_PRIME] = { > + FUSB302_TKN_SYNC1, FUSB302_TKN_SYNC1, > + FUSB302_TKN_SYNC3, FUSB302_TKN_SYNC3, > + }, > +}; > + > static int fusb302_pd_send_message(struct fusb302_chip *chip, > + enum tcpm_transmit_type type, > const struct pd_message *msg) > { > int ret = 0; > @@ -969,11 +982,9 @@ static int fusb302_pd_send_message(struct fusb302_chip *chip, > u8 pos = 0; > int len; > > - /* SOP tokens */ > - buf[pos++] = FUSB302_TKN_SYNC1; > - buf[pos++] = FUSB302_TKN_SYNC1; > - buf[pos++] = FUSB302_TKN_SYNC1; > - buf[pos++] = FUSB302_TKN_SYNC2; > + memcpy(&buf[pos], fusb302_sop_tokens[type], > + sizeof(fusb302_sop_tokens[type])); > + pos += sizeof(fusb302_sop_tokens[type]); > > len = pd_header_cnt_le(msg->header) * 4; > /* plug 2 for header */ > @@ -1037,6 +1048,7 @@ static int tcpm_pd_transmit(struct tcpc_dev *dev, enum tcpm_transmit_type type, > mutex_lock(&chip->lock); > switch (type) { > case TCPC_TX_SOP: > + case TCPC_TX_SOP_PRIME: > /* nRetryCount 3 in P2.0 spec, whereas 2 in PD3.0 spec */ > ret = fusb302_enable_tx_auto_retries(chip, negotiated_rev > PD_REV20 ? > FUSB_REG_CONTROL3_N_RETRIES_2 : > @@ -1044,7 +1056,7 @@ static int tcpm_pd_transmit(struct tcpc_dev *dev, enum tcpm_transmit_type type, > if (ret < 0) > fusb302_log(chip, "Cannot update retry count ret=%d", ret); > > - ret = fusb302_pd_send_message(chip, msg); > + ret = fusb302_pd_send_message(chip, type, msg); > if (ret < 0) > fusb302_log(chip, > "cannot send PD message, ret=%d", ret); > @@ -1475,6 +1487,8 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip, > */ > if ((!len) && (pd_header_type_le(msg->header) == PD_CTRL_GOOD_CRC)) > tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS); > + else if ((token & FUSB302_RX_TKN_MASK) == FUSB302_RX_TKN_SOP1) > + tcpm_pd_receive(chip->tcpm_port, msg, TCPC_TX_SOP_PRIME); > else > tcpm_pd_receive(chip->tcpm_port, msg, TCPC_TX_SOP); > > diff --git a/drivers/usb/typec/tcpm/fusb302_reg.h b/drivers/usb/typec/tcpm/fusb302_reg.h > index edc0e4b0f1e6..c98a502bfbfc 100644 > --- a/drivers/usb/typec/tcpm/fusb302_reg.h > +++ b/drivers/usb/typec/tcpm/fusb302_reg.h > @@ -174,4 +174,14 @@ enum fusb302_txfifo_tokens { > FUSB302_TKN_TXOFF = 0xFE, > }; > > +/* Tokens starting each packet in the FUSB302 RX FIFO, valid under the mask */ > +#define FUSB302_RX_TKN_MASK GENMASK(7, 5) > +enum fusb302_rxfifo_tokens { > + FUSB302_RX_TKN_SOP2DB = 0x60, > + FUSB302_RX_TKN_SOP1DB = 0x80, > + FUSB302_RX_TKN_SOP2 = 0xA0, > + FUSB302_RX_TKN_SOP1 = 0xC0, > + FUSB302_RX_TKN_SOP = 0xE0, > +}; > + > #endif > > -- > 2.56.0 >