summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/build.mk7
-rw-r--r--common/usb_pe_ctvpd_sm.c (renamed from include/usb_pe_ctvpd_sm.h)36
-rw-r--r--common/usb_pe_sm.c12
-rw-r--r--common/usb_prl_sm.c307
-rw-r--r--common/usb_sm.c11
-rw-r--r--common/usb_tc_ctvpd_sm.c1736
-rw-r--r--common/usb_tc_sm.c43
-rw-r--r--common/usb_tc_vpd_sm.c358
-rw-r--r--include/usb_pe_sm.h8
-rw-r--r--include/usb_sm.h72
-rw-r--r--include/usb_tc_ctvpd_sm.h1993
-rw-r--r--include/usb_tc_sm.h72
-rw-r--r--include/usb_tc_vpd_sm.h454
-rw-r--r--test/usb_sm_framework_h3.c7
14 files changed, 2322 insertions, 2794 deletions
diff --git a/common/build.mk b/common/build.mk
index 3faeaae6e4..19dcbd98af 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -138,7 +138,12 @@ else
common-$(CONFIG_USB_SM_FRAMEWORK)+=usb_sm.o
common-$(CONFIG_USB_TYPEC_SM)+=usb_tc_sm.o
common-$(CONFIG_USB_PRL_SM)+=usb_prl_sm.o
-common-$(CONFIG_USB_PE_SM)+=usb_pe_sm.o
+ifneq ($(CONFIG_USB_PE_SM),)
+common-$(CONFIG_USB_TYPEC_VPD)+=usb_pe_ctvpd_sm.o
+common-$(CONFIG_USB_TYPEC_CTVPD)+=usb_pe_ctvpd_sm.o
+endif
+common-$(CONFIG_USB_TYPEC_VPD)+=usb_tc_vpd_sm.o
+common-$(CONFIG_USB_TYPEC_CTVPD)+=usb_tc_ctvpd_sm.o
endif
common-$(CONFIG_USB_PD_LOGGING)+=event_log.o pd_log.o
common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o
diff --git a/include/usb_pe_ctvpd_sm.h b/common/usb_pe_ctvpd_sm.c
index e2b2cde8c4..a8b1b1f0fe 100644
--- a/include/usb_pe_ctvpd_sm.h
+++ b/common/usb_pe_ctvpd_sm.c
@@ -17,9 +17,6 @@
/* USB Policy Engine Charge-Through VCONN Powered Device module */
-#ifndef __CROS_EC_USB_PE_CTVPD_H
-#define __CROS_EC_USB_PE_CTVPD_H
-
/* Policy Engine Flags */
#define PE_FLAGS_MSG_RECEIVED (1 << 0)
@@ -31,12 +28,6 @@ enum l_state {
static enum l_state local_state = PE_INIT;
-/*
- * PE_OBJ is a convenience macro to access struct sm_obj, which
- * must be the first member of struct policy_engine.
- */
-#define PE_OBJ(port) (SM_OBJ(pe[port]))
-
/**
* This is the PE Port object that contains information needed to
* implement a VCONN and Charge-Through VCONN Powered Device.
@@ -52,19 +43,8 @@ static struct policy_engine {
uint32_t flags;
} pe[CONFIG_USB_PD_PORT_COUNT];
-static unsigned int pe_request(int port, enum signal sig);
-static unsigned int pe_request_entry(int port);
-static unsigned int pe_request_run(int port);
-
-static unsigned int do_nothing_exit(int port);
-static unsigned int get_super_state(int port);
-
-static const state_sig pe_request_sig[] = {
- pe_request_entry,
- pe_request_run,
- do_nothing_exit,
- get_super_state
-};
+/* Policy Engine states */
+DECLARE_STATE(pe, request, NOOP_EXIT);
void pe_init(int port)
{
@@ -225,15 +205,3 @@ static unsigned int pe_request_run(int port)
return 0;
}
-
-static unsigned int do_nothing_exit(int port)
-{
- return 0;
-}
-
-static unsigned int get_super_state(int port)
-{
- return RUN_SUPER;
-}
-
-#endif /* __CROS_EC_USB_PE_CTVPD_H */
diff --git a/common/usb_pe_sm.c b/common/usb_pe_sm.c
deleted file mode 100644
index 91f8b587ed..0000000000
--- a/common/usb_pe_sm.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Copyright 2019 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "common.h"
-
-/* Include USB PD Policy Engine State Machine */
-#if defined(CONFIG_USB_TYPEC_VPD) || defined(CONFIG_USB_TYPEC_CTVPD)
-#include "usb_pe_ctvpd_sm.h"
-#else
-#error "A USB PD Policy Engine State Machine must be defined."
-#endif
diff --git a/common/usb_prl_sm.c b/common/usb_prl_sm.c
index 42b4ee3c24..ec29b66fbb 100644
--- a/common/usb_prl_sm.c
+++ b/common/usb_prl_sm.c
@@ -153,292 +153,43 @@ struct extended_msg emsg[CONFIG_USB_PD_PORT_COUNT];
/* Common Protocol Layer Message Transmission */
static void prl_tx_construct_message(int port);
-static unsigned int prl_tx_phy_layer_reset(int port, enum signal sig);
-static unsigned int prl_tx_phy_layer_reset_entry(int port);
-static unsigned int prl_tx_phy_layer_reset_run(int port);
-
-static unsigned int prl_tx_wait_for_message_request(int port, enum signal sig);
-static unsigned int prl_tx_wait_for_message_request_entry(int port);
-static unsigned int prl_tx_wait_for_message_request_run(int port);
-
-static unsigned int prl_tx_layer_reset_for_transmit(int port, enum signal sig);
-static unsigned int prl_tx_layer_reset_for_transmit_entry(int port);
-static unsigned int prl_tx_layer_reset_for_transmit_run(int port);
-
-static unsigned int prl_tx_wait_for_phy_response(int port, enum signal sig);
-static unsigned int prl_tx_wait_for_phy_response_entry(int port);
-static unsigned int prl_tx_wait_for_phy_response_run(int port);
-static unsigned int prl_tx_wait_for_phy_response_exit(int port);
-
-static unsigned int prl_tx_src_source_tx(int port, enum signal sig);
-static unsigned int prl_tx_src_source_tx_entry(int port);
-static unsigned int prl_tx_src_source_tx_run(int port);
-
-static unsigned int prl_tx_snk_start_ams(int port, enum signal sig);
-static unsigned int prl_tx_snk_start_ams_entry(int port);
-static unsigned int prl_tx_snk_start_ams_run(int port);
+DECLARE_STATE(prl, tx_phy_layer_reset, NOOP_EXIT);
+DECLARE_STATE(prl, tx_wait_for_message_request, NOOP_EXIT);
+DECLARE_STATE(prl, tx_layer_reset_for_transmit, NOOP_EXIT);
+DECLARE_STATE(prl, tx_wait_for_phy_response, WITH_EXIT);
+DECLARE_STATE(prl, tx_src_source_tx, NOOP_EXIT);
+DECLARE_STATE(prl, tx_snk_start_ams, NOOP_EXIT);
/* Source Protocol Layser Message Transmission */
-static unsigned int prl_tx_src_pending(int port, enum signal sig);
-static unsigned int prl_tx_src_pending_entry(int port);
-static unsigned int prl_tx_src_pending_run(int port);
+DECLARE_STATE(prl, tx_src_pending, NOOP_EXIT);
/* Sink Protocol Layer Message Transmission */
-static unsigned int prl_tx_snk_pending(int port, enum signal sig);
-static unsigned int prl_tx_snk_pending_entry(int port);
-static unsigned int prl_tx_snk_pending_run(int port);
-
-static unsigned int prl_tx_discard_message(int port, enum signal sig);
-static unsigned int prl_tx_discard_message_entry(int port);
-static unsigned int prl_tx_discard_message_run(int port);
+DECLARE_STATE(prl, tx_snk_pending, NOOP_EXIT);
+DECLARE_STATE(prl, tx_discard_message, NOOP_EXIT);
/* Protocol Layer Message Reception */
static unsigned int prl_rx_wait_for_phy_message(int port, int evt);
/* Hard Reset Operation */
-static unsigned int prl_hr_wait_for_request(int port, enum signal sig);
-static unsigned int prl_hr_wait_for_request_entry(int port);
-static unsigned int prl_hr_wait_for_request_run(int port);
-
-static unsigned int prl_hr_reset_layer(int port, enum signal sig);
-static unsigned int prl_hr_reset_layer_entry(int port);
-static unsigned int prl_hr_reset_layer_run(int port);
-
-static unsigned int
- prl_hr_wait_for_phy_hard_reset_complete(int port, enum signal sig);
-static unsigned int prl_hr_wait_for_phy_hard_reset_complete_entry(int port);
-static unsigned int prl_hr_wait_for_phy_hard_reset_complete_run(int port);
-
-static unsigned int
- prl_hr_wait_for_pe_hard_reset_complete(int port, enum signal sig);
-static unsigned int prl_hr_wait_for_pe_hard_reset_complete_entry(int port);
-static unsigned int prl_hr_wait_for_pe_hard_reset_complete_run(int port);
-static unsigned int prl_hr_wait_for_pe_hard_reset_complete_exit(int port);
+DECLARE_STATE(prl, hr_wait_for_request, NOOP_EXIT);
+DECLARE_STATE(prl, hr_reset_layer, NOOP_EXIT);
+DECLARE_STATE(prl, hr_wait_for_phy_hard_reset_complete, NOOP_EXIT);
+DECLARE_STATE(prl, hr_wait_for_pe_hard_reset_complete, WITH_EXIT);
/* Chunked Rx */
-static unsigned int
- rch_wait_for_message_from_protocol_layer(int port, enum signal sig);
-static unsigned int rch_wait_for_message_from_protocol_layer_entry(int port);
-static unsigned int rch_wait_for_message_from_protocol_layer_run(int port);
-
-static unsigned int rch_processing_extended_message(int port, enum signal sig);
-static unsigned int rch_processing_extended_message_entry(int port);
-static unsigned int rch_processing_extended_message_run(int port);
-
-static unsigned int rch_requesting_chunk(int port, enum signal sig);
-static unsigned int rch_requesting_chunk_entry(int port);
-static unsigned int rch_requesting_chunk_run(int port);
-
-static unsigned int rch_waiting_chunk(int port, enum signal sig);
-static unsigned int rch_waiting_chunk_entry(int port);
-static unsigned int rch_waiting_chunk_run(int port);
-
-static unsigned int rch_report_error(int port, enum signal sig);
-static unsigned int rch_report_error_entry(int port);
-static unsigned int rch_report_error_run(int port);
+DECLARE_STATE(rch, wait_for_message_from_protocol_layer, NOOP_EXIT);
+DECLARE_STATE(rch, processing_extended_message, NOOP_EXIT);
+DECLARE_STATE(rch, requesting_chunk, NOOP_EXIT);
+DECLARE_STATE(rch, waiting_chunk, NOOP_EXIT);
+DECLARE_STATE(rch, report_error, NOOP_EXIT);
/* Chunked Tx */
-static unsigned int
- tch_wait_for_message_request_from_pe(int port, enum signal sig);
-static unsigned int tch_wait_for_message_request_from_pe_entry(int port);
-static unsigned int tch_wait_for_message_request_from_pe_run(int port);
-
-static unsigned int
- tch_wait_for_transmission_complete(int port, enum signal sig);
-static unsigned int tch_wait_for_transmission_complete_entry(int port);
-static unsigned int tch_wait_for_transmission_complete_run(int port);
-
-static unsigned int tch_construct_chunked_message(int port, enum signal sig);
-static unsigned int tch_construct_chunked_message_entry(int port);
-static unsigned int tch_construct_chunked_message_run(int port);
-
-static unsigned int tch_sending_chunked_message(int port, enum signal sig);
-static unsigned int tch_sending_chunked_message_entry(int port);
-static unsigned int tch_sending_chunked_message_run(int port);
-
-static unsigned int tch_wait_chunk_request(int port, enum signal sig);
-static unsigned int tch_wait_chunk_request_entry(int port);
-static unsigned int tch_wait_chunk_request_run(int port);
-
-static unsigned int tch_message_received(int port, enum signal sig);
-static unsigned int tch_message_received_entry(int port);
-static unsigned int tch_message_received_run(int port);
-
-static unsigned int do_nothing_exit(int port);
-static unsigned int get_super_state(int port);
-
-static const state_sig prl_tx_phy_layer_reset_sig[] = {
- prl_tx_phy_layer_reset_entry,
- prl_tx_phy_layer_reset_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig prl_tx_wait_for_message_request_sig[] = {
- prl_tx_wait_for_message_request_entry,
- prl_tx_wait_for_message_request_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig prl_tx_layer_reset_for_transmit_sig[] = {
- prl_tx_layer_reset_for_transmit_entry,
- prl_tx_layer_reset_for_transmit_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig prl_tx_wait_for_phy_response_sig[] = {
- prl_tx_wait_for_phy_response_entry,
- prl_tx_wait_for_phy_response_run,
- prl_tx_wait_for_phy_response_exit,
- get_super_state
-};
-
-static const state_sig prl_tx_src_source_tx_sig[] = {
- prl_tx_src_source_tx_entry,
- prl_tx_src_source_tx_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig prl_tx_snk_start_ams_sig[] = {
- prl_tx_snk_start_ams_entry,
- prl_tx_snk_start_ams_run,
- do_nothing_exit,
- get_super_state
-};
-
-/* Source Protocol Layser Message Transmission */
-static const state_sig prl_tx_src_pending_sig[] = {
- prl_tx_src_pending_entry,
- prl_tx_src_pending_run,
- do_nothing_exit,
- get_super_state
-};
-
-/* Sink Protocol Layer Message Transmission */
-static const state_sig prl_tx_snk_pending_sig[] = {
- prl_tx_snk_pending_entry,
- prl_tx_snk_pending_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig prl_tx_discard_message_sig[] = {
- prl_tx_discard_message_entry,
- prl_tx_discard_message_run,
- do_nothing_exit,
- get_super_state
-};
-
-/* Hard Reset Operation */
-static const state_sig prl_hr_wait_for_request_sig[] = {
- prl_hr_wait_for_request_entry,
- prl_hr_wait_for_request_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig prl_hr_reset_layer_sig[] = {
- prl_hr_reset_layer_entry,
- prl_hr_reset_layer_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig prl_hr_wait_for_phy_hard_reset_complete_sig[] = {
- prl_hr_wait_for_phy_hard_reset_complete_entry,
- prl_hr_wait_for_phy_hard_reset_complete_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig prl_hr_wait_for_pe_hard_reset_complete_sig[] = {
- prl_hr_wait_for_pe_hard_reset_complete_entry,
- prl_hr_wait_for_pe_hard_reset_complete_run,
- prl_hr_wait_for_pe_hard_reset_complete_exit,
- get_super_state
-};
-
-/* Chunked Rx */
-static const state_sig rch_wait_for_message_from_protocol_layer_sig[] = {
- rch_wait_for_message_from_protocol_layer_entry,
- rch_wait_for_message_from_protocol_layer_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig rch_processing_extended_message_sig[] = {
- rch_processing_extended_message_entry,
- rch_processing_extended_message_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig rch_requesting_chunk_sig[] = {
- rch_requesting_chunk_entry,
- rch_requesting_chunk_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig rch_waiting_chunk_sig[] = {
- rch_waiting_chunk_entry,
- rch_waiting_chunk_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig rch_report_error_sig[] = {
- rch_report_error_entry,
- rch_report_error_run,
- do_nothing_exit,
- get_super_state
-};
-
-/* Chunked Tx */
-static const state_sig tch_wait_for_message_request_from_pe_sig[] = {
- tch_wait_for_message_request_from_pe_entry,
- tch_wait_for_message_request_from_pe_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tch_wait_for_transmission_complete_sig[] = {
- tch_wait_for_transmission_complete_entry,
- tch_wait_for_transmission_complete_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tch_construct_chunked_message_sig[] = {
- tch_construct_chunked_message_entry,
- tch_construct_chunked_message_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tch_sending_chunked_message_sig[] = {
- tch_sending_chunked_message_entry,
- tch_sending_chunked_message_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tch_wait_chunk_request_sig[] = {
- tch_wait_chunk_request_entry,
- tch_wait_chunk_request_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tch_message_received_sig[] = {
- tch_message_received_entry,
- tch_message_received_run,
- do_nothing_exit,
- get_super_state
-};
+DECLARE_STATE(tch, wait_for_message_request_from_pe, NOOP_EXIT);
+DECLARE_STATE(tch, wait_for_transmission_complete, NOOP_EXIT);
+DECLARE_STATE(tch, construct_chunked_message, NOOP_EXIT);
+DECLARE_STATE(tch, sending_chunked_message, NOOP_EXIT);
+DECLARE_STATE(tch, wait_chunk_request, NOOP_EXIT);
+DECLARE_STATE(tch, message_received, NOOP_EXIT);
void pd_transmit_complete(int port, int status)
{
@@ -2151,13 +1902,3 @@ static unsigned int prl_rx_wait_for_phy_message(int port, int evt)
return 0;
}
-
-static unsigned int do_nothing_exit(int port)
-{
- return 0;
-}
-
-static unsigned int get_super_state(int port)
-{
- return RUN_SUPER;
-}
diff --git a/common/usb_sm.c b/common/usb_sm.c
index 6d3cacdb3b..de6d7959e3 100644
--- a/common/usb_sm.c
+++ b/common/usb_sm.c
@@ -164,3 +164,14 @@ void exe_state(int port, struct sm_obj *obj, enum signal sig)
obj->task_state(port, sig);
#endif
}
+
+unsigned int do_nothing_exit(int port)
+{
+ return 0;
+}
+
+unsigned int get_super_state(int port)
+{
+ return RUN_SUPER;
+}
+
diff --git a/common/usb_tc_ctvpd_sm.c b/common/usb_tc_ctvpd_sm.c
new file mode 100644
index 0000000000..5b471cf330
--- /dev/null
+++ b/common/usb_tc_ctvpd_sm.c
@@ -0,0 +1,1736 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "common.h"
+#include "console.h"
+#include "system.h"
+#include "task.h"
+#include "tcpm.h"
+#include "usb_pd.h"
+#include "usb_tc_ctvpd_sm.h"
+#include "usb_tc_sm.h"
+#include "vpd_api.h"
+
+/* USB Type-C CTVPD module */
+
+#ifdef CONFIG_COMMON_RUNTIME
+#define CPRINTF(format, args...) cprintf(CC_HOOK, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_HOOK, format, ## args)
+#else /* CONFIG_COMMON_RUNTIME */
+#define CPRINTF(format, args...)
+#define CPRINTS(format, args...)
+#endif
+
+/* Type-C Layer Flags */
+#define TC_FLAGS_VCONN_ON (1 << 0)
+
+#undef PD_DEFAULT_STATE
+/* Port default state at startup */
+#define PD_DEFAULT_STATE(port) tc_unattached_snk
+
+#define SUPPORT_TIMER_RESET_INIT 0
+#define SUPPORT_TIMER_RESET_REQUEST 1
+#define SUPPORT_TIMER_RESET_COMPLETE 2
+
+/**
+ * This is the Type-C Port object that contains information needed to
+ * implement a Charge Through VCONN Powered Device.
+ */
+struct type_c tc[CONFIG_USB_PD_PORT_COUNT];
+
+/* Type-C states */
+DECLARE_STATE(tc, disabled, WITH_EXIT);
+DECLARE_STATE(tc, error_recovery, NOOP_EXIT);
+DECLARE_STATE(tc, unattached_snk, NOOP_EXIT);
+DECLARE_STATE(tc, attach_wait_snk, NOOP_EXIT);
+DECLARE_STATE(tc, attached_snk, WITH_EXIT);
+DECLARE_STATE(tc, try_snk, NOOP_EXIT);
+DECLARE_STATE(tc, unattached_src, NOOP_EXIT);
+DECLARE_STATE(tc, attach_wait_src, NOOP_EXIT);
+DECLARE_STATE(tc, try_wait_src, NOOP_EXIT);
+DECLARE_STATE(tc, attached_src, NOOP_EXIT);
+DECLARE_STATE(tc, ct_try_snk, WITH_EXIT);
+DECLARE_STATE(tc, ct_attach_wait_unsupported, WITH_EXIT);
+DECLARE_STATE(tc, ct_attached_unsupported, WITH_EXIT);
+DECLARE_STATE(tc, ct_unattached_unsupported, WITH_EXIT);
+DECLARE_STATE(tc, ct_unattached_vpd, WITH_EXIT);
+DECLARE_STATE(tc, ct_disabled_vpd, NOOP_EXIT);
+DECLARE_STATE(tc, ct_attached_vpd, NOOP_EXIT);
+DECLARE_STATE(tc, ct_attach_wait_vpd, WITH_EXIT);
+
+/* Super States */
+DECLARE_STATE(tc, host_rard_ct_rd, NOOP_EXIT);
+DECLARE_STATE(tc, host_open_ct_open, NOOP_EXIT);
+DECLARE_STATE(tc, vbus_cc_iso, NOOP_EXIT);
+DECLARE_STATE(tc, host_rp3_ct_rd, NOOP_EXIT);
+DECLARE_STATE(tc, host_rp3_ct_rpu, NOOP_EXIT);
+DECLARE_STATE(tc, host_rpu_ct_rd, NOOP_EXIT);
+
+void tc_reset_support_timer(int port)
+{
+ tc[port].support_timer_reset |= SUPPORT_TIMER_RESET_REQUEST;
+}
+
+void tc_state_init(int port)
+{
+ int res = 0;
+ sm_state this_state;
+
+ res = tc_restart_tcpc(port);
+
+ CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready");
+ this_state = res ? tc_disabled : PD_DEFAULT_STATE(port);
+
+ init_state(port, TC_OBJ(port), this_state);
+
+ /* Disable pd state machines */
+ tc[port].pd_enable = 0;
+ tc[port].evt_timeout = 10*MSEC;
+ tc[port].power_role = PD_PLUG_CABLE_VPD;
+ tc[port].data_role = 0; /* Reserved for VPD */
+ tc[port].billboard_presented = 0;
+ tc[port].flags = 0;
+}
+
+void tc_event_check(int port, int evt)
+{
+ /* Do Nothing */
+}
+
+/**
+ * Disabled
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Remove the terminations from Host
+ * Remove the terminations from Charge-Through
+ */
+static unsigned int tc_disabled(int port, enum signal sig)
+{
+ int ret = 0;
+
+ ret = (*tc_disabled_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_open_ct_open);
+}
+
+static unsigned int tc_disabled_entry(int port)
+{
+ tc[port].state_id = DISABLED;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+ return 0;
+}
+
+static unsigned int tc_disabled_run(int port)
+{
+ task_wait_event(-1);
+ return RUN_SUPER;
+}
+
+static unsigned int tc_disabled_exit(int port)
+{
+#ifndef CONFIG_USB_PD_TCPC
+ if (tc_restart_tcpc(port) != 0) {
+ CPRINTS("TCPC p%d restart failed!", port);
+ return 0;
+ }
+#endif
+ CPRINTS("TCPC p%d resumed!", port);
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+
+ return 0;
+}
+
+/**
+ * ErrorRecovery
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Remove the terminations from Host
+ * Remove the terminations from Charge-Through
+ */
+static unsigned int tc_error_recovery(int port, enum signal sig)
+{
+ int ret = 0;
+
+ ret = (*tc_error_recovery_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_open_ct_open);
+}
+
+static unsigned int tc_error_recovery_entry(int port)
+{
+ tc[port].state_id = ERROR_RECOVERY;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+ /* Use cc_debounce state variable for error recovery timeout */
+ tc[port].cc_debounce = get_time().val + PD_T_ERROR_RECOVERY;
+ return 0;
+}
+
+static unsigned int tc_error_recovery_run(int port)
+{
+ if (get_time().val > tc[port].cc_debounce) {
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+ return 0;
+ }
+
+ return RUN_SUPER;
+}
+
+/**
+ * Unattached.SNK
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place Ra on VCONN and Rd on Host CC
+ * Place Rd on Charge-Through CCs
+ */
+static unsigned int tc_unattached_snk(int port, enum signal sig)
+{
+ int ret = 0;
+
+ ret = (*tc_unattached_snk_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rard_ct_rd);
+}
+
+static unsigned int tc_unattached_snk_entry(int port)
+{
+ tc[port].state_id = UNATTACHED_SNK;
+ if (tc[port].obj.last_state != tc_unattached_src)
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ tc[port].flags &= ~TC_FLAGS_VCONN_ON;
+ tc[port].cc_state = PD_CC_UNSET;
+
+ return 0;
+}
+
+static unsigned int tc_unattached_snk_run(int port)
+{
+ int host_cc;
+ int new_cc_state;
+ int cc1;
+ int cc2;
+
+ /* Check Host CC for connection */
+ vpd_host_get_cc(&host_cc);
+
+ /*
+ * Transition to AttachWait.SNK when a Source connection is
+ * detected, as indicated by the SNK.Rp state on its Host-side
+ * port’s CC pin.
+ */
+ if (cc_is_rp(host_cc)) {
+ set_state(port, TC_OBJ(port), tc_attach_wait_snk);
+ return 0;
+ }
+
+ /* Check Charge-Through CCs for connection */
+ vpd_ct_get_cc(&cc1, &cc2);
+
+ if (cc_is_rp(cc1) != cc_is_rp(cc2))
+ new_cc_state = PD_CC_DFP_ATTACHED;
+ else
+ new_cc_state = PD_CC_NONE;
+
+ /* Debounce Charge-Through CC state */
+ if (tc[port].cc_state != new_cc_state) {
+ tc[port].cc_state = new_cc_state;
+ tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
+ }
+
+ /* If we are here, Host CC must be open */
+
+ /* Wait for Charge-Through CC debounce */
+ if (get_time().val < tc[port].cc_debounce)
+ return 0;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * Unattached.SRC when the state of the Host-side port’s CC pin is
+ * SNK.Open for tDRP − dcSRC.DRP ∙ tDRP and both of the following
+ * is detected on the Charge-Through port.
+ * 1) SNK.Rp state is detected on exactly one of the CC1 or CC2
+ * pins for at least tCCDebounce
+ * 2) VBUS is detected
+ */
+ if (vpd_is_ct_vbus_present() &&
+ tc[port].cc_state == PD_CC_DFP_ATTACHED) {
+ set_state(port, TC_OBJ(port), tc_unattached_src);
+ return 0;
+ }
+
+ return RUN_SUPER;
+}
+
+/**
+ * AttachWait.SNK
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place Ra on VCONN and Rd on Host CC
+ * Place Rd on Charge-Through CCs
+ */
+static unsigned int tc_attach_wait_snk(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_attach_wait_snk_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rard_ct_rd);
+}
+
+static unsigned int tc_attach_wait_snk_entry(int port)
+{
+ tc[port].state_id = ATTACH_WAIT_SNK;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+ tc[port].host_cc_state = PD_CC_UNSET;
+
+ return 0;
+}
+
+static unsigned int tc_attach_wait_snk_run(int port)
+{
+ int host_new_cc_state;
+ int host_cc;
+
+ /* Check Host CC for connection */
+ vpd_host_get_cc(&host_cc);
+
+ if (cc_is_rp(host_cc))
+ host_new_cc_state = PD_CC_DFP_ATTACHED;
+ else
+ host_new_cc_state = PD_CC_NONE;
+
+ /* Debounce the Host CC state */
+ if (tc[port].host_cc_state != host_new_cc_state) {
+ tc[port].host_cc_state = host_new_cc_state;
+ if (host_new_cc_state == PD_CC_DFP_ATTACHED)
+ tc[port].host_cc_debounce = get_time().val +
+ PD_T_CC_DEBOUNCE;
+ else
+ tc[port].host_cc_debounce = get_time().val +
+ PD_T_PD_DEBOUNCE;
+ return 0;
+ }
+
+ /* Wait for Host CC debounce */
+ if (get_time().val < tc[port].host_cc_debounce)
+ return 0;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * Attached.SNK after the state of the Host-side port’s CC pin is
+ * SNK.Rp for at least tCCDebounce and either host-side VCONN or
+ * VBUS is detected.
+ *
+ * Transition to Unattached.SNK when the state of both the CC1 and
+ * CC2 pins is SNK.Open for at least tPDDebounce.
+ */
+ if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
+ (vpd_is_vconn_present() || vpd_is_host_vbus_present()))
+ set_state(port, TC_OBJ(port), tc_attached_snk);
+ else if (tc[port].host_cc_state == PD_CC_NONE)
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+
+ return 0;
+}
+
+/**
+ * Attached.SNK
+ */
+static unsigned int tc_attached_snk(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_attached_snk_sig[sig])(port);
+ return SUPER(ret, sig, 0);
+}
+
+static unsigned int tc_attached_snk_entry(int port)
+{
+ tc[port].state_id = ATTACHED_SNK;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Enable PD */
+ tc[port].pd_enable = 1;
+ set_polarity(port, 0);
+
+ /*
+ * This state can only be entered from states AttachWait.SNK
+ * and Try.SNK. So the Host port is isolated from the
+ * Charge-Through port. We only need to High-Z the
+ * Charge-Through ports CC1 and CC2 pins.
+ */
+ vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
+
+ tc[port].host_cc_state = PD_CC_UNSET;
+
+ /* Start Charge-Through support timer */
+ tc[port].support_timer_reset = SUPPORT_TIMER_RESET_INIT;
+ tc[port].support_timer = get_time().val + PD_T_AME;
+
+ /* Sample host CC every 2ms */
+ tc_set_timeout(port, 2*MSEC);
+
+ return 0;
+}
+
+static unsigned int tc_attached_snk_run(int port)
+{
+ int host_new_cc_state;
+ int host_cc;
+
+ /* Has host vbus and vconn been removed */
+ if (!vpd_is_host_vbus_present() && !vpd_is_vconn_present()) {
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+ return 0;
+ }
+
+ /*
+ * Reset the Charge-Through Support Timer when it first
+ * receives any USB PD Structured VDM Command it supports,
+ * which is the Discover Identity command. And this is only
+ * done one time.
+ */
+ if (tc[port].support_timer_reset == SUPPORT_TIMER_RESET_REQUEST) {
+ tc[port].support_timer_reset |= SUPPORT_TIMER_RESET_COMPLETE;
+ tc[port].support_timer = get_time().val + PD_T_AME;
+ }
+
+ /* Check Host CC for connection */
+ vpd_host_get_cc(&host_cc);
+
+ if (cc_is_rp(host_cc))
+ host_new_cc_state = PD_CC_DFP_ATTACHED;
+ else
+ host_new_cc_state = PD_CC_NONE;
+
+ /* Debounce the Host CC state */
+ if (tc[port].host_cc_state != host_new_cc_state) {
+ tc[port].host_cc_state = host_new_cc_state;
+ tc[port].host_cc_debounce = get_time().val + PD_T_VPDCTDD;
+ return 0;
+ }
+
+ /* Wait for Host CC debounce */
+ if (get_time().val < tc[port].host_cc_debounce)
+ return 0;
+
+ if (vpd_is_vconn_present()) {
+ if (!(tc[port].flags & TC_FLAGS_VCONN_ON)) {
+ /* VCONN detected. Remove RA */
+ vpd_host_set_pull(TYPEC_CC_RD, 0);
+ tc[port].flags |= TC_FLAGS_VCONN_ON;
+ }
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition
+ * to CTUnattached.VPD if VCONN is present and the state of
+ * its Host-side port’s CC pin is SNK.Open for tVPDCTDD.
+ */
+ if (tc[port].host_cc_state == PD_CC_NONE) {
+ set_state(port, TC_OBJ(port), tc_ct_unattached_vpd);
+ return 0;
+ }
+ }
+
+ /* Check the Support Timer */
+ if (get_time().val > tc[port].support_timer &&
+ !tc[port].billboard_presented) {
+ /*
+ * Present USB Billboard Device Class interface
+ * indicating that Charge-Through is not supported
+ */
+ tc[port].billboard_presented = 1;
+ vpd_present_billboard(BB_SNK);
+ }
+
+ return 0;
+}
+
+static unsigned int tc_attached_snk_exit(int port)
+{
+ /* Reset timeout value to 10ms */
+ tc_set_timeout(port, 10*MSEC);
+ tc[port].billboard_presented = 0;
+ vpd_present_billboard(BB_NONE);
+
+ return 0;
+}
+
+/**
+ * Super State HOST_RA_CT_RD
+ */
+static unsigned int tc_host_rard_ct_rd(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_host_rard_ct_rd_sig[sig])(port);
+ return SUPER(ret, sig, tc_vbus_cc_iso);
+}
+
+static unsigned int tc_host_rard_ct_rd_entry(int port)
+{
+ /* Place Ra on VCONN and Rd on Host CC */
+ vpd_host_set_pull(TYPEC_CC_RA_RD, 0);
+
+ /* Place Rd on Charge-Through CCs */
+ vpd_ct_set_pull(TYPEC_CC_RD, 0);
+
+ return 0;
+}
+
+static unsigned int tc_host_rard_ct_rd_run(int port)
+{
+ return RUN_SUPER;
+}
+
+/**
+ * Super State HOST_OPEN_CT_OPEN
+ */
+static unsigned int tc_host_open_ct_open(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_host_open_ct_open_sig[sig])(port);
+ return SUPER(ret, sig, tc_vbus_cc_iso);
+}
+
+static unsigned int tc_host_open_ct_open_entry(int port)
+{
+ /* Remove the terminations from Host */
+ vpd_host_set_pull(TYPEC_CC_OPEN, 0);
+
+ /* Remove the terminations from Charge-Through */
+ vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
+
+ return 0;
+}
+
+static unsigned int tc_host_open_ct_open_run(int port)
+{
+ return RUN_SUPER;
+}
+
+/**
+ * Super State VBUS_CC_ISO
+ */
+static unsigned int tc_vbus_cc_iso(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_vbus_cc_iso_sig[sig])(port);
+ return SUPER(ret, sig, 0);
+}
+
+static unsigned int tc_vbus_cc_iso_entry(int port)
+{
+ /* Isolate the Host-side port from the Charge-Through port */
+ vpd_vbus_pass_en(0);
+
+ /* Remove Charge-Through side port CCs */
+ vpd_ct_cc_sel(CT_OPEN);
+
+ /* Enable mcu communication and cc */
+ vpd_mcu_cc_en(1);
+
+ return 0;
+}
+
+static unsigned int tc_vbus_cc_iso_run(int port)
+{
+ return 0;
+}
+
+/**
+ * Unattached.SRC
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place RpUSB on Host CC
+ * Place Rd on Charge-Through CCs
+ */
+static unsigned int tc_unattached_src(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_unattached_src_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rpu_ct_rd);
+}
+
+static unsigned int tc_unattached_src_entry(int port)
+{
+ tc[port].state_id = UNATTACHED_SRC;
+ if (tc[port].obj.last_state != tc_unattached_snk)
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Get power from VBUS */
+ vpd_vconn_pwr_sel_odl(PWR_VBUS);
+
+ /* Make sure it's the Charge-Through Port's VBUS */
+ if (!vpd_is_ct_vbus_present()) {
+ set_state(port, TC_OBJ(port), tc_error_recovery);
+ return 0;
+ }
+
+ tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC;
+
+ return 0;
+}
+
+static unsigned int tc_unattached_src_run(int port)
+{
+ int host_cc;
+
+ /* Check Host CC for connection */
+ vpd_host_get_cc(&host_cc);
+
+ /*
+ * Transition to AttachWait.SRC when host-side VBUS is
+ * vSafe0V and SRC.Rd state is detected on the Host-side
+ * port’s CC pin.
+ */
+ if (!vpd_is_host_vbus_present() && host_cc == TYPEC_CC_VOLT_RD) {
+ set_state(port, TC_OBJ(port), tc_attach_wait_src);
+ return 0;
+ }
+
+ /*
+ * Transition to Unattached.SNK within tDRPTransition or
+ * if Charge-Through VBUS is removed.
+ */
+ if (!vpd_is_ct_vbus_present() ||
+ get_time().val > tc[port].next_role_swap) {
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+ return 0;
+ }
+
+ return RUN_SUPER;
+}
+
+/**
+ * AttachWait.SRC
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place RpUSB on Host CC
+ * Place Rd on Charge-Through CCs
+ */
+static unsigned int tc_attach_wait_src(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_attach_wait_src_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rpu_ct_rd);
+}
+
+static unsigned int tc_attach_wait_src_entry(int port)
+{
+ tc[port].state_id = ATTACH_WAIT_SRC;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ tc[port].host_cc_state = PD_CC_UNSET;
+
+ return 0;
+}
+
+static unsigned int tc_attach_wait_src_run(int port)
+{
+ int host_new_cc_state;
+ int host_cc;
+
+ /* Check Host CC for connection */
+ vpd_host_get_cc(&host_cc);
+
+ if (host_cc == TYPEC_CC_VOLT_RD)
+ host_new_cc_state = PD_CC_UFP_ATTACHED;
+ else
+ host_new_cc_state = PD_CC_NONE;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition
+ * to Unattached.SNK when the SRC.Open state is detected on the
+ * Host-side port’s CC or if Charge-Through VBUS falls below
+ * vSinkDisconnect. The Charge-Through VCONN-Powered USB Device
+ * shall detect the SRC.Open state within tSRCDisconnect, but
+ * should detect it as quickly as possible.
+ */
+ if (host_new_cc_state == PD_CC_NONE || !vpd_is_ct_vbus_present()) {
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+ return 0;
+ }
+
+ /* Debounce the Host CC state */
+ if (tc[port].host_cc_state != host_new_cc_state) {
+ tc[port].host_cc_state = host_new_cc_state;
+ tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
+ return 0;
+ }
+
+ /* Wait for Host CC debounce */
+ if (get_time().val < tc[port].cc_debounce)
+ return 0;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * Try.SNK when the host-side VBUS is at vSafe0V and the SRC.Rd
+ * state is on the Host-side port’s CC pin for at least tCCDebounce.
+ */
+ if (tc[port].host_cc_state == PD_CC_UFP_ATTACHED &&
+ !vpd_is_host_vbus_present()) {
+ set_state(port, TC_OBJ(port), tc_try_snk);
+ return 0;
+ }
+
+ return RUN_SUPER;
+}
+
+/**
+ * Attached.SRC
+ */
+static unsigned int tc_attached_src(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_attached_src_sig[sig])(port);
+ return SUPER(ret, sig, 0);
+}
+
+static unsigned int tc_attached_src_entry(int port)
+{
+ tc[port].state_id = ATTACHED_SRC;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Enable PD */
+ tc[port].pd_enable = 1;
+ set_polarity(port, 0);
+
+ /* Connect Charge-Through VBUS to Host VBUS */
+ vpd_vbus_pass_en(1);
+
+ /*
+ * Get power from VBUS. No need to test because
+ * the Host VBUS is connected to the Charge-Through
+ * VBUS
+ */
+ vpd_vconn_pwr_sel_odl(PWR_VBUS);
+
+ return 0;
+}
+
+static unsigned int tc_attached_src_run(int port)
+{
+ int host_cc;
+
+ /* Check Host CC for connection */
+ vpd_host_get_cc(&host_cc);
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * Unattached.SNK when VBUS falls below vSinkDisconnect or the
+ * Host-side port’s CC pin is SRC.Open. The Charge-Through
+ * VCONNPowered USB Device shall detect the SRC.Open state within
+ * tSRCDisconnect, but should detect it as quickly as possible.
+ */
+ if (!vpd_is_ct_vbus_present() || host_cc == TYPEC_CC_VOLT_OPEN)
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+
+ return 0;
+}
+
+/**
+ * Super State HOST_RPU_CT_RD
+ */
+static unsigned int tc_host_rpu_ct_rd(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_host_rpu_ct_rd_sig[sig])(port);
+ return SUPER(ret, sig, tc_vbus_cc_iso);
+}
+
+static unsigned int tc_host_rpu_ct_rd_entry(int port)
+{
+ /* Place RpUSB on Host CC */
+ vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_USB);
+
+ /* Place Rd on Charge-Through CCs */
+ vpd_ct_set_pull(TYPEC_CC_RD, 0);
+
+ return 0;
+}
+
+static unsigned int tc_host_rpu_ct_rd_run(int port)
+{
+ return RUN_SUPER;
+}
+
+/**
+ * Try.SNK
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place Ra on VCONN and Rd on Host CC
+ * Place Rd on Charge-Through CCs
+ */
+static unsigned int tc_try_snk(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_try_snk_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rard_ct_rd);
+}
+
+static unsigned int tc_try_snk_entry(int port)
+{
+ tc[port].state_id = TRY_SNK;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Get power from VBUS */
+ vpd_vconn_pwr_sel_odl(PWR_VBUS);
+
+ /* Make sure it's the Charge-Through Port's VBUS */
+ if (!vpd_is_ct_vbus_present()) {
+ set_state(port, TC_OBJ(port), tc_error_recovery);
+ return 0;
+ }
+
+ tc[port].host_cc_state = PD_CC_UNSET;
+
+ /* Using next_role_swap timer as try_src timer */
+ tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
+
+ return 0;
+}
+
+static unsigned int tc_try_snk_run(int port)
+{
+ int host_new_cc_state;
+ int host_cc;
+
+ /*
+ * Wait for tDRPTry before monitoring the Charge-Through
+ * port’s CC pins for the SNK.Rp
+ */
+ if (get_time().val < tc[port].next_role_swap)
+ return 0;
+
+ /* Check Host CC for connection */
+ vpd_host_get_cc(&host_cc);
+
+ if (cc_is_rp(host_cc))
+ host_new_cc_state = PD_CC_DFP_ATTACHED;
+ else
+ host_new_cc_state = PD_CC_NONE;
+
+ /* Debounce the Host CC state */
+ if (tc[port].host_cc_state != host_new_cc_state) {
+ tc[port].host_cc_state = host_new_cc_state;
+ tc[port].cc_debounce = get_time().val + PD_T_DEBOUNCE;
+ return 0;
+ }
+
+ /* Wait for Host CC debounce */
+ if (get_time().val < tc[port].cc_debounce)
+ return 0;
+
+ /*
+ * The Charge-Through VCONN-Powered USB Device shall then transition to
+ * Attached.SNK when the SNK.Rp state is detected on the Host-side
+ * port’s CC pin for at least tTryCCDebounce and VBUS or VCONN is
+ * detected on Host-side port.
+ *
+ * Alternatively, the Charge-Through VCONN-Powered USB Device shall
+ * transition to TryWait.SRC if Host-side SNK.Rp state is not detected
+ * for tTryCCDebounce.
+ */
+ if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
+ (vpd_is_host_vbus_present() || vpd_is_vconn_present()))
+ set_state(port, TC_OBJ(port), tc_attached_snk);
+ else if (tc[port].host_cc_state == PD_CC_NONE)
+ set_state(port, TC_OBJ(port), tc_try_wait_src);
+
+ return 0;
+}
+
+/**
+ * TryWait.SRC
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place RpUSB on Host CC
+ * Place Rd on Charge-Through CCs
+ */
+static unsigned int tc_try_wait_src(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_try_wait_src_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rpu_ct_rd);
+}
+
+static unsigned int tc_try_wait_src_entry(int port)
+{
+ tc[port].state_id = TRY_WAIT_SRC;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ tc[port].host_cc_state = PD_CC_UNSET;
+ tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
+
+ return 0;
+}
+
+static unsigned int tc_try_wait_src_run(int port)
+{
+ int host_new_cc_state;
+ int host_cc;
+
+ /* Check Host CC for connection */
+ vpd_host_get_cc(&host_cc);
+
+ if (host_cc == TYPEC_CC_VOLT_RD)
+ host_new_cc_state = PD_CC_UFP_ATTACHED;
+ else
+ host_new_cc_state = PD_CC_NONE;
+
+ /* Debounce the Host CC state */
+ if (tc[port].host_cc_state != host_new_cc_state) {
+ tc[port].host_cc_state = host_new_cc_state;
+ tc[port].host_cc_debounce =
+ get_time().val + PD_T_TRY_CC_DEBOUNCE;
+ return 0;
+ }
+
+ if (get_time().val > tc[port].host_cc_debounce) {
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition
+ * to Attached.SRC when host-side VBUS is at vSafe0V and the
+ * SRC.Rd state is detected on the Host-side port’s CC pin for
+ * at least tTryCCDebounce.
+ */
+ if (tc[port].host_cc_state == PD_CC_UFP_ATTACHED &&
+ !vpd_is_host_vbus_present()) {
+ set_state(port, TC_OBJ(port), tc_attached_src);
+ return 0;
+ }
+ }
+
+ if (get_time().val > tc[port].next_role_swap) {
+ /*
+ * The Charge-Through VCONN-Powered USB Device shall transition
+ * to Unattached.SNK after tDRPTry if the Host-side port’s CC
+ * pin is not in the SRC.Rd state.
+ */
+ if (tc[port].host_cc_state == PD_CC_NONE) {
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+ return 0;
+ }
+ }
+
+ return RUN_SUPER;
+}
+
+/**
+ * CTTry.SNK
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place RP3A0 on Host CC
+ * Connect Charge-Through Rd
+ * Get power from VCONN
+ */
+static unsigned int tc_ct_try_snk(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_ct_try_snk_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rp3_ct_rd);
+}
+
+static unsigned int tc_ct_try_snk_entry(int port)
+{
+ tc[port].state_id = CTTRY_SNK;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Enable PD */
+ tc[port].pd_enable = 1;
+ set_polarity(port, 0);
+
+ tc[port].cc_state = PD_CC_UNSET;
+ tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
+
+ return 0;
+}
+
+static unsigned int tc_ct_try_snk_run(int port)
+{
+ int new_cc_state;
+ int cc1;
+ int cc2;
+
+ /*
+ * Wait for tDRPTry before monitoring the Charge-Through
+ * port’s CC pins for the SNK.Rp
+ */
+ if (get_time().val < tc[port].next_role_swap)
+ return 0;
+
+ /* Check CT CC for connection */
+ vpd_ct_get_cc(&cc1, &cc2);
+
+ if (cc_is_rp(cc1) || cc_is_rp(cc2))
+ new_cc_state = PD_CC_DFP_ATTACHED;
+ else
+ new_cc_state = PD_CC_NONE;
+
+ /*
+ * The Charge-Through VCONN-Powered USB Device shall transition
+ * to Unattached.SNK if VCONN falls below vVCONNDisconnect.
+ */
+ if (!vpd_is_vconn_present()) {
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+ return 0;
+ }
+
+ /* Debounce the CT CC state */
+ if (tc[port].cc_state != new_cc_state) {
+ tc[port].cc_state = new_cc_state;
+ tc[port].cc_debounce = get_time().val + PD_T_DEBOUNCE;
+ tc[port].try_wait_debounce = get_time().val + PD_T_TRY_WAIT;
+
+ return 0;
+ }
+
+ if (get_time().val > tc[port].cc_debounce) {
+ /*
+ * The Charge-Through VCONN-Powered USB Device shall then
+ * transition to CTAttached.VPD when the SNK.Rp state is
+ * detected on the Charge-Through port’s CC pins for at
+ * least tTryCCDebounce and VBUS is detected on
+ * Charge-Through port.
+ */
+ if (tc[port].cc_state == PD_CC_DFP_ATTACHED &&
+ vpd_is_ct_vbus_present()) {
+ set_state(port, TC_OBJ(port), tc_ct_attached_vpd);
+ return 0;
+ }
+ }
+
+ if (get_time().val > tc[port].try_wait_debounce) {
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition
+ * to CTAttached.Unsupported if SNK.Rp state is not detected
+ * for tDRPTryWait.
+ */
+ if (tc[port].cc_state == PD_CC_NONE) {
+ set_state(port, TC_OBJ(port),
+ tc_ct_attached_unsupported);
+ return 0;
+ }
+ }
+
+ return RUN_SUPER;
+}
+
+static unsigned int tc_ct_try_snk_exit(int port)
+{
+ /* Disable PD */
+ tc[port].pd_enable = 0;
+
+ return 0;
+}
+
+/**
+ * CTAttachWait.Unsupported
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place RP3A0 on Host CC
+ * Place RPUSB on Charge-Through CC
+ * Get power from VCONN
+ */
+static unsigned int tc_ct_attach_wait_unsupported(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_ct_attach_wait_unsupported_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rp3_ct_rpu);
+}
+
+static unsigned int tc_ct_attach_wait_unsupported_entry(int port)
+{
+ tc[port].state_id = CTATTACH_WAIT_UNSUPPORTED;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Enable PD */
+ tc[port].pd_enable = 1;
+ set_polarity(port, 0);
+
+ tc[port].cc_state = PD_CC_UNSET;
+
+ return 0;
+}
+
+static unsigned int tc_ct_attach_wait_unsupported_run(int port)
+{
+ int new_cc_state;
+ int cc1;
+ int cc2;
+
+ /* Check CT CC for connection */
+ vpd_ct_get_cc(&cc1, &cc2);
+
+ if (cc_is_at_least_one_rd(cc1, cc2))
+ new_cc_state = PD_CC_DFP_ATTACHED;
+ else if (cc_is_audio_acc(cc1, cc2))
+ new_cc_state = PD_CC_AUDIO_ACC;
+ else /* (cc1 == TYPEC_CC_VOLT_OPEN or cc2 == TYPEC_CC_VOLT_OPEN */
+ new_cc_state = PD_CC_NONE;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * Unattached.SNK if VCONN falls below vVCONNDisconnect.
+ */
+ if (!vpd_is_vconn_present()) {
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+ return 0;
+ }
+
+ /* Debounce the cc state */
+ if (tc[port].cc_state != new_cc_state) {
+ tc[port].cc_state = new_cc_state;
+ tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
+ return 0;
+ }
+
+ /* Wait for CC debounce */
+ if (get_time().val < tc[port].cc_debounce)
+ return 0;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * CTUnattached.VPD when the state of either the Charge-Through
+ * Port’s CC1 or CC2 pin is SRC.Open for at least tCCDebounce.
+ *
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * CTTry.SNK if the state of at least one of the Charge-Through
+ * port’s CC pins is SRC.Rd, or if the state of both the CC1 and CC2
+ * pins is SRC.Ra. for at least tCCDebounce.
+ */
+ if (new_cc_state == PD_CC_NONE)
+ set_state(port, TC_OBJ(port), tc_ct_unattached_vpd);
+ else /* PD_CC_DFP_ATTACHED or PD_CC_AUDIO_ACC */
+ set_state(port, TC_OBJ(port), tc_ct_try_snk);
+
+ return 0;
+}
+
+static unsigned int tc_ct_attach_wait_unsupported_exit(int port)
+{
+ /* Disable PD */
+ tc[port].pd_enable = 0;
+
+ return 0;
+}
+
+/**
+ * CTAttached.Unsupported
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place RP3A0 on Host CC
+ * Place RPUSB on Charge-Through CC
+ * Get power from VCONN
+ */
+static unsigned int tc_ct_attached_unsupported(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_ct_attached_unsupported_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rp3_ct_rpu);
+}
+
+static unsigned int tc_ct_attached_unsupported_entry(int port)
+{
+ tc[port].state_id = CTATTACHED_UNSUPPORTED;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Present Billboard device */
+ vpd_present_billboard(BB_SNK);
+
+ return 0;
+}
+
+static unsigned int tc_ct_attached_unsupported_run(int port)
+{
+ int cc1;
+ int cc2;
+
+ /* Check CT CC for connection */
+ vpd_ct_get_cc(&cc1, &cc2);
+
+ if (!vpd_is_vconn_present()) {
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+ return 0;
+ }
+
+ /*
+ * The Charge-Through VCONN-Powered USB Device shall transition to
+ * CTUnattached.VPD when SRC.Open state is detected on both the
+ * Charge-Through port’s CC pins or the SRC.Open state is detected
+ * on one CC pin and SRC.Ra is detected on the other CC pin.
+ */
+ if ((cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN) ||
+ (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_RA) ||
+ (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_OPEN)) {
+ set_state(port, TC_OBJ(port), tc_ct_unattached_vpd);
+ return 0;
+ }
+
+ return RUN_SUPER;
+}
+
+static unsigned int tc_ct_attached_unsupported_exit(int port)
+{
+ vpd_present_billboard(BB_NONE);
+
+ return 0;
+}
+
+/**
+ * CTUnattached.Unsupported
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place RP3A0 on Host CC
+ * Place RPUSB on Charge-Through CC
+ * Get power from VCONN
+ */
+static unsigned int tc_ct_unattached_unsupported(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_ct_unattached_unsupported_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rp3_ct_rpu);
+}
+
+static unsigned int tc_ct_unattached_unsupported_entry(int port)
+{
+ tc[port].state_id = CTUNATTACHED_UNSUPPORTED;
+ if (tc[port].obj.last_state != tc_ct_unattached_vpd)
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Enable PD */
+ tc[port].pd_enable = 1;
+ set_polarity(port, 0);
+
+ tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC;
+
+ return 0;
+}
+
+static unsigned int tc_ct_unattached_unsupported_run(int port)
+{
+ int cc1;
+ int cc2;
+
+ /* Check CT CC for connection */
+ vpd_ct_get_cc(&cc1, &cc2);
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * CTAttachWait.Unsupported when a Sink connection is detected on
+ * the Charge-Through port, as indicated by the SRC.Rd state on at
+ * least one of the Charge-Through port’s CC pins or SRC.Ra state
+ * on both the CC1 and CC2 pins.
+ */
+ if (cc_is_at_least_one_rd(cc1, cc2) || cc_is_audio_acc(cc1, cc2)) {
+ set_state(port, TC_OBJ(port),
+ tc_ct_attach_wait_unsupported);
+ return 0;
+ }
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * Unattached.SNK if VCONN falls below vVCONNDisconnect.
+ */
+ if (!vpd_is_vconn_present()) {
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+ return 0;
+ }
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * CTUnattached.VPD within tDRPTransition after dcSRC.DRP ∙ tDRP.
+ */
+ if (get_time().val > tc[port].next_role_swap) {
+ set_state(port, TC_OBJ(port), tc_ct_unattached_vpd);
+ return 0;
+ }
+
+ return RUN_SUPER;
+}
+
+static unsigned int tc_ct_unattached_unsupported_exit(int port)
+{
+ /* Disable PD */
+ tc[port].pd_enable = 0;
+
+ return 0;
+}
+
+/**
+ * CTUnattached.VPD
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place RP3A0 on Host CC
+ * Connect Charge-Through Rd
+ * Get power from VCONN
+ */
+static unsigned int tc_ct_unattached_vpd(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_ct_unattached_vpd_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rp3_ct_rd);
+}
+
+static unsigned int tc_ct_unattached_vpd_entry(int port)
+{
+ tc[port].state_id = CTUNATTACHED_VPD;
+ if (tc[port].obj.last_state != tc_ct_unattached_unsupported)
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Enable PD */
+ tc[port].pd_enable = 1;
+ set_polarity(port, 0);
+
+ tc[port].cc_state = PD_CC_UNSET;
+
+ return 0;
+}
+
+static unsigned int tc_ct_unattached_vpd_run(int port)
+{
+ int new_cc_state;
+ int cc1;
+ int cc2;
+
+ /* Check CT CC for connection */
+ vpd_ct_get_cc(&cc1, &cc2);
+
+ if (cc_is_rp(cc1) != cc_is_rp(cc2))
+ new_cc_state = PD_CC_DFP_ATTACHED;
+ else if (!cc_is_rp(cc1) && !cc_is_rp(cc2))
+ new_cc_state = PD_CC_NONE;
+ else
+ new_cc_state = PD_CC_UNSET;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * CTAttachWait.VPD when a Source connection is detected on the
+ * Charge-Through port, as indicated by the SNK.Rp state on
+ * exactly one of the Charge-Through port’s CC pins.
+ */
+ if (new_cc_state == PD_CC_DFP_ATTACHED) {
+ set_state(port, TC_OBJ(port),
+ tc_ct_attach_wait_vpd);
+ return 0;
+ }
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * Unattached.SNK if VCONN falls below vVCONNDisconnect.
+ */
+ if (!vpd_is_vconn_present()) {
+ set_state(port, TC_OBJ(port),
+ tc_unattached_snk);
+ return 0;
+ }
+
+ /* Debounce the cc state */
+ if (new_cc_state != tc[port].cc_state) {
+ tc[port].cc_state = new_cc_state;
+ tc[port].cc_debounce = get_time().val + PD_T_DRP_SRC;
+ return 0;
+ }
+
+ if (get_time().val < tc[port].cc_debounce)
+ return 0;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * CTUnattached.Unsupported within tDRPTransition after the state
+ * of both the Charge-Through port’s CC1 and CC2 pins is SNK.Open
+ * for tDRP-dcSRC.DRP ∙ tDRP, or if directed.
+ */
+ if (tc[port].cc_state == PD_CC_NONE) {
+ set_state(port, TC_OBJ(port),
+ tc_ct_unattached_unsupported);
+ return 0;
+ }
+
+ return RUN_SUPER;
+}
+
+static unsigned int tc_ct_unattached_vpd_exit(int port)
+{
+ /* Disable PD */
+ tc[port].pd_enable = 0;
+
+ return 0;
+}
+
+/**
+ * CTDisabled.VPD
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Remove the terminations from Host
+ * Remove the terminations from Charge-Through
+ */
+static unsigned int tc_ct_disabled_vpd(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_ct_disabled_vpd_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_open_ct_open);
+}
+
+static unsigned int tc_ct_disabled_vpd_entry(int port)
+{
+ tc[port].state_id = CTDISABLED_VPD;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Get power from VBUS */
+ vpd_vconn_pwr_sel_odl(PWR_VBUS);
+
+ tc[port].next_role_swap = get_time().val + PD_T_VPDDISABLE;
+
+ return 0;
+}
+
+static unsigned int tc_ct_disabled_vpd_run(int port)
+{
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition
+ * to Unattached.SNK after tVPDDisable.
+ */
+ if (get_time().val > tc[port].next_role_swap)
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+
+ return 0;
+}
+
+/**
+ * CTAttached.VPD
+ */
+static unsigned int tc_ct_attached_vpd(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_ct_attached_vpd_sig[sig])(port);
+ return SUPER(ret, sig, 0);
+}
+
+static unsigned int tc_ct_attached_vpd_entry(int port)
+{
+ int cc1;
+ int cc2;
+
+ tc[port].state_id = CTATTACHED_VPD;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Get power from VCONN */
+ vpd_vconn_pwr_sel_odl(PWR_VCONN);
+
+ /*
+ * Detect which of the Charge-Through port’s CC1 or CC2
+ * pins is connected through the cable
+ */
+ vpd_ct_get_cc(&cc1, &cc2);
+ tc[port].ct_cc = cc_is_rp(cc2) ? CT_CC2 : CT_CC1;
+
+ /*
+ * 1. Remove or reduce any additional capacitance on the
+ * Host-side CC port
+ */
+ vpd_mcu_cc_en(0);
+
+ /*
+ * 2. Disable the Rp termination advertising 3.0 A on the
+ * host port’s CC pin
+ */
+ vpd_host_set_pull(TYPEC_CC_OPEN, 0);
+
+ /*
+ * 3. Passively multiplex the detected Charge-Through port’s
+ * CC pin through to the host port’s CC
+ */
+ vpd_ct_cc_sel(tc[port].ct_cc);
+
+ /*
+ * 4. Disable the Rd on the Charge-Through port’s CC1 and CC2
+ * pins
+ */
+ vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
+
+ /*
+ * 5. Connect the Charge-Through port’s VBUS through to the
+ * host port’s VBUS
+ */
+ vpd_vbus_pass_en(1);
+
+ tc[port].cc_state = PD_CC_UNSET;
+
+ return 0;
+}
+
+static unsigned int tc_ct_attached_vpd_run(int port)
+{
+ int new_cc_state;
+ int cc1;
+ int cc2;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * CTDisabled.VPD if VCONN falls below vVCONNDisconnect.
+ */
+ if (!vpd_is_vconn_present()) {
+ set_state(port, TC_OBJ(port), tc_ct_disabled_vpd);
+ return 0;
+ }
+
+ /* Check CT CC for connection */
+ vpd_ct_get_cc(&cc1, &cc2);
+ if ((tc[port].ct_cc ? cc2 : cc1) == TYPEC_CC_VOLT_OPEN)
+ new_cc_state = PD_CC_NONE;
+ else
+ new_cc_state = PD_CC_DFP_ATTACHED;
+
+ /* Debounce the cc state */
+ if (new_cc_state != tc[port].cc_state) {
+ tc[port].cc_state = new_cc_state;
+ tc[port].cc_debounce = get_time().val + PD_T_VPDCTDD;
+ return 0;
+ }
+
+ if (get_time().val < tc[port].pd_debounce)
+ return 0;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * CTUnattached.VPD when VBUS falls below vSinkDisconnect and the
+ * state of the passed-through CC pin is SNK.Open for tVPDCTDD.
+ */
+ if (tc[port].cc_state == PD_CC_NONE && !vpd_is_ct_vbus_present())
+ set_state(port, TC_OBJ(port), tc_ct_unattached_vpd);
+
+ return 0;
+}
+
+/**
+ * CTAttachWait.VPD
+ *
+ * Super State Entry Actions:
+ * Isolate the Host-side port from the Charge-Through port
+ * Enable mcu communication
+ * Place RP3A0 on Host CC
+ * Connect Charge-Through Rd
+ * Get power from VCONN
+ */
+static unsigned int tc_ct_attach_wait_vpd(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_ct_attach_wait_vpd_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rp3_ct_rd);
+}
+
+static unsigned int tc_ct_attach_wait_vpd_entry(int port)
+{
+ tc[port].state_id = CTATTACH_WAIT_VPD;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Enable PD */
+ tc[port].pd_enable = 1;
+ set_polarity(port, 0);
+
+ tc[port].cc_state = PD_CC_UNSET;
+
+ /* Sample CCs every 2ms */
+ tc_set_timeout(port, 2 * MSEC);
+ return 0;
+}
+
+static unsigned int tc_ct_attach_wait_vpd_run(int port)
+{
+ int new_cc_state;
+ int cc1;
+ int cc2;
+
+ /* Check CT CC for connection */
+ vpd_ct_get_cc(&cc1, &cc2);
+
+ if (cc_is_rp(cc1) != cc_is_rp(cc2))
+ new_cc_state = PD_CC_DFP_ATTACHED;
+ else if (!cc_is_rp(cc1) && !cc_is_rp(cc2))
+ new_cc_state = PD_CC_NONE;
+ else
+ new_cc_state = PD_CC_UNSET;
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * CTDisabled.VPD if VCONN falls below vVCONNDisconnect.
+ */
+ if (!vpd_is_vconn_present()) {
+ set_state(port, TC_OBJ(port), tc_ct_disabled_vpd);
+ return 0;
+ }
+
+ /* Debounce the cc state */
+ if (new_cc_state != tc[port].cc_state) {
+ tc[port].cc_state = new_cc_state;
+ tc[port].cc_debounce = get_time().val +
+ PD_T_CC_DEBOUNCE;
+ tc[port].pd_debounce = get_time().val +
+ PD_T_PD_DEBOUNCE;
+ return 0;
+ }
+
+ if (get_time().val > tc[port].pd_debounce) {
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition
+ * to CTUnattached.VPD when the state of both the Charge-Through
+ * port’s CC1 and CC2 pins are SNK.Open for at least
+ * tPDDebounce.
+ */
+ if (tc[port].cc_state == PD_CC_NONE) {
+ set_state(port, TC_OBJ(port),
+ tc_ct_unattached_vpd);
+ return 0;
+ }
+ }
+
+ if (get_time().val > tc[port].cc_debounce) {
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall transition to
+ * CTAttached.VPD after the state of only one of the
+ * Charge-Through port’s CC1 or CC2 pins is SNK.Rp for at
+ * least tCCDebounce and VBUS on the Charge-Through port is
+ * detected.
+ */
+ if (tc[port].cc_state == PD_CC_DFP_ATTACHED &&
+ vpd_is_ct_vbus_present()) {
+ set_state(port, TC_OBJ(port), tc_ct_attached_vpd);
+ return 0;
+ }
+ }
+
+ return RUN_SUPER;
+}
+
+static unsigned int tc_ct_attach_wait_vpd_exit(int port)
+{
+ /* Disable PD */
+ tc[port].pd_enable = 0;
+
+ /* Reset timeout value to 10ms */
+ tc_set_timeout(port, 10 * MSEC);
+
+ return 0;
+}
+
+/**
+ * Super State HOST_RP3_CT_RD
+ */
+static unsigned int tc_host_rp3_ct_rd(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_host_rp3_ct_rd_sig[sig])(port);
+
+ return SUPER(ret, sig, tc_vbus_cc_iso);
+}
+
+static unsigned int tc_host_rp3_ct_rd_entry(int port)
+{
+ /* Place RP3A0 on Host CC */
+ vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_3A0);
+
+ /* Connect Charge-Through Rd */
+ vpd_ct_set_pull(TYPEC_CC_RD, 0);
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall
+ * ensure that it is powered by VCONN
+ */
+
+ /* Make sure vconn is on */
+ if (!vpd_is_vconn_present())
+ set_state(port, TC_OBJ(port), tc_error_recovery);
+
+ /* Get power from VCONN */
+ vpd_vconn_pwr_sel_odl(PWR_VCONN);
+
+ return 0;
+}
+
+static unsigned int tc_host_rp3_ct_rd_run(int port)
+{
+ return 0;
+}
+
+/**
+ * Super State HOST_RP3_CT_RPU
+ */
+static unsigned int tc_host_rp3_ct_rpu(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_host_rp3_ct_rpu_sig[sig])(port);
+ return SUPER(ret, sig, tc_vbus_cc_iso);
+}
+
+static unsigned int tc_host_rp3_ct_rpu_entry(int port)
+{
+ /* Place RP3A0 on Host CC */
+ vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_3A0);
+
+ /* Place RPUSB on Charge-Through CC */
+ vpd_ct_set_pull(TYPEC_CC_RP, TYPEC_RP_USB);
+
+ /*
+ * A Charge-Through VCONN-Powered USB Device shall
+ * ensure that it is powered by VCONN
+ */
+
+ /* Make sure vconn is on */
+ if (!vpd_is_vconn_present())
+ set_state(port, TC_OBJ(port), tc_error_recovery);
+
+ /* Get power from VCONN */
+ vpd_vconn_pwr_sel_odl(PWR_VCONN);
+
+ return 0;
+}
+
+static unsigned int tc_host_rp3_ct_rpu_run(int port)
+{
+ return 0;
+}
diff --git a/common/usb_tc_sm.c b/common/usb_tc_sm.c
index 4f7039a546..68912b0c63 100644
--- a/common/usb_tc_sm.c
+++ b/common/usb_tc_sm.c
@@ -23,7 +23,6 @@
#include "usb_charge.h"
#include "usb_mux.h"
#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
#include "usb_prl_sm.h"
#include "tcpm.h"
#include "usb_pe_sm.h"
@@ -32,23 +31,25 @@
#include "usb_tc_sm.h"
#include "version.h"
+/* Include USB Type-C State Machine Header File */
+#if defined(CONFIG_USB_TYPEC_CTVPD)
+#include "usb_tc_ctvpd_sm.h"
+#elif defined(CONFIG_USB_TYPEC_VPD)
+#include "usb_tc_vpd_sm.h"
+#else
+#error "A USB Type-C State Machine must be defined."
+#endif
+
#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_HOOK, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_HOOK, format, ## args)
+#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
#else /* CONFIG_COMMON_RUNTIME */
#define CPRINTF(format, args...)
#define CPRINTS(format, args...)
#endif
-/* Private Function Prototypes */
-
-static inline int cc_is_rp(int cc);
-static inline enum pd_cc_polarity_type get_snk_polarity(int cc1, int cc2);
-static int tc_restart_tcpc(int port);
-static void set_polarity(int port, int polarity);
-
#ifdef CONFIG_COMMON_RUNTIME
-static const char * const tc_state_names[] = {
+const char * const tc_state_names[] = {
"Disabled",
"Unattached.SNK",
"AttachWait.SNK",
@@ -85,15 +86,6 @@ static const char * const tc_state_names[] = {
BUILD_ASSERT(ARRAY_SIZE(tc_state_names) == TC_STATE_COUNT);
#endif
-/* Include USB Type-C State Machine */
-#if defined(CONFIG_USB_TYPEC_CTVPD)
-#include "usb_tc_ctvpd_sm.h"
-#elif defined(CONFIG_USB_TYPEC_VPD)
-#include "usb_tc_vpd_sm.h"
-#else
-#error "A USB Type-C State Machine must be defined."
-#endif
-
/* Public Functions */
int tc_get_power_role(int port)
@@ -116,8 +108,6 @@ enum typec_state_id get_typec_state_id(int port)
return tc[port].state_id;
}
-/* Private Functions */
-
/*
* CC values for regular sources and Debug sources (aka DTS)
*
@@ -131,10 +121,7 @@ enum typec_state_id get_typec_state_id(int port)
* DTS USB-C @ 3 A Rp3A0 RpUSB
*/
-/**
- * Returns the polarity of a Sink.
- */
-static inline enum pd_cc_polarity_type get_snk_polarity(int cc1, int cc2)
+inline enum pd_cc_polarity_type get_snk_polarity(int cc1, int cc2)
{
/* the following assumes:
* TYPEC_CC_VOLT_RP_3_0 > TYPEC_CC_VOLT_RP_1_5
@@ -144,12 +131,12 @@ static inline enum pd_cc_polarity_type get_snk_polarity(int cc1, int cc2)
return (cc2 > cc1) ? POLARITY_CC2 : POLARITY_CC1;
}
-static int tc_restart_tcpc(int port)
+int tc_restart_tcpc(int port)
{
return tcpm_init(port);
}
-static void set_polarity(int port, int polarity)
+void set_polarity(int port, int polarity)
{
tcpm_set_polarity(port, polarity);
#ifdef CONFIG_USBC_PPC_POLARITY
diff --git a/common/usb_tc_vpd_sm.c b/common/usb_tc_vpd_sm.c
new file mode 100644
index 0000000000..33762257a0
--- /dev/null
+++ b/common/usb_tc_vpd_sm.c
@@ -0,0 +1,358 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "common.h"
+#include "console.h"
+#include "system.h"
+#include "task.h"
+#include "tcpm.h"
+#include "usb_pd.h"
+#include "usb_tc_sm.h"
+#include "usb_tc_vpd_sm.h"
+#include "vpd_api.h"
+
+/* USB Type-C VCONN Powered Device module */
+
+#ifdef CONFIG_COMMON_RUNTIME
+#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
+#else /* CONFIG_COMMON_RUNTIME */
+#define CPRINTF(format, args...)
+#define CPRINTS(format, args...)
+#endif
+
+/* Type-C Layer Flags */
+#define TC_FLAGS_VCONN_ON BIT(0)
+
+#undef PD_DEFAULT_STATE
+/* Port default state at startup */
+#define PD_DEFAULT_STATE(port) tc_unattached_snk
+
+/**
+ * This is the Type-C Port object that contains information needed to
+ * implement a VCONN Powered Device.
+ */
+struct type_c tc[CONFIG_USB_PD_PORT_COUNT];
+
+/* Type-C states */
+DECLARE_STATE(tc, disabled, WITH_EXIT);
+DECLARE_STATE(tc, unattached_snk, NOOP_EXIT);
+DECLARE_STATE(tc, attach_wait_snk, NOOP_EXIT);
+DECLARE_STATE(tc, attached_snk, WITH_EXIT);
+
+/* Super States */
+DECLARE_STATE(tc, host_rard, NOOP_EXIT);
+DECLARE_STATE(tc, host_open, NOOP_EXIT);
+DECLARE_STATE(tc, vbus_cc_iso, NOOP_EXIT);
+
+void tc_state_init(int port)
+{
+ int res = 0;
+ sm_state this_state;
+
+ res = tc_restart_tcpc(port);
+
+ CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready");
+ this_state = res ? tc_disabled : PD_DEFAULT_STATE(port);
+
+ /* Disable TCPC RX until connection is established */
+ tcpm_set_rx_enable(port, 0);
+
+ init_state(port, TC_OBJ(port), this_state);
+
+ /* Disable pd state machines */
+ tc[port].pd_enable = 0;
+ tc[port].evt_timeout = 10*MSEC;
+ tc[port].power_role = PD_PLUG_CABLE_VPD;
+ tc[port].data_role = 0; /* Reserved for VPD */
+ tc[port].flags = 0;
+}
+
+void tc_event_check(int port, int evt)
+{
+ /* Do Nothing */
+}
+
+/**
+ * Disabled
+ *
+ * Super State Entries:
+ * Enable mcu communication
+ * Remove the terminations from Host CC
+ */
+static unsigned int tc_disabled(int port, enum signal sig)
+{
+ int ret = 0;
+
+ ret = (*tc_disabled_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_open);
+}
+
+static unsigned int tc_disabled_entry(int port)
+{
+ tc[port].state_id = DISABLED;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ return 0;
+}
+
+static unsigned int tc_disabled_run(int port)
+{
+ task_wait_event(-1);
+
+ return RUN_SUPER;
+}
+
+static unsigned int tc_disabled_exit(int port)
+{
+#ifndef CONFIG_USB_PD_TCPC
+ if (tc_restart_tcpc(port) != 0) {
+ CPRINTS("TCPC p%d restart failed!", port);
+ return 0;
+ }
+#endif
+ CPRINTS("TCPC p%d resumed!", port);
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+
+ return 0;
+}
+
+/**
+ * Unattached.SNK
+ *
+ * Super State Entry:
+ * Enable mcu communication
+ * Place Ra on VCONN and Rd on Host CC
+ */
+static unsigned int tc_unattached_snk(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_unattached_snk_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rard);
+}
+
+static unsigned int tc_unattached_snk_entry(int port)
+{
+ tc[port].state_id = UNATTACHED_SNK;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ return 0;
+}
+
+static unsigned int tc_unattached_snk_run(int port)
+{
+ int host_cc;
+
+ /* Check Host CC for connection */
+ vpd_host_get_cc(&host_cc);
+
+ /*
+ * Transition to AttachWait.SNK when a Source connection is
+ * detected, as indicated by the SNK.Rp state on its Host-side
+ * port’s CC pin.
+ */
+ if (cc_is_rp(host_cc)) {
+ set_state(port, TC_OBJ(port), tc_attach_wait_snk);
+ return 0;
+ }
+
+ return RUN_SUPER;
+}
+
+/**
+ * AttachedWait.SNK
+ *
+ * Super State Entry:
+ * Enable mcu communication
+ * Place Ra on VCONN and Rd on Host CC
+ */
+static unsigned int tc_attach_wait_snk(int port, enum signal sig)
+{
+ int ret = 0;
+
+ ret = (*tc_attach_wait_snk_sig[sig])(port);
+ return SUPER(ret, sig, tc_host_rard);
+}
+
+static unsigned int tc_attach_wait_snk_entry(int port)
+{
+ tc[port].state_id = ATTACH_WAIT_SNK;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+ tc[port].host_cc_state = PD_CC_UNSET;
+
+ return 0;
+}
+
+static unsigned int tc_attach_wait_snk_run(int port)
+{
+ int host_new_cc_state;
+ int host_cc;
+
+ /* Check Host CC for connection */
+ vpd_host_get_cc(&host_cc);
+
+ if (cc_is_rp(host_cc))
+ host_new_cc_state = PD_CC_DFP_ATTACHED;
+ else
+ host_new_cc_state = PD_CC_NONE;
+
+ /* Debounce the Host CC state */
+ if (tc[port].host_cc_state != host_new_cc_state) {
+ tc[port].host_cc_state = host_new_cc_state;
+ if (host_new_cc_state == PD_CC_DFP_ATTACHED)
+ tc[port].cc_debounce = get_time().val +
+ PD_T_CC_DEBOUNCE;
+ else
+ tc[port].cc_debounce = get_time().val +
+ PD_T_PD_DEBOUNCE;
+
+ return 0;
+ }
+
+ /* Wait for Host CC debounce */
+ if (get_time().val < tc[port].cc_debounce)
+ return 0;
+
+ /*
+ * A VCONN-Powered USB Device shall transition to
+ * Attached.SNK after the state of the Host-side port’s CC pin is
+ * SNK.Rp for at least tCCDebounce and either host-side VCONN or
+ * VBUS is detected.
+ *
+ * Transition to Unattached.SNK when the state of both the CC1 and
+ * CC2 pins is SNK.Open for at least tPDDebounce.
+ */
+ if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
+ (vpd_is_vconn_present() || vpd_is_host_vbus_present()))
+ set_state(port, TC_OBJ(port), tc_attached_snk);
+ else if (tc[port].host_cc_state == PD_CC_NONE)
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+
+ return 0;
+}
+
+/**
+ * Attached.SNK
+ */
+static unsigned int tc_attached_snk(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_attached_snk_sig[sig])(port);
+ return SUPER(ret, sig, 0);
+}
+
+static unsigned int tc_attached_snk_entry(int port)
+{
+ tc[port].state_id = ATTACHED_SNK;
+ CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
+
+ /* Enable PD */
+ tc[port].pd_enable = 1;
+ set_polarity(port, 0);
+
+ return 0;
+}
+
+static unsigned int tc_attached_snk_run(int port)
+{
+ /* Has host vbus and vconn been removed */
+ if (!vpd_is_host_vbus_present() && !vpd_is_vconn_present()) {
+ set_state(port, TC_OBJ(port), tc_unattached_snk);
+ return 0;
+ }
+
+ if (vpd_is_vconn_present()) {
+ if (!(tc[port].flags & TC_FLAGS_VCONN_ON)) {
+ /* VCONN detected. Remove RA */
+ vpd_host_set_pull(TYPEC_CC_RD, 0);
+ tc[port].flags |= TC_FLAGS_VCONN_ON;
+ }
+ }
+
+ return 0;
+}
+
+static unsigned int tc_attached_snk_exit(int port)
+{
+ /* Disable PD */
+ tc[port].pd_enable = 0;
+ tc[port].flags &= ~TC_FLAGS_VCONN_ON;
+
+ return 0;
+}
+
+/**
+ * Super State HOST_RARD
+ */
+static unsigned int tc_host_rard(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_host_rard_sig[sig])(port);
+ return SUPER(ret, sig, tc_vbus_cc_iso);
+}
+
+static unsigned int tc_host_rard_entry(int port)
+{
+ /* Place Ra on VCONN and Rd on Host CC */
+ vpd_host_set_pull(TYPEC_CC_RA_RD, 0);
+
+ return 0;
+}
+
+static unsigned int tc_host_rard_run(int port)
+{
+ return RUN_SUPER;
+}
+
+/**
+ * Super State HOST_OPEN
+ */
+static unsigned int tc_host_open(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_host_open_sig[sig])(port);
+ return SUPER(ret, sig, tc_vbus_cc_iso);
+}
+
+static unsigned int tc_host_open_entry(int port)
+{
+ /* Remove the terminations from Host CC */
+ vpd_host_set_pull(TYPEC_CC_OPEN, 0);
+
+ return 0;
+}
+
+static unsigned int tc_host_open_run(int port)
+{
+ return RUN_SUPER;
+}
+
+/**
+ * Super State VBUS_CC_ISO
+ */
+static unsigned int tc_vbus_cc_iso(int port, enum signal sig)
+{
+ int ret;
+
+ ret = (*tc_vbus_cc_iso_sig[sig])(port);
+ return SUPER(ret, sig, 0);
+}
+
+static unsigned int tc_vbus_cc_iso_entry(int port)
+{
+ /* Enable mcu communication and cc */
+ vpd_mcu_cc_en(1);
+
+ return 0;
+}
+
+static unsigned int tc_vbus_cc_iso_run(int port)
+{
+ return 0;
+}
diff --git a/include/usb_pe_sm.h b/include/usb_pe_sm.h
index a8fd59b08c..ae925c270e 100644
--- a/include/usb_pe_sm.h
+++ b/include/usb_pe_sm.h
@@ -8,6 +8,8 @@
#ifndef __CROS_EC_USB_PE_H
#define __CROS_EC_USB_PE_H
+#include "usb_sm.h"
+
enum pe_error {
ERR_RCH_CHUNKED,
ERR_RCH_MSG_REC,
@@ -15,6 +17,12 @@ enum pe_error {
ERR_TCH_XMIT,
};
+/*
+ * PE_OBJ is a convenience macro to access struct sm_obj, which
+ * must be the first member of struct policy_engine.
+ */
+#define PE_OBJ(port) (SM_OBJ(pe[port]))
+
/**
* Initialize the Policy Engine State Machine
*
diff --git a/include/usb_sm.h b/include/usb_sm.h
index 15de5f9ef4..1fd6688a1f 100644
--- a/include/usb_sm.h
+++ b/include/usb_sm.h
@@ -8,6 +8,62 @@
#ifndef __CROS_EC_USB_SM_H
#define __CROS_EC_USB_SM_H
+#define DECLARE_SM_FUNC_(prefix, name, exit) \
+ DECLARE_SM_FUNC_##exit(prefix, name)
+#define DECLARE_SM_FUNC_WITH_EXIT(prefix, name) static unsigned int \
+ prefix##_##name##_exit(int port)
+#define DECLARE_SM_FUNC_NOOP_EXIT(prefix, name)
+
+#define DECLARE_SM_SIG_(prefix, name, exit) DECLARE_SM_##exit(prefix, name)
+#define DECLARE_SM_WITH_EXIT(prefix, name) prefix##_##name##_exit
+#define DECLARE_SM_NOOP_EXIT(prefix, name) do_nothing_exit
+
+
+/*
+ * Helper macro for the declaration of states.
+ *
+ * @param prefix - prefix of state function name
+ * @param name - name of state
+ * @param exit - if WITH_EXIT, generates an exit state function name
+ * if NOOP_EXIT, generates do_nothing_exit function name
+ *
+ * EXAMPLE:
+ *
+ * DECLARE_STATE(tc, test, WITH_EXIT); generates the following:
+ *
+ * static unsigned int tc_test(int port, enum signal sig);
+ * static unsigned int tc_test_entry(int port);
+ * static unsigned int tc_test_run(int port);
+ * static unsigned int tc_test_exit(int port);
+ * static const state_sig tc_test_sig[] = {
+ * tc_test_entry,
+ * tc_test_run,
+ * tc_test_exit,
+ * get_super_state };
+ *
+ * DECLARE_STATE(tc, test, NOOP_EXIT); generates the following:
+ *
+ * static unsigned int tc_test(int port, enum signal sig);
+ * static unsigned int tc_test_entry(int port);
+ * static unsigned int tc_test_run(int port);
+ * static const state_sig tc_test_sig[] = {
+ * tc_test_entry,
+ * tc_test_run,
+ * do_nothing_exit,
+ * get_super_state };
+ */
+#define DECLARE_STATE(prefix, name, exit) \
+static unsigned int prefix##_##name(int port, enum signal sig); \
+static unsigned int prefix##_##name##_entry(int port); \
+static unsigned int prefix##_##name##_run(int port); \
+DECLARE_SM_FUNC_(prefix, name, exit); \
+static const state_sig prefix##_##name##_sig[] = { \
+prefix##_##name##_entry, \
+prefix##_##name##_run, \
+DECLARE_SM_SIG_(prefix, name, exit), \
+get_super_state \
+}
+
#define SM_OBJ(smo) ((struct sm_obj *)&smo)
#define SUPER(r, sig, s) ((((r) == 0) || ((sig) == ENTRY_SIG) || \
((sig) == EXIT_SIG)) ? 0 : ((uintptr_t)(s)))
@@ -64,4 +120,20 @@ int set_state(int port, struct sm_obj *obj, sm_state target);
*/
void exe_state(int port, struct sm_obj *obj, enum signal sig);
+/**
+ * Substitute this function for states that do not implement an exit state.
+ *
+ * @param port USB-C port number
+ * @return 0
+ */
+unsigned int do_nothing_exit(int port);
+
+/**
+ * Called by the state machine framework to execute a states super state.
+ *
+ * @param port USB-C port number
+ * @return RUN_SUPER
+ */
+unsigned int get_super_state(int port);
+
#endif /* __CROS_EC_USB_SM_H */
diff --git a/include/usb_tc_ctvpd_sm.h b/include/usb_tc_ctvpd_sm.h
index 8e0e1eaf2f..72ce16f317 100644
--- a/include/usb_tc_ctvpd_sm.h
+++ b/include/usb_tc_ctvpd_sm.h
@@ -3,29 +3,17 @@
* found in the LICENSE file.
*/
-#include "vpd_api.h"
+#ifndef __CROS_EC_USB_TC_CTVPD_SM_H
+#define __CROS_EC_USB_TC_CTVPD_SM_H
-/* USB Type-C CTVPD module */
+#include "usb_sm.h"
+#include "usb_tc_sm.h"
-#ifndef __CROS_EC_USB_TC_VPD_H
-#define __CROS_EC_USB_TC_VPD_H
-
-/* Type-C Layer Flags */
-#define TC_FLAGS_VCONN_ON (1 << 0)
-
-
-#undef PD_DEFAULT_STATE
-/* Port default state at startup */
-#define PD_DEFAULT_STATE(port) tc_state_unattached_snk
-
-#define TC_OBJ(port) (SM_OBJ(tc[port]))
-#define TC_TEST_OBJ(port) (SM_OBJ(tc[(port)].obj))
-
-#define SUPPORT_TIMER_RESET_INIT 0
-#define SUPPORT_TIMER_RESET_REQUEST 1
-#define SUPPORT_TIMER_RESET_COMPLETE 2
-
-static struct type_c {
+/**
+ * This is the Type-C Port object that contains information needed to
+ * implement a Charge Through VCONN Powered Device.
+ */
+struct type_c {
/* struct sm_obj must be first */
struct sm_obj obj;
/* state id */
@@ -71,1967 +59,8 @@ static struct type_c {
/* The cc state */
enum pd_cc_states cc_state;
uint64_t next_role_swap;
-} tc[CONFIG_USB_PD_PORT_COUNT];
-
-/* Type-C states */
-static unsigned int tc_state_disabled(int port, enum signal sig);
-static unsigned int tc_state_disabled_entry(int port);
-static unsigned int tc_state_disabled_run(int port);
-static unsigned int tc_state_disabled_exit(int port);
-
-static unsigned int tc_state_error_recovery(int port, enum signal sig);
-static unsigned int tc_state_error_recovery_entry(int port);
-static unsigned int tc_state_error_recovery_run(int port);
-
-static unsigned int tc_state_unattached_snk(int port, enum signal sig);
-static unsigned int tc_state_unattached_snk_entry(int port);
-static unsigned int tc_state_unattached_snk_run(int port);
-
-static unsigned int tc_state_attach_wait_snk(int port, enum signal sig);
-static unsigned int tc_state_attach_wait_snk_entry(int port);
-static unsigned int tc_state_attach_wait_snk_run(int port);
-
-static unsigned int tc_state_attached_snk(int port, enum signal sig);
-static unsigned int tc_state_attached_snk_entry(int port);
-static unsigned int tc_state_attached_snk_run(int port);
-static unsigned int tc_state_attached_snk_exit(int port);
-
-static unsigned int tc_state_try_snk(int port, enum signal sig);
-static unsigned int tc_state_try_snk_entry(int port);
-static unsigned int tc_state_try_snk_run(int port);
-
-static unsigned int tc_state_unattached_src(int port, enum signal sig);
-static unsigned int tc_state_unattached_src_entry(int port);
-static unsigned int tc_state_unattached_src_run(int port);
-
-static unsigned int tc_state_attach_wait_src(int port, enum signal sig);
-static unsigned int tc_state_attach_wait_src_entry(int port);
-static unsigned int tc_state_attach_wait_src_run(int port);
-
-static unsigned int tc_state_try_wait_src(int port, enum signal sig);
-static unsigned int tc_state_try_wait_src_entry(int port);
-static unsigned int tc_state_try_wait_src_run(int port);
-
-static unsigned int tc_state_attached_src(int port, enum signal sig);
-static unsigned int tc_state_attached_src_entry(int port);
-static unsigned int tc_state_attached_src_run(int port);
-
-static unsigned int tc_state_ct_try_snk(int port, enum signal sig);
-static unsigned int tc_state_ct_try_snk_entry(int port);
-static unsigned int tc_state_ct_try_snk_run(int port);
-static unsigned int tc_state_ct_try_snk_exit(int port);
-
-static unsigned int
- tc_state_ct_attach_wait_unsupported(int port, enum signal sig);
-static unsigned int tc_state_ct_attach_wait_unsupported_entry(int port);
-static unsigned int tc_state_ct_attach_wait_unsupported_run(int port);
-static unsigned int tc_state_ct_attach_wait_unsupported_exit(int port);
-
-static unsigned int tc_state_ct_attached_unsupported(int port, enum signal sig);
-static unsigned int tc_state_ct_attached_unsupported_entry(int port);
-static unsigned int tc_state_ct_attached_unsupported_run(int port);
-static unsigned int tc_state_ct_attached_unsupported_exit(int port);
-
-static unsigned int
- tc_state_ct_unattached_unsupported(int port, enum signal sig);
-static unsigned int tc_state_ct_unattached_unsupported_entry(int port);
-static unsigned int tc_state_ct_unattached_unsupported_run(int port);
-static unsigned int tc_state_ct_unattached_unsupported_exit(int port);
-
-static unsigned int tc_state_ct_unattached_vpd(int port, enum signal sig);
-static unsigned int tc_state_ct_unattached_vpd_entry(int port);
-static unsigned int tc_state_ct_unattached_vpd_run(int port);
-static unsigned int tc_state_ct_unattached_vpd_exit(int port);
-
-static unsigned int tc_state_ct_disabled_vpd(int port, enum signal sig);
-static unsigned int tc_state_ct_disabled_vpd_entry(int port);
-static unsigned int tc_state_ct_disabled_vpd_run(int port);
-
-static unsigned int tc_state_ct_attached_vpd(int port, enum signal sig);
-static unsigned int tc_state_ct_attached_vpd_entry(int port);
-static unsigned int tc_state_ct_attached_vpd_run(int port);
-
-static unsigned int tc_state_ct_attach_wait_vpd(int port, enum signal sig);
-static unsigned int tc_state_ct_attach_wait_vpd_entry(int port);
-static unsigned int tc_state_ct_attach_wait_vpd_run(int port);
-static unsigned int tc_state_ct_attach_wait_vpd_exit(int port);
-
-
-/* Super States */
-static unsigned int tc_state_host_rard_ct_rd(int port, enum signal sig);
-static unsigned int tc_state_host_rard_ct_rd_entry(int port);
-static unsigned int tc_state_host_rard_ct_rd_run(int port);
-
-static unsigned int tc_state_host_open_ct_open(int port, enum signal sig);
-static unsigned int tc_state_host_open_ct_open_entry(int port);
-static unsigned int tc_state_host_open_ct_open_run(int port);
-
-static unsigned int tc_state_vbus_cc_iso(int port, enum signal sig);
-static unsigned int tc_state_vbus_cc_iso_entry(int port);
-static unsigned int tc_state_vbus_cc_iso_run(int port);
-
-static unsigned int tc_state_host_rp3_ct_rd(int port, enum signal sig);
-static unsigned int tc_state_host_rp3_ct_rd_entry(int port);
-static unsigned int tc_state_host_rp3_ct_rd_run(int port);
-
-static unsigned int tc_state_host_rp3_ct_rpu(int port, enum signal sig);
-static unsigned int tc_state_host_rp3_ct_rpu_entry(int port);
-static unsigned int tc_state_host_rp3_ct_rpu_run(int port);
-
-static unsigned int tc_state_host_rpu_ct_rd(int port, enum signal sig);
-static unsigned int tc_state_host_rpu_ct_rd_entry(int port);
-static unsigned int tc_state_host_rpu_ct_rd_run(int port);
-
-static unsigned int do_nothing_exit(int port);
-static unsigned int get_super_state(int port);
-
-
-static const state_sig tc_state_disabled_sig[] = {
- tc_state_disabled_entry,
- tc_state_disabled_run,
- tc_state_disabled_exit,
- get_super_state
-};
-
-static const state_sig tc_state_error_recovery_sig[] = {
- tc_state_error_recovery_entry,
- tc_state_error_recovery_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_unattached_snk_sig[] = {
- tc_state_unattached_snk_entry,
- tc_state_unattached_snk_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_attach_wait_snk_sig[] = {
- tc_state_attach_wait_snk_entry,
- tc_state_attach_wait_snk_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_attached_snk_sig[] = {
- tc_state_attached_snk_entry,
- tc_state_attached_snk_run,
- tc_state_attached_snk_exit,
- get_super_state
-};
-
-static const state_sig tc_state_try_snk_sig[] = {
- tc_state_try_snk_entry,
- tc_state_try_snk_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_unattached_src_sig[] = {
- tc_state_unattached_src_entry,
- tc_state_unattached_src_run,
- do_nothing_exit,
- get_super_state
};
-static const state_sig tc_state_attach_wait_src_sig[] = {
- tc_state_attach_wait_src_entry,
- tc_state_attach_wait_src_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_try_wait_src_sig[] = {
- tc_state_try_wait_src_entry,
- tc_state_try_wait_src_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_attached_src_sig[] = {
- tc_state_attached_src_entry,
- tc_state_attached_src_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_ct_try_snk_sig[] = {
- tc_state_ct_try_snk_entry,
- tc_state_ct_try_snk_run,
- tc_state_ct_try_snk_exit,
- get_super_state
-};
-
-static const state_sig tc_state_ct_attach_wait_unsupported_sig[] = {
- tc_state_ct_attach_wait_unsupported_entry,
- tc_state_ct_attach_wait_unsupported_run,
- tc_state_ct_attach_wait_unsupported_exit,
- get_super_state
-};
-
-static const state_sig tc_state_ct_attached_unsupported_sig[] = {
- tc_state_ct_attached_unsupported_entry,
- tc_state_ct_attached_unsupported_run,
- tc_state_ct_attached_unsupported_exit,
- get_super_state
-};
-
-static const state_sig tc_state_ct_unattached_unsupported_sig[] = {
- tc_state_ct_unattached_unsupported_entry,
- tc_state_ct_unattached_unsupported_run,
- tc_state_ct_unattached_unsupported_exit,
- get_super_state
-};
-
-static const state_sig tc_state_ct_unattached_vpd_sig[] = {
- tc_state_ct_unattached_vpd_entry,
- tc_state_ct_unattached_vpd_run,
- tc_state_ct_unattached_vpd_exit,
- get_super_state
-};
-
-static const state_sig tc_state_ct_disabled_vpd_sig[] = {
- tc_state_ct_disabled_vpd_entry,
- tc_state_ct_disabled_vpd_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_ct_attached_vpd_sig[] = {
- tc_state_ct_attached_vpd_entry,
- tc_state_ct_attached_vpd_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_ct_attach_wait_vpd_sig[] = {
- tc_state_ct_attach_wait_vpd_entry,
- tc_state_ct_attach_wait_vpd_run,
- tc_state_ct_attach_wait_vpd_exit,
- get_super_state
-};
-
-static const state_sig tc_state_host_rard_ct_rd_sig[] = {
- tc_state_host_rard_ct_rd_entry,
- tc_state_host_rard_ct_rd_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_host_open_ct_open_sig[] = {
- tc_state_host_open_ct_open_entry,
- tc_state_host_open_ct_open_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_vbus_cc_iso_sig[] = {
- tc_state_vbus_cc_iso_entry,
- tc_state_vbus_cc_iso_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_host_rp3_ct_rd_sig[] = {
- tc_state_host_rp3_ct_rd_entry,
- tc_state_host_rp3_ct_rd_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_host_rp3_ct_rpu_sig[] = {
- tc_state_host_rp3_ct_rpu_entry,
- tc_state_host_rp3_ct_rpu_run,
- do_nothing_exit,
- get_super_state
-};
-
-static const state_sig tc_state_host_rpu_ct_rd_sig[] = {
- tc_state_host_rpu_ct_rd_entry,
- tc_state_host_rpu_ct_rd_run,
- do_nothing_exit,
- get_super_state
-};
-
-void tc_reset_support_timer(int port)
-{
- tc[port].support_timer_reset |= SUPPORT_TIMER_RESET_REQUEST;
-}
-
-static void tc_state_init(int port)
-{
- int res = 0;
- sm_state this_state;
-
- res = tc_restart_tcpc(port);
-
- CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready");
- this_state = res ? tc_state_disabled : PD_DEFAULT_STATE(port);
-
- init_state(port, TC_OBJ(port), this_state);
-
- /* Disable pd state machines */
- tc[port].pd_enable = 0;
- tc[port].evt_timeout = 10*MSEC;
- tc[port].power_role = PD_PLUG_CABLE_VPD;
- tc[port].data_role = 0; /* Reserved for VPD */
- tc[port].billboard_presented = 0;
- tc[port].flags = 0;
-}
-
-static void tc_event_check(int port, int evt)
-{
- /* Do Nothing */
-}
-
-/**
- * Disabled
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Remove the terminations from Host
- * Remove the terminations from Charge-Through
- */
-static unsigned int tc_state_disabled(int port, enum signal sig)
-{
- int ret = 0;
-
- ret = (*tc_state_disabled_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_open_ct_open);
-}
-
-static unsigned int tc_state_disabled_entry(int port)
-{
- tc[port].state_id = DISABLED;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
- return 0;
-}
-
-static unsigned int tc_state_disabled_run(int port)
-{
- task_wait_event(-1);
- return RUN_SUPER;
-}
-
-static unsigned int tc_state_disabled_exit(int port)
-{
-#ifndef CONFIG_USB_PD_TCPC
- if (tc_restart_tcpc(port) != 0) {
- CPRINTS("TCPC p%d restart failed!", port);
- return 0;
- }
-#endif
- CPRINTS("TCPC p%d resumed!", port);
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
-
- return 0;
-}
-
-/**
- * ErrorRecovery
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Remove the terminations from Host
- * Remove the terminations from Charge-Through
- */
-static unsigned int tc_state_error_recovery(int port, enum signal sig)
-{
- int ret = 0;
-
- ret = (*tc_state_error_recovery_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_open_ct_open);
-}
-
-static unsigned int tc_state_error_recovery_entry(int port)
-{
- tc[port].state_id = ERROR_RECOVERY;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
- /* Use cc_debounce state variable for error recovery timeout */
- tc[port].cc_debounce = get_time().val + PD_T_ERROR_RECOVERY;
- return 0;
-}
-
-static unsigned int tc_state_error_recovery_run(int port)
-{
- if (get_time().val > tc[port].cc_debounce) {
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
- return 0;
- }
-
- return RUN_SUPER;
-}
-
-/**
- * Unattached.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- * Place Rd on Charge-Through CCs
- */
-static unsigned int tc_state_unattached_snk(int port, enum signal sig)
-{
- int ret = 0;
-
- ret = (*tc_state_unattached_snk_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rard_ct_rd);
-}
-
-static unsigned int tc_state_unattached_snk_entry(int port)
-{
- tc[port].state_id = UNATTACHED_SNK;
- if (tc[port].obj.last_state != tc_state_unattached_src)
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- tc[port].flags &= ~TC_FLAGS_VCONN_ON;
- tc[port].cc_state = PD_CC_UNSET;
-
- return 0;
-}
-
-static unsigned int tc_state_unattached_snk_run(int port)
-{
- int host_cc;
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * Transition to AttachWait.SNK when a Source connection is
- * detected, as indicated by the SNK.Rp state on its Host-side
- * port’s CC pin.
- */
- if (cc_is_rp(host_cc)) {
- set_state(port, TC_OBJ(port), tc_state_attach_wait_snk);
- return 0;
- }
-
- /* Check Charge-Through CCs for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) != cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else
- new_cc_state = PD_CC_NONE;
-
- /* Debounce Charge-Through CC state */
- if (tc[port].cc_state != new_cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- }
-
- /* If we are here, Host CC must be open */
-
- /* Wait for Charge-Through CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return 0;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SRC when the state of the Host-side port’s CC pin is
- * SNK.Open for tDRP − dcSRC.DRP ∙ tDRP and both of the following
- * is detected on the Charge-Through port.
- * 1) SNK.Rp state is detected on exactly one of the CC1 or CC2
- * pins for at least tCCDebounce
- * 2) VBUS is detected
- */
- if (vpd_is_ct_vbus_present() &&
- tc[port].cc_state == PD_CC_DFP_ATTACHED) {
- set_state(port, TC_OBJ(port), tc_state_unattached_src);
- return 0;
- }
-
- return RUN_SUPER;
-}
-
-/**
- * AttachWait.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- * Place Rd on Charge-Through CCs
- */
-static unsigned int tc_state_attach_wait_snk(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_attach_wait_snk_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rard_ct_rd);
-}
-
-static unsigned int tc_state_attach_wait_snk_entry(int port)
-{
- tc[port].state_id = ATTACH_WAIT_SNK;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
- tc[port].host_cc_state = PD_CC_UNSET;
-
- return 0;
-}
-
-static unsigned int tc_state_attach_wait_snk_run(int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- if (host_new_cc_state == PD_CC_DFP_ATTACHED)
- tc[port].host_cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- else
- tc[port].host_cc_debounce = get_time().val +
- PD_T_PD_DEBOUNCE;
- return 0;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].host_cc_debounce)
- return 0;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Attached.SNK after the state of the Host-side port’s CC pin is
- * SNK.Rp for at least tCCDebounce and either host-side VCONN or
- * VBUS is detected.
- *
- * Transition to Unattached.SNK when the state of both the CC1 and
- * CC2 pins is SNK.Open for at least tPDDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
- (vpd_is_vconn_present() || vpd_is_host_vbus_present()))
- set_state(port, TC_OBJ(port), tc_state_attached_snk);
- else if (tc[port].host_cc_state == PD_CC_NONE)
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
-
- return 0;
-}
-
-/**
- * Attached.SNK
- */
-static unsigned int tc_state_attached_snk(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_attached_snk_sig[sig])(port);
- return SUPER(ret, sig, 0);
-}
-
-static unsigned int tc_state_attached_snk_entry(int port)
-{
- tc[port].state_id = ATTACHED_SNK;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- /*
- * This state can only be entered from states AttachWait.SNK
- * and Try.SNK. So the Host port is isolated from the
- * Charge-Through port. We only need to High-Z the
- * Charge-Through ports CC1 and CC2 pins.
- */
- vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
-
- tc[port].host_cc_state = PD_CC_UNSET;
-
- /* Start Charge-Through support timer */
- tc[port].support_timer_reset = SUPPORT_TIMER_RESET_INIT;
- tc[port].support_timer = get_time().val + PD_T_AME;
-
- /* Sample host CC every 2ms */
- tc_set_timeout(port, 2*MSEC);
-
- return 0;
-}
-
-static unsigned int tc_state_attached_snk_run(int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Has host vbus and vconn been removed */
- if (!vpd_is_host_vbus_present() && !vpd_is_vconn_present()) {
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
- return 0;
- }
-
- /*
- * Reset the Charge-Through Support Timer when it first
- * receives any USB PD Structured VDM Command it supports,
- * which is the Discover Identity command. And this is only
- * done one time.
- */
- if (tc[port].support_timer_reset == SUPPORT_TIMER_RESET_REQUEST) {
- tc[port].support_timer_reset |= SUPPORT_TIMER_RESET_COMPLETE;
- tc[port].support_timer = get_time().val + PD_T_AME;
- }
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].host_cc_debounce = get_time().val + PD_T_VPDCTDD;
- return 0;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].host_cc_debounce)
- return 0;
-
- if (vpd_is_vconn_present()) {
- if (!(tc[port].flags & TC_FLAGS_VCONN_ON)) {
- /* VCONN detected. Remove RA */
- vpd_host_set_pull(TYPEC_CC_RD, 0);
- tc[port].flags |= TC_FLAGS_VCONN_ON;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to CTUnattached.VPD if VCONN is present and the state of
- * its Host-side port’s CC pin is SNK.Open for tVPDCTDD.
- */
- if (tc[port].host_cc_state == PD_CC_NONE) {
- set_state(port, TC_OBJ(port),
- tc_state_ct_unattached_vpd);
- return 0;
- }
- }
-
- /* Check the Support Timer */
- if (get_time().val > tc[port].support_timer &&
- !tc[port].billboard_presented) {
- /*
- * Present USB Billboard Device Class interface
- * indicating that Charge-Through is not supported
- */
- tc[port].billboard_presented = 1;
- vpd_present_billboard(BB_SNK);
- }
-
- return 0;
-}
-
-static unsigned int tc_state_attached_snk_exit(int port)
-{
- /* Reset timeout value to 10ms */
- tc_set_timeout(port, 10*MSEC);
- tc[port].billboard_presented = 0;
- vpd_present_billboard(BB_NONE);
-
- return 0;
-}
-
-/**
- * Super State HOST_RA_CT_RD
- */
-static unsigned int tc_state_host_rard_ct_rd(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_host_rard_ct_rd_sig[sig])(port);
- return SUPER(ret, sig, tc_state_vbus_cc_iso);
-}
-
-static unsigned int tc_state_host_rard_ct_rd_entry(int port)
-{
- /* Place Ra on VCONN and Rd on Host CC */
- vpd_host_set_pull(TYPEC_CC_RA_RD, 0);
-
- /* Place Rd on Charge-Through CCs */
- vpd_ct_set_pull(TYPEC_CC_RD, 0);
-
- return 0;
-}
-
-static unsigned int tc_state_host_rard_ct_rd_run(int port)
-{
- return RUN_SUPER;
-}
-
-/**
- * Super State HOST_OPEN_CT_OPEN
- */
-static unsigned int tc_state_host_open_ct_open(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_host_open_ct_open_sig[sig])(port);
- return SUPER(ret, sig, tc_state_vbus_cc_iso);
-}
-
-static unsigned int tc_state_host_open_ct_open_entry(int port)
-{
- /* Remove the terminations from Host */
- vpd_host_set_pull(TYPEC_CC_OPEN, 0);
-
- /* Remove the terminations from Charge-Through */
- vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
-
- return 0;
-}
-
-static unsigned int tc_state_host_open_ct_open_run(int port)
-{
- return RUN_SUPER;
-}
-
-/**
- * Super State VBUS_CC_ISO
- */
-static unsigned int tc_state_vbus_cc_iso(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_vbus_cc_iso_sig[sig])(port);
- return SUPER(ret, sig, 0);
-}
-
-static unsigned int tc_state_vbus_cc_iso_entry(int port)
-{
- /* Isolate the Host-side port from the Charge-Through port */
- vpd_vbus_pass_en(0);
-
- /* Remove Charge-Through side port CCs */
- vpd_ct_cc_sel(CT_OPEN);
-
- /* Enable mcu communication and cc */
- vpd_mcu_cc_en(1);
-
- return 0;
-}
-
-static unsigned int tc_state_vbus_cc_iso_run(int port)
-{
- return 0;
-}
-
-/**
- * Unattached.SRC
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RpUSB on Host CC
- * Place Rd on Charge-Through CCs
- */
-static unsigned int tc_state_unattached_src(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_unattached_src_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rpu_ct_rd);
-}
-
-static unsigned int tc_state_unattached_src_entry(int port)
-{
- tc[port].state_id = UNATTACHED_SRC;
- if (tc[port].obj.last_state != tc_state_unattached_snk)
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Get power from VBUS */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-
- /* Make sure it's the Charge-Through Port's VBUS */
- if (!vpd_is_ct_vbus_present()) {
- set_state(port, TC_OBJ(port), tc_state_error_recovery);
- return 0;
- }
-
- tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC;
-
- return 0;
-}
-
-static unsigned int tc_state_unattached_src_run(int port)
-{
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * Transition to AttachWait.SRC when host-side VBUS is
- * vSafe0V and SRC.Rd state is detected on the Host-side
- * port’s CC pin.
- */
- if (!vpd_is_host_vbus_present() && host_cc == TYPEC_CC_VOLT_RD) {
- set_state(port, TC_OBJ(port), tc_state_attach_wait_src);
- return 0;
- }
-
- /*
- * Transition to Unattached.SNK within tDRPTransition or
- * if Charge-Through VBUS is removed.
- */
- if (!vpd_is_ct_vbus_present() ||
- get_time().val > tc[port].next_role_swap) {
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
- return 0;
- }
-
- return RUN_SUPER;
-}
-
-/**
- * AttachWait.SRC
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RpUSB on Host CC
- * Place Rd on Charge-Through CCs
- */
-static unsigned int tc_state_attach_wait_src(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_attach_wait_src_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rpu_ct_rd);
-}
-
-static unsigned int tc_state_attach_wait_src_entry(int port)
-{
- tc[port].state_id = ATTACH_WAIT_SRC;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- tc[port].host_cc_state = PD_CC_UNSET;
-
- return 0;
-}
-
-static unsigned int tc_state_attach_wait_src_run(int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (host_cc == TYPEC_CC_VOLT_RD)
- host_new_cc_state = PD_CC_UFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK when the SRC.Open state is detected on the
- * Host-side port’s CC or if Charge-Through VBUS falls below
- * vSinkDisconnect. The Charge-Through VCONN-Powered USB Device
- * shall detect the SRC.Open state within tSRCDisconnect, but
- * should detect it as quickly as possible.
- */
- if (host_new_cc_state == PD_CC_NONE || !vpd_is_ct_vbus_present()) {
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
- return 0;
- }
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- return 0;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return 0;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Try.SNK when the host-side VBUS is at vSafe0V and the SRC.Rd
- * state is on the Host-side port’s CC pin for at least tCCDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_UFP_ATTACHED &&
- !vpd_is_host_vbus_present()) {
- set_state(port, TC_OBJ(port), tc_state_try_snk);
- return 0;
- }
-
- return RUN_SUPER;
-}
-
-/**
- * Attached.SRC
- */
-static unsigned int tc_state_attached_src(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_attached_src_sig[sig])(port);
- return SUPER(ret, sig, 0);
-}
-
-static unsigned int tc_state_attached_src_entry(int port)
-{
- tc[port].state_id = ATTACHED_SRC;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- /* Connect Charge-Through VBUS to Host VBUS */
- vpd_vbus_pass_en(1);
-
- /*
- * Get power from VBUS. No need to test because
- * the Host VBUS is connected to the Charge-Through
- * VBUS
- */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-
- return 0;
-}
-
-static unsigned int tc_state_attached_src_run(int port)
-{
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK when VBUS falls below vSinkDisconnect or the
- * Host-side port’s CC pin is SRC.Open. The Charge-Through
- * VCONNPowered USB Device shall detect the SRC.Open state within
- * tSRCDisconnect, but should detect it as quickly as possible.
- */
- if (!vpd_is_ct_vbus_present() || host_cc == TYPEC_CC_VOLT_OPEN)
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
-
- return 0;
-}
-
-/**
- * Super State HOST_RPU_CT_RD
- */
-static unsigned int tc_state_host_rpu_ct_rd(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_host_rpu_ct_rd_sig[sig])(port);
- return SUPER(ret, sig, tc_state_vbus_cc_iso);
-}
-
-static unsigned int tc_state_host_rpu_ct_rd_entry(int port)
-{
- /* Place RpUSB on Host CC */
- vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_USB);
-
- /* Place Rd on Charge-Through CCs */
- vpd_ct_set_pull(TYPEC_CC_RD, 0);
-
- return 0;
-}
-
-static unsigned int tc_state_host_rpu_ct_rd_run(int port)
-{
- return RUN_SUPER;
-}
-
-/**
- * Try.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- * Place Rd on Charge-Through CCs
- */
-static unsigned int tc_state_try_snk(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_try_snk_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rard_ct_rd);
-}
-
-static unsigned int tc_state_try_snk_entry(int port)
-{
- tc[port].state_id = TRY_SNK;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Get power from VBUS */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-
- /* Make sure it's the Charge-Through Port's VBUS */
- if (!vpd_is_ct_vbus_present()) {
- set_state(port, TC_OBJ(port), tc_state_error_recovery);
- return 0;
- }
-
- tc[port].host_cc_state = PD_CC_UNSET;
-
- /* Using next_role_swap timer as try_src timer */
- tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
-
- return 0;
-}
-
-static unsigned int tc_state_try_snk_run(int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /*
- * Wait for tDRPTry before monitoring the Charge-Through
- * port’s CC pins for the SNK.Rp
- */
- if (get_time().val < tc[port].next_role_swap)
- return 0;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_DEBOUNCE;
- return 0;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return 0;
-
- /*
- * The Charge-Through VCONN-Powered USB Device shall then transition to
- * Attached.SNK when the SNK.Rp state is detected on the Host-side
- * port’s CC pin for at least tTryCCDebounce and VBUS or VCONN is
- * detected on Host-side port.
- *
- * Alternatively, the Charge-Through VCONN-Powered USB Device shall
- * transition to TryWait.SRC if Host-side SNK.Rp state is not detected
- * for tTryCCDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
- (vpd_is_host_vbus_present() || vpd_is_vconn_present()))
- set_state(port, TC_OBJ(port), tc_state_attached_snk);
- else if (tc[port].host_cc_state == PD_CC_NONE)
- set_state(port, TC_OBJ(port), tc_state_try_wait_src);
-
- return 0;
-}
-
-/**
- * TryWait.SRC
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RpUSB on Host CC
- * Place Rd on Charge-Through CCs
- */
-static unsigned int tc_state_try_wait_src(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_try_wait_src_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rpu_ct_rd);
-}
-
-static unsigned int tc_state_try_wait_src_entry(int port)
-{
- tc[port].state_id = TRY_WAIT_SRC;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- tc[port].host_cc_state = PD_CC_UNSET;
- tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
-
- return 0;
-}
-
-static unsigned int tc_state_try_wait_src_run(int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (host_cc == TYPEC_CC_VOLT_RD)
- host_new_cc_state = PD_CC_UFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].host_cc_debounce =
- get_time().val + PD_T_TRY_CC_DEBOUNCE;
- return 0;
- }
-
- if (get_time().val > tc[port].host_cc_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to Attached.SRC when host-side VBUS is at vSafe0V and the
- * SRC.Rd state is detected on the Host-side port’s CC pin for
- * at least tTryCCDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_UFP_ATTACHED &&
- !vpd_is_host_vbus_present()) {
- set_state(port, TC_OBJ(port), tc_state_attached_src);
- return 0;
- }
- }
-
- if (get_time().val > tc[port].next_role_swap) {
- /*
- * The Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK after tDRPTry if the Host-side port’s CC
- * pin is not in the SRC.Rd state.
- */
- if (tc[port].host_cc_state == PD_CC_NONE) {
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
- return 0;
- }
- }
-
- return RUN_SUPER;
-}
-
-/**
- * CTTry.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Connect Charge-Through Rd
- * Get power from VCONN
- */
-static unsigned int tc_state_ct_try_snk(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_ct_try_snk_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rp3_ct_rd);
-}
-
-static unsigned int tc_state_ct_try_snk_entry(int port)
-{
- tc[port].state_id = CTTRY_SNK;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
- tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
-
- return 0;
-}
-
-static unsigned int tc_state_ct_try_snk_run(int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /*
- * Wait for tDRPTry before monitoring the Charge-Through
- * port’s CC pins for the SNK.Rp
- */
- if (get_time().val < tc[port].next_role_swap)
- return 0;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) || cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else
- new_cc_state = PD_CC_NONE;
-
- /*
- * The Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
- return 0;
- }
-
- /* Debounce the CT CC state */
- if (tc[port].cc_state != new_cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_DEBOUNCE;
- tc[port].try_wait_debounce = get_time().val + PD_T_TRY_WAIT;
-
- return 0;
- }
-
- if (get_time().val > tc[port].cc_debounce) {
- /*
- * The Charge-Through VCONN-Powered USB Device shall then
- * transition to CTAttached.VPD when the SNK.Rp state is
- * detected on the Charge-Through port’s CC pins for at
- * least tTryCCDebounce and VBUS is detected on
- * Charge-Through port.
- */
- if (tc[port].cc_state == PD_CC_DFP_ATTACHED &&
- vpd_is_ct_vbus_present()) {
- set_state(port, TC_OBJ(port), tc_state_ct_attached_vpd);
- return 0;
- }
- }
-
- if (get_time().val > tc[port].try_wait_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to CTAttached.Unsupported if SNK.Rp state is not detected
- * for tDRPTryWait.
- */
- if (tc[port].cc_state == PD_CC_NONE) {
- set_state(port, TC_OBJ(port),
- tc_state_ct_attached_unsupported);
- return 0;
- }
- }
-
- return RUN_SUPER;
-}
-
-static unsigned int tc_state_ct_try_snk_exit(int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-
- return 0;
-}
-
-/**
- * CTAttachWait.Unsupported
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Place RPUSB on Charge-Through CC
- * Get power from VCONN
- */
-static unsigned int
- tc_state_ct_attach_wait_unsupported(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_ct_attach_wait_unsupported_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rp3_ct_rpu);
-}
-
-static unsigned int tc_state_ct_attach_wait_unsupported_entry(int port)
-{
- tc[port].state_id = CTATTACH_WAIT_UNSUPPORTED;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
-
- return 0;
-}
-
-static unsigned int tc_state_ct_attach_wait_unsupported_run(int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_at_least_one_rd(cc1, cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else if (cc_is_audio_acc(cc1, cc2))
- new_cc_state = PD_CC_AUDIO_ACC;
- else /* (cc1 == TYPEC_CC_VOLT_OPEN or cc2 == TYPEC_CC_VOLT_OPEN */
- new_cc_state = PD_CC_NONE;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
- return 0;
- }
-
- /* Debounce the cc state */
- if (tc[port].cc_state != new_cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- return 0;
- }
-
- /* Wait for CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return 0;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD when the state of either the Charge-Through
- * Port’s CC1 or CC2 pin is SRC.Open for at least tCCDebounce.
- *
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTTry.SNK if the state of at least one of the Charge-Through
- * port’s CC pins is SRC.Rd, or if the state of both the CC1 and CC2
- * pins is SRC.Ra. for at least tCCDebounce.
- */
- if (new_cc_state == PD_CC_NONE)
- set_state(port, TC_OBJ(port), tc_state_ct_unattached_vpd);
- else /* PD_CC_DFP_ATTACHED or PD_CC_AUDIO_ACC */
- set_state(port, TC_OBJ(port), tc_state_ct_try_snk);
-
- return 0;
-}
-
-static unsigned int tc_state_ct_attach_wait_unsupported_exit(int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-
- return 0;
-}
-
-/**
- * CTAttached.Unsupported
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Place RPUSB on Charge-Through CC
- * Get power from VCONN
- */
-static unsigned int tc_state_ct_attached_unsupported(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_ct_attached_unsupported_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rp3_ct_rpu);
-}
-
-static unsigned int tc_state_ct_attached_unsupported_entry(int port)
-{
- tc[port].state_id = CTATTACHED_UNSUPPORTED;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Present Billboard device */
- vpd_present_billboard(BB_SNK);
-
- return 0;
-}
-
-static unsigned int tc_state_ct_attached_unsupported_run(int port)
-{
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (!vpd_is_vconn_present()) {
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
- return 0;
- }
-
- /*
- * The Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD when SRC.Open state is detected on both the
- * Charge-Through port’s CC pins or the SRC.Open state is detected
- * on one CC pin and SRC.Ra is detected on the other CC pin.
- */
- if ((cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN) ||
- (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_RA) ||
- (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_OPEN)) {
- set_state(port, TC_OBJ(port), tc_state_ct_unattached_vpd);
- return 0;
- }
-
- return RUN_SUPER;
-}
-
-static unsigned int tc_state_ct_attached_unsupported_exit(int port)
-{
- vpd_present_billboard(BB_NONE);
-
- return 0;
-}
-
-/**
- * CTUnattached.Unsupported
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Place RPUSB on Charge-Through CC
- * Get power from VCONN
- */
-static unsigned int
- tc_state_ct_unattached_unsupported(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_ct_unattached_unsupported_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rp3_ct_rpu);
-}
-
-static unsigned int tc_state_ct_unattached_unsupported_entry(int port)
-{
- tc[port].state_id = CTUNATTACHED_UNSUPPORTED;
- if (tc[port].obj.last_state != tc_state_ct_unattached_vpd)
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC;
-
- return 0;
-}
-
-static unsigned int tc_state_ct_unattached_unsupported_run(int port)
-{
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTAttachWait.Unsupported when a Sink connection is detected on
- * the Charge-Through port, as indicated by the SRC.Rd state on at
- * least one of the Charge-Through port’s CC pins or SRC.Ra state
- * on both the CC1 and CC2 pins.
- */
- if (cc_is_at_least_one_rd(cc1, cc2) || cc_is_audio_acc(cc1, cc2)) {
- set_state(port, TC_OBJ(port),
- tc_state_ct_attach_wait_unsupported);
- return 0;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
- return 0;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD within tDRPTransition after dcSRC.DRP ∙ tDRP.
- */
- if (get_time().val > tc[port].next_role_swap) {
- set_state(port, TC_OBJ(port), tc_state_ct_unattached_vpd);
- return 0;
- }
-
- return RUN_SUPER;
-}
-
-static unsigned int tc_state_ct_unattached_unsupported_exit(int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-
- return 0;
-}
-
-/**
- * CTUnattached.VPD
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Connect Charge-Through Rd
- * Get power from VCONN
- */
-static unsigned int tc_state_ct_unattached_vpd(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_ct_unattached_vpd_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rp3_ct_rd);
-}
-
-static unsigned int tc_state_ct_unattached_vpd_entry(int port)
-{
- tc[port].state_id = CTUNATTACHED_VPD;
- if (tc[port].obj.last_state != tc_state_ct_unattached_unsupported)
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
-
- return 0;
-}
-
-static unsigned int tc_state_ct_unattached_vpd_run(int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) != cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else if (!cc_is_rp(cc1) && !cc_is_rp(cc2))
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UNSET;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTAttachWait.VPD when a Source connection is detected on the
- * Charge-Through port, as indicated by the SNK.Rp state on
- * exactly one of the Charge-Through port’s CC pins.
- */
- if (new_cc_state == PD_CC_DFP_ATTACHED) {
- set_state(port, TC_OBJ(port),
- tc_state_ct_attach_wait_vpd);
- return 0;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state(port, TC_OBJ(port),
- tc_state_unattached_snk);
- return 0;
- }
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_DRP_SRC;
- return 0;
- }
-
- if (get_time().val < tc[port].cc_debounce)
- return 0;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.Unsupported within tDRPTransition after the state
- * of both the Charge-Through port’s CC1 and CC2 pins is SNK.Open
- * for tDRP-dcSRC.DRP ∙ tDRP, or if directed.
- */
- if (tc[port].cc_state == PD_CC_NONE) {
- set_state(port, TC_OBJ(port),
- tc_state_ct_unattached_unsupported);
- return 0;
- }
-
- return RUN_SUPER;
-}
-
-static unsigned int tc_state_ct_unattached_vpd_exit(int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-
- return 0;
-}
-
-/**
- * CTDisabled.VPD
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Remove the terminations from Host
- * Remove the terminations from Charge-Through
- */
-static unsigned int tc_state_ct_disabled_vpd(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_ct_disabled_vpd_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_open_ct_open);
-}
-
-static unsigned int tc_state_ct_disabled_vpd_entry(int port)
-{
- tc[port].state_id = CTDISABLED_VPD;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Get power from VBUS */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-
- tc[port].next_role_swap = get_time().val + PD_T_VPDDISABLE;
-
- return 0;
-}
-
-static unsigned int tc_state_ct_disabled_vpd_run(int port)
-{
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK after tVPDDisable.
- */
- if (get_time().val > tc[port].next_role_swap)
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
-
- return 0;
-}
-
-/**
- * CTAttached.VPD
- */
-static unsigned int tc_state_ct_attached_vpd(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_ct_attached_vpd_sig[sig])(port);
- return SUPER(ret, sig, 0);
-}
-
-static unsigned int tc_state_ct_attached_vpd_entry(int port)
-{
- int cc1;
- int cc2;
-
- tc[port].state_id = CTATTACHED_VPD;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Get power from VCONN */
- vpd_vconn_pwr_sel_odl(PWR_VCONN);
-
- /*
- * Detect which of the Charge-Through port’s CC1 or CC2
- * pins is connected through the cable
- */
- vpd_ct_get_cc(&cc1, &cc2);
- tc[port].ct_cc = cc_is_rp(cc2) ? CT_CC2 : CT_CC1;
-
- /*
- * 1. Remove or reduce any additional capacitance on the
- * Host-side CC port
- */
- vpd_mcu_cc_en(0);
-
- /*
- * 2. Disable the Rp termination advertising 3.0 A on the
- * host port’s CC pin
- */
- vpd_host_set_pull(TYPEC_CC_OPEN, 0);
-
- /*
- * 3. Passively multiplex the detected Charge-Through port’s
- * CC pin through to the host port’s CC
- */
- vpd_ct_cc_sel(tc[port].ct_cc);
-
- /*
- * 4. Disable the Rd on the Charge-Through port’s CC1 and CC2
- * pins
- */
- vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
-
- /*
- * 5. Connect the Charge-Through port’s VBUS through to the
- * host port’s VBUS
- */
- vpd_vbus_pass_en(1);
-
- tc[port].cc_state = PD_CC_UNSET;
-
- return 0;
-}
-
-static unsigned int tc_state_ct_attached_vpd_run(int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTDisabled.VPD if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state(port, TC_OBJ(port), tc_state_ct_disabled_vpd);
- return 0;
- }
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
- if ((tc[port].ct_cc ? cc2 : cc1) == TYPEC_CC_VOLT_OPEN)
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_DFP_ATTACHED;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_VPDCTDD;
- return 0;
- }
-
- if (get_time().val < tc[port].pd_debounce)
- return 0;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD when VBUS falls below vSinkDisconnect and the
- * state of the passed-through CC pin is SNK.Open for tVPDCTDD.
- */
- if (tc[port].cc_state == PD_CC_NONE && !vpd_is_ct_vbus_present())
- set_state(port, TC_OBJ(port), tc_state_ct_unattached_vpd);
-
- return 0;
-}
-
-/**
- * CTAttachWait.VPD
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Connect Charge-Through Rd
- * Get power from VCONN
- */
-static unsigned int tc_state_ct_attach_wait_vpd(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_ct_attach_wait_vpd_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rp3_ct_rd);
-}
-
-static unsigned int tc_state_ct_attach_wait_vpd_entry(int port)
-{
- tc[port].state_id = CTATTACH_WAIT_VPD;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
-
- /* Sample CCs every 2ms */
- tc_set_timeout(port, 2 * MSEC);
- return 0;
-}
-
-static unsigned int tc_state_ct_attach_wait_vpd_run(int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) != cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else if (!cc_is_rp(cc1) && !cc_is_rp(cc2))
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UNSET;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTDisabled.VPD if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state(port, TC_OBJ(port), tc_state_ct_disabled_vpd);
- return 0;
- }
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- tc[port].pd_debounce = get_time().val +
- PD_T_PD_DEBOUNCE;
- return 0;
- }
-
- if (get_time().val > tc[port].pd_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to CTUnattached.VPD when the state of both the Charge-Through
- * port’s CC1 and CC2 pins are SNK.Open for at least
- * tPDDebounce.
- */
- if (tc[port].cc_state == PD_CC_NONE) {
- set_state(port, TC_OBJ(port),
- tc_state_ct_unattached_vpd);
- return 0;
- }
- }
-
- if (get_time().val > tc[port].cc_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTAttached.VPD after the state of only one of the
- * Charge-Through port’s CC1 or CC2 pins is SNK.Rp for at
- * least tCCDebounce and VBUS on the Charge-Through port is
- * detected.
- */
- if (tc[port].cc_state == PD_CC_DFP_ATTACHED &&
- vpd_is_ct_vbus_present()) {
- set_state(port, TC_OBJ(port), tc_state_ct_attached_vpd);
- return 0;
- }
- }
-
- return RUN_SUPER;
-}
-
-static unsigned int tc_state_ct_attach_wait_vpd_exit(int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-
- /* Reset timeout value to 10ms */
- tc_set_timeout(port, 10 * MSEC);
-
- return 0;
-}
-
-/**
- * Super State HOST_RP3_CT_RD
- */
-static unsigned int tc_state_host_rp3_ct_rd(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_host_rp3_ct_rd_sig[sig])(port);
-
- return SUPER(ret, sig, tc_state_vbus_cc_iso);
-}
-
-static unsigned int tc_state_host_rp3_ct_rd_entry(int port)
-{
- /* Place RP3A0 on Host CC */
- vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_3A0);
-
- /* Connect Charge-Through Rd */
- vpd_ct_set_pull(TYPEC_CC_RD, 0);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall
- * ensure that it is powered by VCONN
- */
-
- /* Make sure vconn is on */
- if (!vpd_is_vconn_present())
- set_state(port, TC_OBJ(port), tc_state_error_recovery);
-
- /* Get power from VCONN */
- vpd_vconn_pwr_sel_odl(PWR_VCONN);
-
- return 0;
-}
-
-static unsigned int tc_state_host_rp3_ct_rd_run(int port)
-{
- return 0;
-}
-
-/**
- * Super State HOST_RP3_CT_RPU
- */
-static unsigned int tc_state_host_rp3_ct_rpu(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_host_rp3_ct_rpu_sig[sig])(port);
- return SUPER(ret, sig, tc_state_vbus_cc_iso);
-}
-
-static unsigned int tc_state_host_rp3_ct_rpu_entry(int port)
-{
- /* Place RP3A0 on Host CC */
- vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_3A0);
-
- /* Place RPUSB on Charge-Through CC */
- vpd_ct_set_pull(TYPEC_CC_RP, TYPEC_RP_USB);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall
- * ensure that it is powered by VCONN
- */
-
- /* Make sure vconn is on */
- if (!vpd_is_vconn_present())
- set_state(port, TC_OBJ(port), tc_state_error_recovery);
-
- /* Get power from VCONN */
- vpd_vconn_pwr_sel_odl(PWR_VCONN);
-
- return 0;
-}
-
-static unsigned int tc_state_host_rp3_ct_rpu_run(int port)
-{
- return 0;
-}
-
-static unsigned int do_nothing_exit(int port)
-{
- return 0;
-}
-
-static unsigned int get_super_state(int port)
-{
- return RUN_SUPER;
-}
+extern struct type_c tc[];
-#endif /* CONFIG_USB_TYPEC_CTVPD */
+#endif /* __CROS_EC_USB_TC_CTVPD_SM_H */
diff --git a/include/usb_tc_sm.h b/include/usb_tc_sm.h
index 08e9ebbf54..4a2af0fa6f 100644
--- a/include/usb_tc_sm.h
+++ b/include/usb_tc_sm.h
@@ -8,6 +8,8 @@
#ifndef __CROS_EC_USB_TC_H
#define __CROS_EC_USB_TC_H
+#include "usb_sm.h"
+
enum typec_state_id {
DISABLED,
UNATTACHED_SNK,
@@ -45,6 +47,34 @@ enum typec_state_id {
TC_STATE_COUNT,
};
+extern const char * const tc_state_names[];
+
+#define TC_SET_FLAG(port, flag) atomic_or(&tc[port].flags, (flag))
+#define TC_CLR_FLAG(port, flag) atomic_clear(&tc[port].flags, (flag))
+#define TC_CHK_FLAG(port, flag) (tc[port].flags & (flag))
+
+/*
+ * TC_OBJ is a convenience macro to access struct sm_obj, which
+ * must be the first member of struct type_c.
+ */
+#define TC_OBJ(port) (SM_OBJ(tc[port]))
+
+/*
+ * Type C supply voltage (mV)
+ *
+ * This is the maximum voltage a sink can request
+ * while charging.
+ */
+#define TYPE_C_VOLTAGE 5000 /* mV */
+
+/*
+ * Type C default sink current (mA)
+ *
+ * This is the maximum current a sink can draw if charging
+ * while in the Audio Accessory State.
+ */
+#define TYPE_C_AUDIO_ACC_CURRENT 500 /* mA */
+
/**
* Get the id of the current Type-C state
*
@@ -76,6 +106,48 @@ int tc_get_power_role(int port);
*/
void tc_set_timeout(int port, uint64_t timeout);
+/**
+ * Returns the polarity of a Sink.
+ *
+ * @param cc1 value of CC1 set by tcpm_get_cc
+ * @param cc2 value of CC2 set by tcpm_get_cc
+ * @return 0 if cc1 is connected, else 1 for cc2
+ */
+enum pd_cc_polarity_type get_snk_polarity(int cc1, int cc2);
+
+/**
+ * Restarts the TCPC
+ *
+ * @param port USB-C port number
+ * @returns EC_SUCCESS on success
+ */
+int tc_restart_tcpc(int port);
+
+/**
+ * Sets the polarity of the port
+ *
+ * @param port USB-C port number
+ * @param polarity 0 for CC1, else 1 for CC2
+ */
+void set_polarity(int port, int polarity);
+
+/**
+ * Called by the state machine framework to initialize the
+ * TypeC state machine
+ *
+ * @param port USB-C port number
+ */
+void tc_state_init(int port);
+
+/**
+ * Called by the state machine framework to handle events
+ * that affect the state machine as a whole
+ *
+ * @param port USB-C port number
+ * @param evt event
+ */
+void tc_event_check(int port, int evt);
+
#ifdef CONFIG_USB_TYPEC_CTVPD
/**
* Resets the charge-through support timer. This can be
diff --git a/include/usb_tc_vpd_sm.h b/include/usb_tc_vpd_sm.h
index c8a4dd48a3..cd564cb3ce 100644
--- a/include/usb_tc_vpd_sm.h
+++ b/include/usb_tc_vpd_sm.h
@@ -3,31 +3,17 @@
* found in the LICENSE file.
*/
-#include "vpd_api.h"
+#ifndef __CROS_EC_USB_TC_VPD_SM_H
+#define __CROS_EC_USB_TC_VPD_SM_H
-/* USB Type-C VCONN Powered Device module */
-
-#ifndef __CROS_EC_USB_TC_VPD_H
-#define __CROS_EC_USB_TC_VPD_H
-
-/* Type-C Layer Flags */
-#define TC_FLAGS_VCONN_ON BIT(0)
-
-#undef PD_DEFAULT_STATE
-/* Port default state at startup */
-#define PD_DEFAULT_STATE(port) tc_state_unattached_snk
-
-/*
- * TC_OBJ is a convenience macro to access struct sm_obj, which
- * must be the first member of struct type_c.
- */
-#define TC_OBJ(port) (SM_OBJ(tc[port]))
+#include "usb_sm.h"
+#include "usb_tc_sm.h"
/**
* This is the Type-C Port object that contains information needed to
* implement a VCONN Powered Device.
*/
-static struct type_c {
+struct type_c {
/*
* struct sm_obj must be first. This is the state machine
* object that keeps track of the current and last state
@@ -53,434 +39,8 @@ static struct type_c {
/* VPD host port cc state */
enum pd_cc_states host_cc_state;
uint8_t ct_cc;
-} tc[CONFIG_USB_PD_PORT_COUNT];
-
-/* Type-C states */
-static unsigned int tc_state_disabled(int port, enum signal sig);
-static unsigned int tc_state_disabled_entry(int port);
-static unsigned int tc_state_disabled_run(int port);
-static unsigned int tc_state_disabled_exit(int port);
-
-static unsigned int tc_state_unattached_snk(int port, enum signal sig);
-static unsigned int tc_state_unattached_snk_entry(int port);
-static unsigned int tc_state_unattached_snk_run(int port);
-static unsigned int tc_state_unattached_snk_exit(int port);
-
-static unsigned int tc_state_attach_wait_snk(int port, enum signal sig);
-static unsigned int tc_state_attach_wait_snk_entry(int port);
-static unsigned int tc_state_attach_wait_snk_run(int port);
-static unsigned int tc_state_attach_wait_snk_exit(int port);
-
-static unsigned int tc_state_attached_snk(int port, enum signal sig);
-static unsigned int tc_state_attached_snk_entry(int port);
-static unsigned int tc_state_attached_snk_run(int port);
-static unsigned int tc_state_attached_snk_exit(int port);
-
-/* Super States */
-static unsigned int tc_state_host_rard(int port, enum signal sig);
-static unsigned int tc_state_host_rard_entry(int port);
-static unsigned int tc_state_host_rard_run(int port);
-static unsigned int tc_state_host_rard_exit(int port);
-
-static unsigned int tc_state_host_open(int port, enum signal sig);
-static unsigned int tc_state_host_open_entry(int port);
-static unsigned int tc_state_host_open_run(int port);
-static unsigned int tc_state_host_open_exit(int port);
-
-static unsigned int tc_state_vbus_cc_iso(int port, enum signal sig);
-static unsigned int tc_state_vbus_cc_iso_entry(int port);
-static unsigned int tc_state_vbus_cc_iso_run(int port);
-static unsigned int tc_state_vbus_cc_iso_exit(int port);
-
-static unsigned int get_super_state(int port);
-
-static const state_sig tc_state_disabled_sig[] = {
- tc_state_disabled_entry,
- tc_state_disabled_run,
- tc_state_disabled_exit,
- get_super_state
};
-static const state_sig tc_state_unattached_snk_sig[] = {
- tc_state_unattached_snk_entry,
- tc_state_unattached_snk_run,
- tc_state_unattached_snk_exit,
- get_super_state
-};
-
-static const state_sig tc_state_attach_wait_snk_sig[] = {
- tc_state_attach_wait_snk_entry,
- tc_state_attach_wait_snk_run,
- tc_state_attach_wait_snk_exit,
- get_super_state
-};
-
-static const state_sig tc_state_attached_snk_sig[] = {
- tc_state_attached_snk_entry,
- tc_state_attached_snk_run,
- tc_state_attached_snk_exit,
- get_super_state
-};
-
-static const state_sig tc_state_host_rard_sig[] = {
- tc_state_host_rard_entry,
- tc_state_host_rard_run,
- tc_state_host_rard_exit,
- get_super_state
-};
-
-static const state_sig tc_state_host_open_sig[] = {
- tc_state_host_open_entry,
- tc_state_host_open_run,
- tc_state_host_open_exit,
- get_super_state
-};
-
-static const state_sig tc_state_vbus_cc_iso_sig[] = {
- tc_state_vbus_cc_iso_entry,
- tc_state_vbus_cc_iso_run,
- tc_state_vbus_cc_iso_exit,
- get_super_state
-};
-
-static void tc_state_init(int port)
-{
- int res = 0;
- sm_state this_state;
-
- res = tc_restart_tcpc(port);
-
- CPRINTS("TCPC p%d init %s", port, res ? "failed" : "ready");
- this_state = res ? tc_state_disabled : PD_DEFAULT_STATE(port);
-
- /* Disable TCPC RX until connection is established */
- tcpm_set_rx_enable(port, 0);
-
- init_state(port, TC_OBJ(port), this_state);
-
- /* Disable pd state machines */
- tc[port].pd_enable = 0;
- tc[port].evt_timeout = 10*MSEC;
- tc[port].power_role = PD_PLUG_CABLE_VPD;
- tc[port].data_role = 0; /* Reserved for VPD */
- tc[port].flags = 0;
-}
-
-static void tc_event_check(int port, int evt)
-{
- /* Do Nothing */
-}
-
-/**
- * Disabled
- *
- * Super State Entries:
- * Enable mcu communication
- * Remove the terminations from Host CC
- */
-static unsigned int tc_state_disabled(int port, enum signal sig)
-{
- int ret = 0;
-
- ret = (*tc_state_disabled_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_open);
-}
-
-static unsigned int tc_state_disabled_entry(int port)
-{
- tc[port].state_id = DISABLED;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- return 0;
-}
-
-static unsigned int tc_state_disabled_run(int port)
-{
- task_wait_event(-1);
-
- return RUN_SUPER;
-}
-
-static unsigned int tc_state_disabled_exit(int port)
-{
-#ifndef CONFIG_USB_PD_TCPC
- if (tc_restart_tcpc(port) != 0) {
- CPRINTS("TCPC p%d restart failed!", port);
- return 0;
- }
-#endif
- CPRINTS("TCPC p%d resumed!", port);
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
-
- return 0;
-}
-
-/**
- * Unattached.SNK
- *
- * Super State Entry:
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- */
-static unsigned int tc_state_unattached_snk(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_unattached_snk_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rard);
-}
-
-static unsigned int tc_state_unattached_snk_entry(int port)
-{
- tc[port].state_id = UNATTACHED_SNK;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- return 0;
-}
-
-static unsigned int tc_state_unattached_snk_run(int port)
-{
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * Transition to AttachWait.SNK when a Source connection is
- * detected, as indicated by the SNK.Rp state on its Host-side
- * port’s CC pin.
- */
- if (cc_is_rp(host_cc)) {
- set_state(port, TC_OBJ(port), tc_state_attach_wait_snk);
- return 0;
- }
-
- return RUN_SUPER;
-}
-
-static unsigned int tc_state_unattached_snk_exit(int port)
-{
- return 0;
-}
-
-/**
- * AttachedWait.SNK
- *
- * Super State Entry:
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- */
-static unsigned int tc_state_attach_wait_snk(int port, enum signal sig)
-{
- int ret = 0;
-
- ret = (*tc_state_attach_wait_snk_sig[sig])(port);
- return SUPER(ret, sig, tc_state_host_rard);
-}
-
-static unsigned int tc_state_attach_wait_snk_entry(int port)
-{
- tc[port].state_id = ATTACH_WAIT_SNK;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
- tc[port].host_cc_state = PD_CC_UNSET;
-
- return 0;
-}
-
-static unsigned int tc_state_attach_wait_snk_run(int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- if (host_new_cc_state == PD_CC_DFP_ATTACHED)
- tc[port].cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- else
- tc[port].cc_debounce = get_time().val +
- PD_T_PD_DEBOUNCE;
-
- return 0;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return 0;
-
- /*
- * A VCONN-Powered USB Device shall transition to
- * Attached.SNK after the state of the Host-side port’s CC pin is
- * SNK.Rp for at least tCCDebounce and either host-side VCONN or
- * VBUS is detected.
- *
- * Transition to Unattached.SNK when the state of both the CC1 and
- * CC2 pins is SNK.Open for at least tPDDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
- (vpd_is_vconn_present() || vpd_is_host_vbus_present()))
- set_state(port, TC_OBJ(port), tc_state_attached_snk);
- else if (tc[port].host_cc_state == PD_CC_NONE)
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
-
- return 0;
-}
-
-static unsigned int tc_state_attach_wait_snk_exit(int port)
-{
- return 0;
-}
-
-/**
- * Attached.SNK
- */
-static unsigned int tc_state_attached_snk(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_attached_snk_sig[sig])(port);
- return SUPER(ret, sig, 0);
-}
-
-static unsigned int tc_state_attached_snk_entry(int port)
-{
- tc[port].state_id = ATTACHED_SNK;
- CPRINTS("C%d: %s", port, tc_state_names[tc[port].state_id]);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- set_polarity(port, 0);
-
- return 0;
-}
-
-static unsigned int tc_state_attached_snk_run(int port)
-{
- /* Has host vbus and vconn been removed */
- if (!vpd_is_host_vbus_present() && !vpd_is_vconn_present()) {
- set_state(port, TC_OBJ(port), tc_state_unattached_snk);
- return 0;
- }
-
- if (vpd_is_vconn_present()) {
- if (!(tc[port].flags & TC_FLAGS_VCONN_ON)) {
- /* VCONN detected. Remove RA */
- vpd_host_set_pull(TYPEC_CC_RD, 0);
- tc[port].flags |= TC_FLAGS_VCONN_ON;
- }
- }
-
- return 0;
-}
-
-static unsigned int tc_state_attached_snk_exit(int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
- tc[port].flags &= ~TC_FLAGS_VCONN_ON;
-
- return 0;
-}
-
-/**
- * Super State HOST_RARD
- */
-static unsigned int tc_state_host_rard(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_host_rard_sig[sig])(port);
- return SUPER(ret, sig, tc_state_vbus_cc_iso);
-}
-
-static unsigned int tc_state_host_rard_entry(int port)
-{
- /* Place Ra on VCONN and Rd on Host CC */
- vpd_host_set_pull(TYPEC_CC_RA_RD, 0);
-
- return 0;
-}
-
-static unsigned int tc_state_host_rard_run(int port)
-{
- return RUN_SUPER;
-}
-
-static unsigned int tc_state_host_rard_exit(int port)
-{
- return 0;
-}
-
-/**
- * Super State HOST_OPEN
- */
-static unsigned int tc_state_host_open(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_host_open_sig[sig])(port);
- return SUPER(ret, sig, tc_state_vbus_cc_iso);
-}
-
-static unsigned int tc_state_host_open_entry(int port)
-{
- /* Remove the terminations from Host CC */
- vpd_host_set_pull(TYPEC_CC_OPEN, 0);
-
- return 0;
-}
-
-static unsigned int tc_state_host_open_run(int port)
-{
- return RUN_SUPER;
-}
-
-static unsigned int tc_state_host_open_exit(int port)
-{
- return 0;
-}
-
-/**
- * Super State VBUS_CC_ISO
- */
-static unsigned int tc_state_vbus_cc_iso(int port, enum signal sig)
-{
- int ret;
-
- ret = (*tc_state_vbus_cc_iso_sig[sig])(port);
- return SUPER(ret, sig, 0);
-}
-
-static unsigned int tc_state_vbus_cc_iso_entry(int port)
-{
- /* Enable mcu communication and cc */
- vpd_mcu_cc_en(1);
-
- return 0;
-}
-
-static unsigned int tc_state_vbus_cc_iso_run(int port)
-{
- return 0;
-}
-
-static unsigned int tc_state_vbus_cc_iso_exit(int port)
-{
- return 0;
-}
-
-static unsigned int get_super_state(int port)
-{
- return RUN_SUPER;
-}
+extern struct type_c tc[];
-#endif /*__CROS_EC_USB_TC_VPD_H */
+#endif /* __CROS_EC_USB_TC_VPD_SM_H */
diff --git a/test/usb_sm_framework_h3.c b/test/usb_sm_framework_h3.c
index db88338387..37266517ce 100644
--- a/test/usb_sm_framework_h3.c
+++ b/test/usb_sm_framework_h3.c
@@ -200,8 +200,6 @@ static unsigned int sm_test_C_entry(int port);
static unsigned int sm_test_C_run(int port);
static unsigned int sm_test_C_exit(int port);
-static unsigned int get_super_state(int port);
-
#if defined(TEST_USB_SM_FRAMEWORK_H3)
static const state_sig sm_test_super_A1_sig[] = {
sm_test_super_A1_entry,
@@ -774,11 +772,6 @@ static unsigned int sm_test_B6_exit(int port)
return 0;
}
-static unsigned int get_super_state(int port)
-{
- return RUN_SUPER;
-}
-
static unsigned int sm_test_C(int port, enum signal sig)
{
int ret;