AMS is defined in PD2.0 as well. Remove the filter in tcpm_ams_start
and change the CC for Collision Avoidance only if the negotiated
revision is higher than PD2.0.

Signed-off-by: Kyle Tso <kyle...@google.com>
---
Changelog since v2:
- N/A; This is the first version.

 drivers/usb/typec/tcpm/tcpm.c | 129 +++++++++++++++-------------------
 1 file changed, 57 insertions(+), 72 deletions(-)

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 7d1c30c33097..aca1c5bbe870 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -391,6 +391,12 @@ struct pd_rx_event {
        struct pd_message msg;
 };
 
+static const char * const pd_rev[] = {
+       [PD_REV10]              = "rev1",
+       [PD_REV20]              = "rev2",
+       [PD_REV30]              = "rev3",
+};
+
 #define tcpm_cc_is_sink(cc) \
        ((cc) == TYPEC_CC_RP_DEF || (cc) == TYPEC_CC_RP_1_5 || \
         (cc) == TYPEC_CC_RP_3_0)
@@ -431,8 +437,6 @@ struct pd_rx_event {
        (tcpm_port_is_sink(port) && \
        ((port)->cc1 == TYPEC_CC_RP_3_0 || (port)->cc2 == TYPEC_CC_RP_3_0))
 
-#define support_ams(port)       ((port)->negotiated_rev >= PD_REV30)
-
 static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
 {
        if (port->port_type == TYPEC_PORT_DRP) {
@@ -679,14 +683,9 @@ static int tcpm_ams_finish(struct tcpm_port *port)
 {
        int ret = 0;
 
-       if (!support_ams(port)) {
-               port->upcoming_state = INVALID_STATE;
-               return -EOPNOTSUPP;
-       }
-
        tcpm_log(port, "AMS %s finished", tcpm_ams_str[port->ams]);
 
-       if (port->pwr_role == TYPEC_SOURCE)
+       if (port->negotiated_rev >= PD_REV30 && port->pwr_role == TYPEC_SOURCE)
                tcpm_set_cc(port, SINK_TX_OK);
 
        port->in_ams = false;
@@ -723,12 +722,13 @@ static int tcpm_pd_transmit(struct tcpm_port *port,
        case TCPC_TX_SUCCESS:
                port->message_id = (port->message_id + 1) & PD_HEADER_ID_MASK;
                /*
+                * USB PD rev 2.0, 8.3.2.2.1:
                 * USB PD rev 3.0, 8.3.2.1.3:
                 * "... Note that every AMS is Interruptible until the first
                 * Message in the sequence has been successfully sent (GoodCRC
                 * Message received)."
                 */
-               if (support_ams(port) && port->ams != NONE_AMS)
+               if (port->ams != NONE_AMS)
                        port->in_ams = true;
                break;
        case TCPC_TX_DISCARDED:
@@ -994,20 +994,18 @@ static void tcpm_set_state(struct tcpm_port *port, enum 
tcpm_state state,
                           unsigned int delay_ms)
 {
        if (delay_ms) {
-               tcpm_log(port, "pending state change %s -> %s @ %u ms%s%s",
+               tcpm_log(port, "pending state change %s -> %s @ %u ms [%s %s]",
                         tcpm_states[port->state], tcpm_states[state], delay_ms,
-                        support_ams(port) ? " in AMS " : "",
-                        support_ams(port) ? tcpm_ams_str[port->ams] : "");
+                        pd_rev[port->negotiated_rev], tcpm_ams_str[port->ams]);
                port->delayed_state = state;
                mod_delayed_work(port->wq, &port->state_machine,
                                 msecs_to_jiffies(delay_ms));
                port->delayed_runtime = jiffies + msecs_to_jiffies(delay_ms);
                port->delay_ms = delay_ms;
        } else {
-               tcpm_log(port, "state change %s -> %s%s%s",
+               tcpm_log(port, "state change %s -> %s [%s %s]",
                         tcpm_states[port->state], tcpm_states[state],
-                        support_ams(port) ? " in AMS " : "",
-                        support_ams(port) ? tcpm_ams_str[port->ams] : "");
+                        pd_rev[port->negotiated_rev], tcpm_ams_str[port->ams]);
                port->delayed_state = INVALID_STATE;
                port->prev_state = port->state;
                port->state = state;
@@ -1029,12 +1027,11 @@ static void tcpm_set_state_cond(struct tcpm_port *port, 
enum tcpm_state state,
                tcpm_set_state(port, state, delay_ms);
        else
                tcpm_log(port,
-                        "skipped %sstate change %s -> %s [%u ms], context 
state %s%s%s",
+                        "skipped %sstate change %s -> %s [%u ms], context 
state %s [%s %s]",
                         delay_ms ? "delayed " : "",
                         tcpm_states[port->state], tcpm_states[state],
                         delay_ms, tcpm_states[port->enter_state],
-                        support_ams(port) ? " in AMS " : "",
-                        support_ams(port) ? tcpm_ams_str[port->ams] : "");
+                        pd_rev[port->negotiated_rev], tcpm_ams_str[port->ams]);
 }
 
 static void tcpm_queue_message(struct tcpm_port *port,
@@ -1100,11 +1097,6 @@ static int tcpm_ams_start(struct tcpm_port *port, enum 
tcpm_ams ams)
 {
        int ret = 0;
 
-       if (!support_ams(port)) {
-               port->upcoming_state = INVALID_STATE;
-               return -EOPNOTSUPP;
-       }
-
        tcpm_log(port, "AMS %s start", tcpm_ams_str[ams]);
 
        if (!tcpm_ams_interruptible(port) && ams != HARD_RESET) {
@@ -1132,24 +1124,41 @@ static int tcpm_ams_start(struct tcpm_port *port, enum 
tcpm_ams ams)
                        }
                } else if (tcpm_vdm_ams(port)) {
                        /* tSinkTx is enforced in vdm_run_state_machine */
-                       tcpm_set_cc(port, SINK_TX_NG);
+                       if (port->negotiated_rev >= PD_REV30)
+                               tcpm_set_cc(port, SINK_TX_NG);
                        return ret;
                }
 
-               cc_req = port->cc_req;
-               tcpm_set_cc(port, SINK_TX_NG);
-               if (port->state == SRC_READY ||
-                   port->state == SRC_STARTUP ||
-                   port->state == SRC_SOFT_RESET_WAIT_SNK_TX ||
-                   port->state == SOFT_RESET ||
-                   port->state == SOFT_RESET_SEND)
-                       tcpm_set_state(port, AMS_START, cc_req == SINK_TX_OK ?
-                                      PD_T_SINK_TX : 0);
-               else
-                       tcpm_set_state(port, SRC_READY, cc_req == SINK_TX_OK ?
-                                      PD_T_SINK_TX : 0);
+               if (port->negotiated_rev >= PD_REV30) {
+                       cc_req = port->cc_req;
+                       tcpm_set_cc(port, SINK_TX_NG);
+               }
+
+               switch (port->state) {
+               case SRC_READY:
+               case SRC_STARTUP:
+               case SRC_SOFT_RESET_WAIT_SNK_TX:
+               case SOFT_RESET:
+               case SOFT_RESET_SEND:
+                       if (port->negotiated_rev >= PD_REV30)
+                               tcpm_set_state(port, AMS_START,
+                                              cc_req == SINK_TX_OK ?
+                                              PD_T_SINK_TX : 0);
+                       else
+                               tcpm_set_state(port, AMS_START, 0);
+                       break;
+               default:
+                       if (port->negotiated_rev >= PD_REV30)
+                               tcpm_set_state(port, SRC_READY,
+                                              cc_req == SINK_TX_OK ?
+                                              PD_T_SINK_TX : 0);
+                       else
+                               tcpm_set_state(port, SRC_READY, 0);
+                       break;
+               }
        } else {
-               if (!tcpm_sink_tx_ok(port) &&
+               if (port->negotiated_rev >= PD_REV30 &&
+                   !tcpm_sink_tx_ok(port) &&
                    ams != SOFT_RESET_AMS &&
                    ams != HARD_RESET) {
                        port->upcoming_state = INVALID_STATE;
@@ -1565,13 +1574,13 @@ static void vdm_run_state_machine(struct tcpm_port 
*port)
                                break;
                        }
 
-                       if (res == -EAGAIN)
+                       if (res < 0)
                                return;
                }
 
                port->vdm_state = VDM_STATE_SEND_MESSAGE;
                mod_delayed_work(port->wq, &port->vdm_state_machine,
-                                (res != -EOPNOTSUPP) &&
+                                (port->negotiated_rev >= PD_REV30) &&
                                 (port->pwr_role == TYPEC_SOURCE) &&
                                 (PD_VDO_CMDT(port->vdo_data[0]) == CMDT_INIT) ?
                                 PD_T_SINK_TX : 0);
@@ -1975,7 +1984,6 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
 {
        enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
        enum tcpm_state next_state;
-       int ret = 0;
 
        switch (type) {
        case PD_CTRL_GOOD_CRC:
@@ -2094,11 +2102,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                                tcpm_ams_finish(port);
                        if (port->pwr_role == TYPEC_SOURCE) {
                                port->upcoming_state = SRC_SEND_CAPABILITIES;
-                               ret = tcpm_ams_start(port, POWER_NEGOTIATION);
-                               if (ret == -EOPNOTSUPP)
-                                       tcpm_set_state(port,
-                                                      SRC_SEND_CAPABILITIES,
-                                                      0);
+                               tcpm_ams_start(port, POWER_NEGOTIATION);
                        } else {
                                tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
                        }
@@ -3254,9 +3258,7 @@ static void run_state_machine(struct tcpm_port *port)
                    port->ams == FAST_ROLE_SWAP)
                        tcpm_ams_finish(port);
                port->upcoming_state = SRC_SEND_CAPABILITIES;
-               ret = tcpm_ams_start(port, POWER_NEGOTIATION);
-               if (ret == -EOPNOTSUPP)
-                       tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
+               tcpm_ams_start(port, POWER_NEGOTIATION);
                break;
        case SRC_SEND_CAPABILITIES:
                port->caps_count++;
@@ -3620,11 +3622,7 @@ static void run_state_machine(struct tcpm_port *port)
                 * thus set upcoming_state to INVALID_STATE.
                 */
                port->upcoming_state = INVALID_STATE;
-               ret = tcpm_ams_start(port, HARD_RESET);
-               if (ret == -EOPNOTSUPP) {
-                       tcpm_pd_transmit(port, TCPC_TX_HARD_RESET, NULL);
-                       tcpm_set_state(port, HARD_RESET_START, 0);
-               }
+               tcpm_ams_start(port, HARD_RESET);
                break;
        case HARD_RESET_START:
                port->hard_reset_count++;
@@ -3709,9 +3707,7 @@ static void run_state_machine(struct tcpm_port *port)
                tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
                if (port->pwr_role == TYPEC_SOURCE) {
                        port->upcoming_state = SRC_SEND_CAPABILITIES;
-                       ret = tcpm_ams_start(port, POWER_NEGOTIATION);
-                       if (ret == -EOPNOTSUPP)
-                               tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
+                       tcpm_ams_start(port, POWER_NEGOTIATION);
                } else {
                        tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0);
                }
@@ -3721,9 +3717,7 @@ static void run_state_machine(struct tcpm_port *port)
                if (port->ams != NONE_AMS)
                        tcpm_ams_finish(port);
                port->upcoming_state = SOFT_RESET_SEND;
-               ret = tcpm_ams_start(port, SOFT_RESET_AMS);
-               if (ret == -EOPNOTSUPP)
-                       tcpm_set_state(port, SOFT_RESET_SEND, 0);
+               tcpm_ams_start(port, SOFT_RESET_AMS);
                break;
        case SOFT_RESET_SEND:
                port->message_id = 0;
@@ -3930,7 +3924,7 @@ static void run_state_machine(struct tcpm_port *port)
                               port->vbus_present ? PD_T_PS_SOURCE_OFF : 0);
                break;
 
-       /* Collision Avoidance state */
+       /* AMS intermediate state */
        case AMS_START:
                if (port->upcoming_state == INVALID_STATE) {
                        tcpm_set_state(port, port->pwr_role == TYPEC_SOURCE ?
@@ -4392,9 +4386,6 @@ static int tcpm_dr_set(const struct typec_capability *cap,
                if (ret == -EAGAIN) {
                        port->upcoming_state = INVALID_STATE;
                        goto port_unlock;
-               } else if (ret == -EOPNOTSUPP) {
-                       port->upcoming_state = INVALID_STATE;
-                       tcpm_set_state(port, DR_SWAP_SEND, 0);
                }
        }
 
@@ -4447,9 +4438,6 @@ static int tcpm_pr_set(const struct typec_capability *cap,
        if (ret == -EAGAIN) {
                port->upcoming_state = INVALID_STATE;
                goto port_unlock;
-       } else if (ret == -EOPNOTSUPP) {
-               port->upcoming_state = INVALID_STATE;
-               tcpm_set_state(port, PR_SWAP_SEND, 0);
        }
 
        port->swap_status = 0;
@@ -4496,9 +4484,6 @@ static int tcpm_vconn_set(const struct typec_capability 
*cap,
        if (ret == -EAGAIN) {
                port->upcoming_state = INVALID_STATE;
                goto port_unlock;
-       } else if (ret == -EOPNOTSUPP) {
-               port->upcoming_state = INVALID_STATE;
-               tcpm_set_state(port, VCONN_SWAP_SEND, 0);
        }
 
        port->swap_status = 0;
@@ -4570,7 +4555,7 @@ static int tcpm_pps_set_op_curr(struct tcpm_port *port, 
u16 op_curr)
 
        port->upcoming_state = SNK_NEGOTIATE_PPS_CAPABILITIES;
        ret = tcpm_ams_start(port, POWER_NEGOTIATION);
-       if (ret == -EAGAIN || ret == -EOPNOTSUPP) {
+       if (ret == -EAGAIN) {
                port->upcoming_state = INVALID_STATE;
                goto port_unlock;
        }
@@ -4632,7 +4617,7 @@ static int tcpm_pps_set_out_volt(struct tcpm_port *port, 
u16 out_volt)
 
        port->upcoming_state = SNK_NEGOTIATE_PPS_CAPABILITIES;
        ret = tcpm_ams_start(port, POWER_NEGOTIATION);
-       if (ret == -EAGAIN || ret == -EOPNOTSUPP) {
+       if (ret == -EAGAIN) {
                port->upcoming_state = INVALID_STATE;
                goto port_unlock;
        }
@@ -4688,7 +4673,7 @@ static int tcpm_pps_activate(struct tcpm_port *port, bool 
activate)
        else
                port->upcoming_state = SNK_NEGOTIATE_CAPABILITIES;
        ret = tcpm_ams_start(port, POWER_NEGOTIATION);
-       if (ret == -EAGAIN || ret == -EOPNOTSUPP) {
+       if (ret == -EAGAIN) {
                port->upcoming_state = INVALID_STATE;
                goto port_unlock;
        }
-- 
2.23.0.351.gc4317032e6-goog

Reply via email to