]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
usb: typec: tcpm: allow sink (ufp) to toggle into accessory mode debug
authorMichael Grzeschik <m.grzeschik@pengutronix.de>
Thu, 3 Apr 2025 22:43:05 +0000 (00:43 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 11 Apr 2025 14:08:32 +0000 (16:08 +0200)
This patch extends the is_debug macro to cover the sink case (ufp). It
also handles the transition to access the DEBUG_ACC_ATTACHED state in
the sink case. It also handles the debounce case in which the cc
pins are not immediately valid after the plug event.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20250404-ml-topic-tcpm-v1-2-b99f44badce8@pengutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/typec/tcpm/tcpm.c

index 839697c14265e53682078b81e2fd71c4c86e8d8e..01714a42f848a705a51316f7ad7a9425df65d4e2 100644 (file)
@@ -67,6 +67,7 @@
                                                \
        S(ACC_UNATTACHED),                      \
        S(DEBUG_ACC_ATTACHED),                  \
+       S(DEBUG_ACC_DEBOUNCE),                  \
        S(AUDIO_ACC_ATTACHED),                  \
        S(AUDIO_ACC_DEBOUNCE),                  \
                                                \
@@ -621,7 +622,8 @@ static const char * const pd_rev[] = {
          !tcpm_cc_is_source((port)->cc1)))
 
 #define tcpm_port_is_debug(port) \
-       (tcpm_cc_is_source((port)->cc1) && tcpm_cc_is_source((port)->cc2))
+       ((tcpm_cc_is_source((port)->cc1) && tcpm_cc_is_source((port)->cc2)) || \
+        (tcpm_cc_is_sink((port)->cc1) && tcpm_cc_is_sink((port)->cc2)))
 
 #define tcpm_port_is_audio(port) \
        (tcpm_cc_is_audio((port)->cc1) && tcpm_cc_is_audio((port)->cc2))
@@ -4969,7 +4971,13 @@ static void run_state_machine(struct tcpm_port *port)
                        tcpm_set_state(port, SRC_UNATTACHED, PD_T_DRP_SRC);
                break;
        case SNK_ATTACH_WAIT:
-               if ((port->cc1 == TYPEC_CC_OPEN &&
+               if (tcpm_port_is_debug(port))
+                       tcpm_set_state(port, DEBUG_ACC_ATTACHED,
+                                      PD_T_CC_DEBOUNCE);
+               else if (tcpm_port_is_audio(port))
+                       tcpm_set_state(port, AUDIO_ACC_ATTACHED,
+                                      PD_T_CC_DEBOUNCE);
+               else if ((port->cc1 == TYPEC_CC_OPEN &&
                     port->cc2 != TYPEC_CC_OPEN) ||
                    (port->cc1 != TYPEC_CC_OPEN &&
                     port->cc2 == TYPEC_CC_OPEN))
@@ -4983,6 +4991,12 @@ static void run_state_machine(struct tcpm_port *port)
                if (tcpm_port_is_disconnected(port))
                        tcpm_set_state(port, SNK_UNATTACHED,
                                       PD_T_PD_DEBOUNCE);
+               else if (tcpm_port_is_debug(port))
+                       tcpm_set_state(port, DEBUG_ACC_ATTACHED,
+                                      PD_T_CC_DEBOUNCE);
+               else if (tcpm_port_is_audio(port))
+                       tcpm_set_state(port, AUDIO_ACC_ATTACHED,
+                                      PD_T_CC_DEBOUNCE);
                else if (port->vbus_present)
                        tcpm_set_state(port,
                                       tcpm_try_src(port) ? SRC_TRY
@@ -5281,7 +5295,10 @@ static void run_state_machine(struct tcpm_port *port)
        /* Accessory states */
        case ACC_UNATTACHED:
                tcpm_acc_detach(port);
-               tcpm_set_state(port, SRC_UNATTACHED, 0);
+               if (port->port_type == TYPEC_PORT_SRC)
+                       tcpm_set_state(port, SRC_UNATTACHED, 0);
+               else
+                       tcpm_set_state(port, SNK_UNATTACHED, 0);
                break;
        case DEBUG_ACC_ATTACHED:
        case AUDIO_ACC_ATTACHED:
@@ -5289,6 +5306,7 @@ static void run_state_machine(struct tcpm_port *port)
                if (ret < 0)
                        tcpm_set_state(port, ACC_UNATTACHED, 0);
                break;
+       case DEBUG_ACC_DEBOUNCE:
        case AUDIO_ACC_DEBOUNCE:
                tcpm_set_state(port, ACC_UNATTACHED, port->timings.cc_debounce_time);
                break;
@@ -5880,7 +5898,8 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
                }
                break;
        case SNK_UNATTACHED:
-               if (tcpm_port_is_sink(port))
+               if (tcpm_port_is_debug(port) || tcpm_port_is_audio(port) ||
+                   tcpm_port_is_sink(port))
                        tcpm_set_state(port, SNK_ATTACH_WAIT, 0);
                break;
        case SNK_ATTACH_WAIT:
@@ -5943,7 +5962,12 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
 
        case DEBUG_ACC_ATTACHED:
                if (cc1 == TYPEC_CC_OPEN || cc2 == TYPEC_CC_OPEN)
-                       tcpm_set_state(port, ACC_UNATTACHED, 0);
+                       tcpm_set_state(port, DEBUG_ACC_DEBOUNCE, 0);
+               break;
+
+       case DEBUG_ACC_DEBOUNCE:
+               if (tcpm_port_is_debug(port))
+                       tcpm_set_state(port, DEBUG_ACC_ATTACHED, 0);
                break;
 
        case SNK_TRY: