summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorSam Hurst <shurst@google.com>2019-11-05 18:47:47 +0000
committerCommit Bot <commit-bot@chromium.org>2019-11-06 21:49:53 +0000
commit1369d55f5e3cb9f0389c452b054d62fc74255c18 (patch)
tree4bfeacef7e4ecea4a126f9798b364e1b2f12417b /common
parentbdc0f13235d05c411a3ebd96eeb58f338cbff4da (diff)
downloadchrome-ec-1369d55f5e3cb9f0389c452b054d62fc74255c18.tar.gz
Revert "usbc: remove unnecessary tcpc CC reads"
This reverts commit bec03d91bc9f954682c02d122a0500d10cc102c2. Reason for revert: Some TCPC's bugs will generate an attach event when nothing is connected, triggering the state machine to enter an attached state. Example output with nothing connected to the port: 2019-10-28 10:23:20 [0.044393 C1: Unattached.SNK] 2019-10-28 10:23:20 [0.101264 p1: PPC init'd.] 2019-10-28 10:23:20 [0.106488 C1: Unattached.SRC] 2019-10-28 10:23:20 [0.116072 C1: AttachWait.SRC] 2019-10-28 10:23:20 [0.220006 C1: Attached.SRC] TOT has basic TypeC/PD functionality but issues still exist that will be fixed in subsequent CLs. Original change's description: > usbc: remove unnecessary tcpc CC reads > > We only need to read the CC pins when the CC evt is fired otherwise the > CC pins should have the same value. It is actually incorrect/undesirable > that our old PD stack queried the tpcp cc driver over i2c so frequently > for the CC pins status. > > Also single source code that interprets the CC lines values into a UFP > or DFP state. > > Lastly, remove extraneous timers for cc debouncing, we only need one. > > BRANCH=none > BUG=none > TEST=builds > > Change-Id: I65baa2e6fb92d7ab5ca12daa76225cd13b9ab974 > Signed-off-by: Jett Rink <jettrink@chromium.org> > Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1825504 > Reviewed-by: Denis Brockus <dbrockus@chromium.org> > Reviewed-by: Sam Hurst <shurst@google.com> > Commit-Queue: Denis Brockus <dbrockus@chromium.org> Bug: none Change-Id: Ie9bd366dd85df9a33934e06e4208543f6e7aaa9b Signed-off-by: Sam Hurst <shurst@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1900058 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
Diffstat (limited to 'common')
-rw-r--r--common/usb_common.c1
-rw-r--r--common/usbc/usb_tc_ctvpd_sm.c3
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c645
3 files changed, 458 insertions, 191 deletions
diff --git a/common/usb_common.c b/common/usb_common.c
index 85e81b8042..eab88e0e5e 100644
--- a/common/usb_common.c
+++ b/common/usb_common.c
@@ -107,7 +107,6 @@ enum pd_cc_states pd_get_cc_state(
*/
return PD_CC_NONE;
}
-
/*
* Zinger implements a board specific usb policy that does not define
* PD_MAX_VOLTAGE_MV and PD_OPERATING_POWER_MW. And in turn, does not
diff --git a/common/usbc/usb_tc_ctvpd_sm.c b/common/usbc/usb_tc_ctvpd_sm.c
index 996b38b6fb..1747a8c0ab 100644
--- a/common/usbc/usb_tc_ctvpd_sm.c
+++ b/common/usbc/usb_tc_ctvpd_sm.c
@@ -29,9 +29,6 @@
#define SUPPORT_TIMER_RESET_REQUEST 1
#define SUPPORT_TIMER_RESET_COMPLETE 2
-/* Constant used to force an initial debounce cycle */
-#define PD_CC_UNSET -1
-
/**
* This is the Type-C Port object that contains information needed to
* implement a Charge Through VCONN Powered Device.
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
index 2accd67d6e..a6c58ce843 100644
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
@@ -50,7 +50,7 @@
#define TC_FLAGS_PARTNER_EXTPOWER BIT(13)
#define TC_FLAGS_PARTNER_DR_DATA BIT(14)
#define TC_FLAGS_PARTNER_DR_POWER BIT(15)
-#define TC_FLAGS_PARTNER_PD_CAPABLE BIT(16)
+#define TC_FLAGS_PARTNER_PD_CAPABLE BIT(16)
#define TC_FLAGS_HARD_RESET BIT(17)
#define TC_FLAGS_PARTNER_USB_COMM BIT(18)
#define TC_FLAGS_PR_SWAP_IN_PROGRESS BIT(19)
@@ -112,9 +112,7 @@ static const char * const tc_state_names[] = {
/* Generate a compiler error if invalid states are referenced */
#ifndef CONFIG_USB_PD_TRY_SRC
-extern int TC_TRY_SRC_UNDEFINED;
#define TC_TRY_SRC TC_TRY_SRC_UNDEFINED
-extern int TC_TRY_WAIT_SNK_UNDEFINED;
#define TC_TRY_WAIT_SNK TC_TRY_WAIT_SNK_UNDEFINED
#endif
@@ -135,22 +133,39 @@ static struct type_c {
uint8_t polarity;
/* port flags, see TC_FLAGS_* */
uint32_t flags;
+ /* event timeout */
+ uint64_t evt_timeout;
+ /* Time a port shall wait before it can determine it is attached */
+ uint64_t cc_debounce;
+ /*
+ * Time a Sink port shall wait before it can determine it is detached
+ * due to the potential for USB PD signaling on CC as described in
+ * the state definitions.
+ */
+ uint64_t pd_debounce;
+#ifdef CONFIG_USB_PD_TRY_SRC
+ /*
+ * Time a port shall wait before it can determine it is
+ * re-attached during the try-wait process.
+ */
+ uint64_t try_wait_debounce;
+#endif
+ /* The cc state */
+ enum pd_cc_states cc_state;
/* Role toggle timer */
uint64_t next_role_swap;
/* Generic timer */
uint64_t timeout;
+#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
/* Time to enter low power mode */
uint64_t low_power_time;
/* Tasks to notify after TCPC has been reset */
int tasks_waiting_on_reset;
/* Tasks preventing TCPC from entering low power mode */
int tasks_preventing_lpm;
- /* The last time the cc1 or cc2 line changed. */
- uint64_t cc_last_change;
- /* Current voltage on CC pins */
- enum tcpc_cc_voltage_status cc1, cc2;
- /* Interpreted PD state of above cc1 and cc2 lines */
- enum pd_cc_states cc_state;
+#endif
+ /* Voltage on CC pin */
+ enum tcpc_cc_voltage_status cc_voltage;
/* Type-C current */
typec_current_t typec_curr;
/* Type-C current change */
@@ -162,7 +177,6 @@ static struct type_c {
} tc[CONFIG_USB_PD_PORT_MAX_COUNT];
/* Port dual-role state */
-static __maybe_unused
enum pd_dual_role_states drp_state[CONFIG_USB_PD_PORT_MAX_COUNT] = {
[0 ... (CONFIG_USB_PD_PORT_MAX_COUNT - 1)] =
CONFIG_USB_PD_INITIAL_DRP_STATE};
@@ -171,19 +185,13 @@ enum pd_dual_role_states drp_state[CONFIG_USB_PD_PORT_MAX_COUNT] = {
static void set_vconn(int port, int enable);
#endif
-/* Forward declare common, private functions */
-static void exit_low_power_mode(int port);
-static void handle_device_access(int port);
-static void handle_new_power_state(int port);
-static int reset_device_and_notify(int port);
-static void pd_update_dual_role_config(int port);
-static int pd_device_in_low_power(int port);
-static void pd_wait_for_wakeup(int port);
+#ifdef CONFIG_USB_PE_SM
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
/* Tracker for which task is waiting on sysjump prep to finish */
static volatile task_id_t sysjump_task_waiting = TASK_ID_INVALID;
+#endif
-#ifdef CONFIG_USB_PE_SM
/*
* 4 entry rw_hash table of type-C devices that AP has firmware updates for.
*/
@@ -192,15 +200,31 @@ static volatile task_id_t sysjump_task_waiting = TASK_ID_INVALID;
static struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES];
#endif
+/* Forward declare common, private functions */
+#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
+static void exit_low_power_mode(int port);
+static void handle_device_access(int port);
+static int pd_device_in_low_power(int port);
+static void pd_wait_for_wakeup(int port);
+static int reset_device_and_notify(int port);
+#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
+
+#ifdef CONFIG_POWER_COMMON
+static void handle_new_power_state(int port);
+#endif
+
+static void pd_update_dual_role_config(int port);
#endif /* CONFIG_USB_PE_SM */
/* Forward declare common, private functions */
static void set_state_tc(const int port, const enum usb_tc_state new_state);
test_export_static enum usb_tc_state get_state_tc(const int port);
+#ifdef CONFIG_USB_PD_TRY_SRC
/* Enable variable for Try.SRC states */
-STATIC_IF(CONFIG_USB_PD_TRY_SRC) uint8_t pd_try_src_enable;
-STATIC_IF(CONFIG_USB_PD_TRY_SRC) void pd_update_try_source(void);
+static uint8_t pd_try_src_enable;
+static void pd_update_try_source(void);
+#endif
static void sink_stop_drawing_current(int port);
@@ -718,11 +742,19 @@ test_export_static enum usb_tc_state get_state_tc(const int port)
return tc[port].ctx.current - &tc_states[0];
}
+/* Get the previous TypeC state. */
+static enum usb_tc_state get_last_state_tc(const int port)
+{
+ return tc[port].ctx.previous - &tc_states[0];
+}
+
static void print_current_state(const int port)
{
CPRINTS("C%d: %s", port, tc_state_names[get_state_tc(port)]);
}
+#ifdef CONFIG_USB_PE_SM
+#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
/* This is only called from the PD tasks that owns the port. */
static void exit_low_power_mode(int port)
{
@@ -735,25 +767,12 @@ static void exit_low_power_mode(int port)
else
TC_CLR_FLAG(port, TC_FLAGS_LPM_REQUESTED);
}
+#endif
+#endif
void tc_event_check(int port, int evt)
{
- /* Update the cc variables if there was a change */
- if (evt & PD_EVENT_CC) {
- enum tcpc_cc_voltage_status cc1, cc2;
-
- tcpm_get_cc(port, &cc1, &cc2);
- if (cc1 != tc[port].cc1 || cc2 != tc[port].cc2) {
- tc[port].cc_state = pd_get_cc_state(cc1, cc2);
- tc[port].cc1 = cc1;
- tc[port].cc2 = cc2;
- tc[port].cc_last_change = get_time().val;
- }
- }
-
- if (!IS_ENABLED(CONFIG_USB_PE_SM))
- return;
-
+#ifdef CONFIG_USB_PE_SM
if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER)) {
if (evt & PD_EXIT_LOW_POWER_EVENT_MASK)
exit_low_power_mode(port);
@@ -762,20 +781,25 @@ void tc_event_check(int port, int evt)
handle_device_access(port);
}
+#ifdef CONFIG_POWER_COMMON
if (IS_ENABLED(CONFIG_POWER_COMMON)) {
if (evt & PD_EVENT_POWER_STATE_CHANGE)
handle_new_power_state(port);
}
+#endif
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
if (evt & PD_EVENT_SYSJUMP) {
pe_exit_dp_mode(port);
notify_sysjump_ready(&sysjump_task_waiting);
}
}
+#endif
if (evt & PD_EVENT_UPDATE_DUAL_ROLE)
pd_update_dual_role_config(port);
+#endif
}
/*
@@ -924,6 +948,8 @@ void pd_deferred_resume(int port)
}
#endif /* CONFIG_USB_PD_DEFERRED_RESUME */
+#ifdef CONFIG_USB_PE_SM
+
/* This must only be called from the PD task */
static void pd_update_dual_role_config(int port)
{
@@ -952,6 +978,7 @@ static void pd_update_dual_role_config(int port)
}
}
+#ifdef CONFIG_POWER_COMMON
static void handle_new_power_state(int port)
{
if (IS_ENABLED(CONFIG_POWER_COMMON) &&
@@ -967,8 +994,8 @@ static void handle_new_power_state(int port)
set_usb_mux_with_current_data_role(port);
}
}
+#endif /* CONFIG_POWER_COMMON */
-#ifdef CONFIG_USB_PE_SM
/*
* HOST COMMANDS
*/
@@ -1418,6 +1445,7 @@ void pd_handle_overcurrent(int port)
}
#endif /* defined(CONFIG_USBC_PPC) */
+#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
/* 10 ms is enough time for any TCPC transaction to complete. */
#define PD_LPM_DEBOUNCE_US (10 * MSEC)
@@ -1598,16 +1626,43 @@ void pd_prevent_low_power_mode(int port, int prevent)
else
atomic_clear(&tc[port].tasks_preventing_lpm, current_task_mask);
}
+#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
static void sink_power_sub_states(int port)
{
- /* Debounce cc lines for at least Rp value change timer */
- if (get_time().val < tc[port].cc_last_change + PD_T_RP_VALUE_CHANGE)
+ enum tcpc_cc_voltage_status cc1, cc2, cc;
+ enum tcpc_cc_voltage_status new_cc_voltage;
+
+ tcpm_get_cc(port, &cc1, &cc2);
+
+ cc = tc[port].polarity ? cc2 : cc1;
+
+ if (cc == TYPEC_CC_VOLT_RP_DEF)
+ new_cc_voltage = TYPEC_CC_VOLT_RP_DEF;
+ else if (cc == TYPEC_CC_VOLT_RP_1_5)
+ new_cc_voltage = TYPEC_CC_VOLT_RP_1_5;
+ else if (cc == TYPEC_CC_VOLT_RP_3_0)
+ new_cc_voltage = TYPEC_CC_VOLT_RP_3_0;
+ else
+ new_cc_voltage = TYPEC_CC_VOLT_OPEN;
+
+ /* Debounce the cc state */
+ if (new_cc_voltage != tc[port].cc_voltage) {
+ tc[port].cc_voltage = new_cc_voltage;
+ tc[port].cc_debounce =
+ get_time().val + PD_T_RP_VALUE_CHANGE;
+ return;
+ }
+
+ if (tc[port].cc_debounce == 0 ||
+ get_time().val < tc[port].cc_debounce)
return;
+ tc[port].cc_debounce = 0;
+
if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
tc[port].typec_curr = usb_get_typec_current_limit(
- tc[port].polarity, tc[port].cc1, tc[port].cc2);
+ tc[port].polarity, cc1, cc2);
typec_set_input_current_limit(port,
tc[port].typec_curr, TYPE_C_VOLTAGE);
@@ -1671,21 +1726,6 @@ static void tc_error_recovery_run(const int port)
}
}
-/* Set the CC resistors to Rd and update the TCPC power role header */
-static void set_rd(const int port)
-{
- /*
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rd. Reset last cc change time.
- */
- tcpm_set_cc(port, TYPEC_CC_RD);
- tc[port].cc_last_change = get_time().val;
-
- /* Set power role to sink */
- tc_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
-}
-
/**
* Unattached.SNK
*
@@ -1693,14 +1733,23 @@ static void set_rd(const int port)
*/
static void tc_unattached_snk_entry(const int port)
{
- /* Set Rd since we are not in the Rd superstate */
- set_rd(port);
+ if (get_last_state_tc(port) != TC_UNATTACHED_SRC)
+ print_current_state(port);
if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
charge_manager_update_dualrole(port, CAP_UNKNOWN);
+ /*
+ * Indicate that the port is disconnected so the board
+ * can restore state from any previous data swap.
+ */
+ pd_execute_data_swap(port, PD_ROLE_DISCONNECTED);
tc[port].next_role_swap = get_time().val + PD_T_DRP_SNK;
+ if (IS_ENABLED(CONFIG_USBC_SS_MUX))
+ usb_mux_set(port, TYPEC_MUX_NONE,
+ USB_SWITCH_DISCONNECT, tc[port].polarity);
+
if (IS_ENABLED(CONFIG_USB_PE_SM)) {
tc[port].flags = 0;
tc[port].pd_enable = 0;
@@ -1709,6 +1758,8 @@ static void tc_unattached_snk_entry(const int port)
static void tc_unattached_snk_run(const int port)
{
+ enum tcpc_cc_voltage_status cc1, cc2;
+
/*
* TODO(b/137498392): Add wait before sampling the CC
* status after role changes
@@ -1723,6 +1774,9 @@ static void tc_unattached_snk_run(const int port)
}
}
+ /* Check for connection */
+ tcpm_get_cc(port, &cc1, &cc2);
+
/*
* The port shall transition to AttachWait.SNK when a Source
* connection is detected, as indicated by the SNK.Rp state
@@ -1732,13 +1786,15 @@ static void tc_unattached_snk_run(const int port)
* after the state of both CC pins is SNK.Open for
* tDRP − dcSRC.DRP ∙ tDRP.
*/
- if (tc[port].cc_state == PD_CC_DFP_DEBUG_ACC ||
- tc[port].cc_state == PD_CC_DFP_ATTACHED)
+ if (cc_is_rp(cc1) || cc_is_rp(cc2)) {
/* Connection Detected */
set_state_tc(port, TC_ATTACH_WAIT_SNK);
- else if (get_time().val > tc[port].next_role_swap)
+ } else if (get_time().val > tc[port].next_role_swap) {
/* DRP Toggle */
set_state_tc(port, TC_UNATTACHED_SRC);
+ }
+
+ return;
}
/**
@@ -1752,19 +1808,43 @@ static void tc_unattached_snk_run(const int port)
static void tc_attach_wait_snk_entry(const int port)
{
print_current_state(port);
+
+ tc[port].cc_state = PD_CC_UNSET;
}
static void tc_attach_wait_snk_run(const int port)
{
+ enum tcpc_cc_voltage_status cc1, cc2;
+ enum pd_cc_states new_cc_state;
+
+ /* Check for connection */
+ tcpm_get_cc(port, &cc1, &cc2);
+
+ if (cc_is_rp(cc1) && cc_is_rp(cc2))
+ new_cc_state = PD_CC_DFP_DEBUG_ACC;
+ else if (cc_is_rp(cc1) || cc_is_rp(cc2))
+ new_cc_state = PD_CC_DFP_ATTACHED;
+ else
+ new_cc_state = PD_CC_NONE;
+
+ /* Debounce the cc state */
+ if (new_cc_state != tc[port].cc_state) {
+ tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
+ tc[port].pd_debounce = get_time().val + PD_T_PD_DEBOUNCE;
+ tc[port].cc_state = new_cc_state;
+ return;
+ }
+
/*
* A DRP shall transition to Unattached.SNK when the state of both
* the CC1 and CC2 pins is SNK.Open for at least tPDDebounce.
*/
- if (get_time().val > tc[port].cc_last_change + PD_T_PD_DEBOUNCE &&
- tc[port].cc_state == PD_CC_NONE) {
+ if (new_cc_state == PD_CC_NONE &&
+ get_time().val > tc[port].pd_debounce) {
if (IS_ENABLED(CONFIG_USB_PE_SM) &&
- IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
+ IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
pd_dfp_exit_mode(port, 0, 0);
+ }
/* We are detached */
set_state_tc(port, TC_UNATTACHED_SRC);
@@ -1772,7 +1852,7 @@ static void tc_attach_wait_snk_run(const int port)
}
/* Wait for CC debounce */
- if (get_time().val < tc[port].cc_last_change + PD_T_CC_DEBOUNCE)
+ if (get_time().val < tc[port].cc_debounce)
return;
/*
@@ -1790,22 +1870,23 @@ static void tc_attach_wait_snk_run(const int port)
* SNK.Rp for at least tCCDebounce and VBUS is detected.
*/
if (pd_is_vbus_present(port)) {
- if (tc[port].cc_state == PD_CC_DFP_ATTACHED) {
- if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC) &&
- pd_try_src_enable)
+ if (new_cc_state == PD_CC_DFP_ATTACHED) {
+#ifdef CONFIG_USB_PD_TRY_SRC
+ if (pd_try_src_enable)
set_state_tc(port, TC_TRY_SRC);
else
+#endif
set_state_tc(port, TC_ATTACHED_SNK);
} else {
- /* cc_state is PD_CC_DFP_DEBUG_ACC */
+ /* new_cc_state is PD_CC_DFP_DEBUG_ACC */
TC_SET_FLAG(port, TC_FLAGS_TS_DTS_PARTNER);
set_state_tc(port, TC_DBG_ACC_SNK);
}
if (IS_ENABLED(CONFIG_USB_PE_SM) &&
- IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
- hook_call_deferred(
- &pd_usb_billboard_deferred_data, PD_T_AME);
+ IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
+ hook_call_deferred(&pd_usb_billboard_deferred_data,
+ PD_T_AME);
}
}
}
@@ -1815,12 +1896,33 @@ static void tc_attach_wait_snk_run(const int port)
*/
static void tc_attached_snk_entry(const int port)
{
+ enum tcpc_cc_voltage_status cc1, cc2;
+
print_current_state(port);
- if (!TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
+#ifdef CONFIG_USB_PE_SM
+ if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
+ /*
+ * Both CC1 and CC2 pins shall be independently terminated to
+ * ground through Rd.
+ */
+ tcpm_set_cc(port, TYPEC_CC_RD);
+
+ /* Change role to sink */
+ tc_set_power_role(port, PD_ROLE_SINK);
+ tcpm_set_msg_header(port, tc[port].power_role,
+ tc[port].data_role);
+
+ /*
+ * Maintain VCONN supply state, whether ON or OFF, and its
+ * data role / usb mux connections.
+ */
+ } else
+#endif
+ {
/* Get connector orientation */
- tc[port].polarity = get_snk_polarity(
- tc[port].cc1, tc[port].cc2);
+ tcpm_get_cc(port, &cc1, &cc2);
+ tc[port].polarity = get_snk_polarity(cc1, cc2);
set_polarity(port, tc[port].polarity);
/*
@@ -1831,14 +1933,19 @@ static void tc_attached_snk_entry(const int port)
if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
tc[port].typec_curr =
- usb_get_typec_current_limit(
- tc[port].polarity, tc[port].cc1, tc[port].cc2);
- typec_set_input_current_limit(
- port, tc[port].typec_curr, TYPE_C_VOLTAGE);
+ usb_get_typec_current_limit(tc[port].polarity,
+ cc1, cc2);
+ typec_set_input_current_limit(port,
+ tc[port].typec_curr, TYPE_C_VOLTAGE);
charge_manager_update_dualrole(port, CAP_DEDICATED);
}
}
+ /* Apply Rd */
+ tcpm_set_cc(port, TYPEC_CC_RD);
+
+ tc[port].cc_debounce = 0;
+
/* Enable PD */
if (IS_ENABLED(CONFIG_USB_PE_SM))
tc[port].pd_enable = 1;
@@ -2003,12 +2110,16 @@ static void tc_unoriented_dbg_acc_src_entry(const int port)
static void tc_unoriented_dbg_acc_src_run(const int port)
{
+ enum tcpc_cc_voltage_status cc1, cc2;
+
+ /* Check for connection */
+ tcpm_get_cc(port, &cc1, &cc2);
+
/*
* A DRP, the port shall transition to Unattached.SNK when the
* SRC.Open state is detected on either the CC1 or CC2 pin.
*/
- if (tc[port].cc1 == TYPEC_CC_VOLT_OPEN ||
- tc[port].cc2 == TYPEC_CC_VOLT_OPEN) {
+ if (cc1 == TYPEC_CC_VOLT_OPEN || cc2 == TYPEC_CC_VOLT_OPEN) {
/* Remove VBUS */
pd_power_supply_reset(port);
@@ -2042,7 +2153,7 @@ static void tc_dbg_acc_snk_run(const int port)
{
if (!pd_is_vbus_present(port)) {
if (IS_ENABLED(CONFIG_USB_PE_SM) &&
- IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
+ IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
pd_dfp_exit_mode(port, 0, 0);
}
@@ -2050,22 +2161,6 @@ static void tc_dbg_acc_snk_run(const int port)
}
}
-/* Set the CC resistors to Rp and update the TCPC power role header */
-static void set_rp(const int port)
-{
- /*
- * Both CC1 and CC2 pins shall be independently pulled
- * up through Rp. Reset last cc change time.
- */
- tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP);
- tcpm_set_cc(port, TYPEC_CC_RP);
- tc[port].cc_last_change = get_time().val;
-
- /* Set power role to source */
- tc_set_power_role(port, PD_ROLE_SOURCE);
- tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
-}
-
/**
* Unattached.SRC
*
@@ -2073,8 +2168,8 @@ static void set_rp(const int port)
*/
static void tc_unattached_src_entry(const int port)
{
- /* Set Rd since we are not in the Rd superstate */
- set_rp(port);
+ if (get_last_state_tc(port) != TC_UNATTACHED_SNK)
+ print_current_state(port);
if (IS_ENABLED(CONFIG_USBC_PPC)) {
/* There is no sink connected. */
@@ -2100,6 +2195,8 @@ static void tc_unattached_src_entry(const int port)
static void tc_unattached_src_run(const int port)
{
+ enum tcpc_cc_voltage_status cc1, cc2;
+
if (IS_ENABLED(CONFIG_USB_PE_SM)) {
if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET)) {
TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET);
@@ -2118,6 +2215,9 @@ static void tc_unattached_src_run(const int port)
return;
}
+ /* Check for connection */
+ tcpm_get_cc(port, &cc1, &cc2);
+
/*
* Transition to AttachWait.SRC when VBUS is vSafe0V and:
* 1) The SRC.Rd state is detected on either CC1 or CC2 pin or
@@ -2126,8 +2226,7 @@ static void tc_unattached_src_run(const int port)
* A DRP shall transition to Unattached.SNK within tDRPTransition
* after dcSRC.DRP ∙ tDRP
*/
- if (cc_is_at_least_one_rd(tc[port].cc1, tc[port].cc2) ||
- cc_is_audio_acc(tc[port].cc1, tc[port].cc2))
+ if (cc_is_at_least_one_rd(cc1, cc2) || cc_is_audio_acc(cc1, cc2))
set_state_tc(port, TC_ATTACH_WAIT_SRC);
else if (get_time().val > tc[port].next_role_swap)
set_state_tc(port, TC_UNATTACHED_SNK);
@@ -2144,18 +2243,43 @@ static void tc_unattached_src_run(const int port)
static void tc_attach_wait_src_entry(const int port)
{
print_current_state(port);
+
+ tc[port].cc_state = PD_CC_UNSET;
}
static void tc_attach_wait_src_run(const int port)
{
- /* Immediate transition without debounce if we detect Vopen */
- if (tc[port].cc_state == PD_CC_NONE) {
+ enum tcpc_cc_voltage_status cc1, cc2;
+ enum pd_cc_states new_cc_state;
+
+ /* Check for connection */
+ tcpm_get_cc(port, &cc1, &cc2);
+
+ /* Debug accessory */
+ if (cc_is_snk_dbg_acc(cc1, cc2)) {
+ /* Debug accessory */
+ new_cc_state = PD_CC_UFP_DEBUG_ACC;
+ } else if (cc_is_at_least_one_rd(cc1, cc2)) {
+ /* UFP attached */
+ new_cc_state = PD_CC_UFP_ATTACHED;
+ } else if (cc_is_audio_acc(cc1, cc2)) {
+ /* AUDIO Accessory not supported. Just ignore */
+ new_cc_state = PD_CC_UFP_AUDIO_ACC;
+ } else {
+ /* No UFP */
set_state_tc(port, TC_UNATTACHED_SNK);
return;
}
+ /* Debounce the cc state */
+ if (new_cc_state != tc[port].cc_state) {
+ tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
+ tc[port].cc_state = new_cc_state;
+ return;
+ }
+
/* Wait for CC debounce */
- if (get_time().val < tc[port].cc_last_change + PD_T_CC_DEBOUNCE)
+ if (get_time().val < tc[port].cc_debounce)
return;
/*
@@ -2169,10 +2293,13 @@ static void tc_attach_wait_src_run(const int port)
* tCCDebounce.
*/
if (!pd_is_vbus_present(port)) {
- if (tc[port].cc_state == PD_CC_UFP_ATTACHED)
+ if (new_cc_state == PD_CC_UFP_ATTACHED) {
set_state_tc(port, TC_ATTACHED_SRC);
- else if (tc[port].cc_state == PD_CC_UFP_DEBUG_ACC)
+ return;
+ } else if (new_cc_state == PD_CC_UFP_DEBUG_ACC) {
set_state_tc(port, TC_UNORIENTED_DBG_ACC_SRC);
+ return;
+ }
}
}
@@ -2182,12 +2309,23 @@ static void tc_attach_wait_src_run(const int port)
*/
static void tc_attached_src_entry(const int port)
{
- print_current_state(port);
+ enum tcpc_cc_voltage_status cc1, cc2;
- /* Run function relies on timeout being 0 or meaningful */
- tc[port].timeout = 0;
+ print_current_state(port);
+#if defined(CONFIG_USB_PE_SM)
if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
+ /* Change role to source */
+ tc_set_power_role(port, PD_ROLE_SOURCE);
+ tcpm_set_msg_header(port,
+ tc[port].power_role, tc[port].data_role);
+
+ /*
+ * Both CC1 and CC2 pins shall be independently terminated to
+ * ground through Rp.
+ */
+ tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP);
+
/* Enable VBUS */
pd_set_power_supply_ready(port);
@@ -2214,7 +2352,9 @@ static void tc_attached_src_entry(const int port)
USB_SWITCH_DISCONNECT, tc[port].polarity);
}
- tc[port].polarity = (tc[port].cc1 != TYPEC_CC_VOLT_RD);
+ /* Get connector orientation */
+ tcpm_get_cc(port, &cc1, &cc2);
+ tc[port].polarity = (cc1 != TYPEC_CC_VOLT_RD);
set_polarity(port, tc[port].polarity);
/*
@@ -2227,6 +2367,42 @@ static void tc_attached_src_entry(const int port)
tc[port].timeout = get_time().val +
MAX(PD_POWER_SUPPLY_TURN_ON_DELAY, PD_T_VCONN_STABLE);
}
+#else
+ /* Get connector orientation */
+ tcpm_get_cc(port, &cc1, &cc2);
+ tc[port].polarity = (cc1 != TYPEC_CC_VOLT_RD);
+ set_polarity(port, tc[port].polarity);
+
+ /*
+ * Initial data role for sink is DFP
+ * This also sets the usb mux
+ */
+ tc_set_data_role(port, PD_ROLE_DFP);
+
+ /*
+ * Start sourcing Vconn before Vbus to ensure
+ * we are within USB Type-C Spec 1.4 tVconnON
+ */
+ if (IS_ENABLED(CONFIG_USBC_VCONN))
+ set_vconn(port, 1);
+
+ /* Enable VBUS */
+ if (pd_set_power_supply_ready(port)) {
+ /* Stop sourcing Vconn if Vbus failed */
+ if (IS_ENABLED(CONFIG_USBC_VCONN))
+ set_vconn(port, 0);
+
+ if (IS_ENABLED(CONFIG_USBC_SS_MUX))
+ usb_mux_set(port, TYPEC_MUX_NONE,
+ USB_SWITCH_DISCONNECT, tc[port].polarity);
+ }
+#endif /* CONFIG_USB_PE_SM */
+
+ /* Apply Rp */
+ tcpm_set_cc(port, TYPEC_CC_RP);
+
+ tc[port].cc_debounce = 0;
+ tc[port].cc_state = PD_CC_NONE;
/* Inform PPC that a sink is connected. */
if (IS_ENABLED(CONFIG_USBC_PPC))
@@ -2235,9 +2411,14 @@ static void tc_attached_src_entry(const int port)
static void tc_attached_src_run(const int port)
{
+ enum tcpc_cc_voltage_status cc1, cc2;
+ enum pd_cc_states new_cc_state;
+
#ifdef CONFIG_USB_PE_SM
/* Enable PD communications after power supply has fully turned on */
- if (tc[port].pd_enable == 0 && get_time().val > tc[port].timeout) {
+ if (tc[port].pd_enable == 0 &&
+ get_time().val > tc[port].timeout) {
+
tc[port].pd_enable = 1;
tc[port].timeout = 0;
}
@@ -2299,6 +2480,26 @@ static void tc_attached_src_run(const int port)
}
#endif
+ /* Check for connection */
+ tcpm_get_cc(port, &cc1, &cc2);
+
+ if (tc[port].polarity)
+ cc1 = cc2;
+
+ if (cc1 == TYPEC_CC_VOLT_OPEN)
+ new_cc_state = PD_CC_NONE;
+ else
+ new_cc_state = PD_CC_UFP_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_SRC_DISCONNECT;
+ }
+
+ if (get_time().val < tc[port].cc_debounce)
+ return;
+
/*
* When the SRC.Open state is detected on the monitored CC pin, a DRP
* shall transition to Unattached.SNK unless it strongly prefers the
@@ -2320,7 +2521,6 @@ static void tc_attached_src_run(const int port)
tc[port].pd_enable = 0;
set_state_tc(port, IS_ENABLED(CONFIG_USB_PD_TRY_SRC) ?
TC_TRY_WAIT_SNK : TC_UNATTACHED_SNK);
- return;
}
#ifdef CONFIG_USB_PE_SM
@@ -2332,9 +2532,8 @@ static void tc_attached_src_run(const int port)
* Power Role Swap Request
*/
if (TC_CHK_FLAG(port, TC_FLAGS_DO_PR_SWAP)) {
- /* Clear PR_SWAP flag in exit */
- set_state_tc(port, TC_ATTACHED_SNK);
- return;
+ TC_CLR_FLAG(port, TC_FLAGS_DO_PR_SWAP);
+ return set_state_tc(port, TC_ATTACHED_SNK);
}
/*
@@ -2425,31 +2624,53 @@ static void tc_try_src_entry(const int port)
{
print_current_state(port);
+ tc[port].cc_state = PD_CC_UNSET;
+ tc[port].try_wait_debounce = get_time().val + PD_T_DRP_TRY;
tc[port].timeout = get_time().val + PD_T_TRY_TIMEOUT;
}
static void tc_try_src_run(const int port)
{
- const uint64_t now = get_time().val;
+ enum tcpc_cc_voltage_status cc1, cc2;
+ enum pd_cc_states new_cc_state;
+
+ /* Check for connection */
+ tcpm_get_cc(port, &cc1, &cc2);
+
+ if ((cc1 == TYPEC_CC_VOLT_RD && cc2 != TYPEC_CC_VOLT_RD) ||
+ (cc1 != TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD))
+ new_cc_state = PD_CC_UFP_ATTACHED;
+ else
+ new_cc_state = PD_CC_NONE;
+
+ /* 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;
+ }
/*
* The port shall transition to Attached.SRC when the SRC.Rd state is
* detected on exactly one of the CC1 or CC2 pins for at least
* tTryCCDebounce.
*/
- if (now > tc[port].cc_last_change + PD_T_TRY_CC_DEBOUNCE &&
- tc[port].cc_state == PD_CC_UFP_ATTACHED)
- set_state_tc(port, TC_ATTACHED_SRC);
+ if (get_time().val > tc[port].cc_debounce) {
+ if (new_cc_state == PD_CC_UFP_ATTACHED)
+ set_state_tc(port, TC_ATTACHED_SRC);
+ }
+
/*
* The port shall transition to TryWait.SNK after tDRPTry and the
* SRC.Rd state has not been detected and VBUS is within vSafe0V,
* or after tTryTimeout and the SRC.Rd state has not been detected.
*/
- else if (now > tc[port].cc_last_change + PD_T_DRP_TRY &&
- !pd_is_vbus_present(port))
- set_state_tc(port, TC_TRY_WAIT_SNK);
- else if (now > tc[port].timeout)
- set_state_tc(port, TC_TRY_WAIT_SNK);
+ if (new_cc_state == PD_CC_NONE) {
+ if ((get_time().val > tc[port].try_wait_debounce &&
+ !pd_is_vbus_present(port)) ||
+ get_time().val > tc[port].timeout) {
+ set_state_tc(port, TC_TRY_WAIT_SNK);
+ }
+ }
}
/**
@@ -2463,26 +2684,48 @@ static void tc_try_src_run(const int port)
static void tc_try_wait_snk_entry(const int port)
{
print_current_state(port);
+
+ tc[port].cc_state = PD_CC_UNSET;
+ tc[port].try_wait_debounce = get_time().val + PD_T_CC_DEBOUNCE;
}
static void tc_try_wait_snk_run(const int port)
{
- const uint64_t now = get_time().val;
+ enum tcpc_cc_voltage_status cc1, cc2;
+ enum pd_cc_states new_cc_state;
+
+ /* Check for connection */
+ tcpm_get_cc(port, &cc1, &cc2);
+
+ /* We only care about CCs being open */
+ if (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN)
+ new_cc_state = PD_CC_NONE;
+ else
+ new_cc_state = PD_CC_UNSET;
+
+ /* Debounce the cc state */
+ if (new_cc_state != tc[port].cc_state) {
+ tc[port].cc_state = new_cc_state;
+ tc[port].pd_debounce = get_time().val + PD_T_PD_DEBOUNCE;
+ }
- /*
- * The port shall transition to Attached.SNK after tCCDebounce if or
- * when VBUS is detected.
- */
- if (now > tc[port].cc_last_change + PD_T_CC_DEBOUNCE &&
- pd_is_vbus_present(port))
- set_state_tc(port, TC_ATTACHED_SNK);
/*
* The port shall transition to Unattached.SNK when the state of both
* of the CC1 and CC2 pins is SNK.Open for at least tPDDebounce.
*/
- else if (now > tc[port].cc_last_change + PD_T_PD_DEBOUNCE &&
- tc[port].cc_state == PD_CC_NONE)
+ if ((get_time().val > tc[port].pd_debounce) &&
+ (new_cc_state == PD_CC_NONE)) {
set_state_tc(port, TC_UNATTACHED_SNK);
+ return;
+ }
+
+ /*
+ * The port shall transition to Attached.SNK after tCCDebounce if or
+ * when VBUS is detected.
+ */
+ if (get_time().val > tc[port].try_wait_debounce &&
+ pd_is_vbus_present(port))
+ set_state_tc(port, TC_ATTACHED_SNK);
}
#endif
@@ -2497,11 +2740,11 @@ static void tc_ct_unattached_snk_entry(int port)
/*
* Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rd. Reset last cc change time.
+ * ground through Rd.
*/
tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP);
tcpm_set_cc(port, TYPEC_CC_RD);
- tc[port].cc_last_change = get_time().val;
+ tc[port].cc_state = PD_CC_UNSET;
/* Set power role to sink */
tc_set_power_role(port, PD_ROLE_SINK);
@@ -2518,6 +2761,10 @@ static void tc_ct_unattached_snk_entry(int port)
static void tc_ct_unattached_snk_run(int port)
{
+ enum tcpc_cc_voltage_status cc1;
+ enum tcpc_cc_voltage_status cc2;
+ enum pd_cc_states new_cc_state;
+
if (tc[port].timeout > 0 && get_time().val > tc[port].timeout) {
tc[port].pd_enable = 1;
tc[port].timeout = 0;
@@ -2540,22 +2787,40 @@ static void tc_ct_unattached_snk_run(int port)
pe_ps_reset_complete(port);
}
- /*
- * The port shall transition to CTAttached.SNK when VBUS is detected.
- */
- if (pd_is_vbus_present(port)) {
- set_state_tc(port, TC_CT_ATTACHED_SNK);
+ /* Check for connection */
+ tcpm_get_cc(port, &cc1, &cc2);
+
+ /* We only care about CCs being open */
+ if (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN)
+ new_cc_state = PD_CC_NONE;
+ else
+ new_cc_state = PD_CC_UNSET;
+
+ /* 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_VPDDETACH;
+ }
+
/*
* The port shall transition to Unattached.SNK if the state of
* the CC pin is SNK.Open for tVPDDetach after VBUS is vSafe0V.
*/
- } else if (get_time().val > tc[port].cc_last_change + PD_T_VPDDETACH &&
- tc[port].cc_state == PD_CC_NONE) {
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- pd_dfp_exit_mode(port, 0, 0);
+ if (get_time().val > tc[port].cc_debounce) {
+ if (new_cc_state == PD_CC_NONE && !pd_is_vbus_present(port)) {
+ if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
+ pd_dfp_exit_mode(port, 0, 0);
- set_state_tc(port, TC_UNATTACHED_SNK);
+ set_state_tc(port, TC_UNATTACHED_SNK);
+ return;
+ }
}
+
+ /*
+ * The port shall transition to CTAttached.SNK when VBUS is detected.
+ */
+ if (pd_is_vbus_present(port))
+ set_state_tc(port, TC_CT_ATTACHED_SNK);
}
/**
@@ -2610,6 +2875,48 @@ static void tc_ct_attached_snk_exit(int port)
#endif /* CONFIG_USB_PE_SM */
/**
+ * Super State CC_RD
+ */
+static void tc_cc_rd_entry(const int port)
+{
+ /* Disable VCONN */
+ if (IS_ENABLED(CONFIG_USBC_VCONN))
+ set_vconn(port, 0);
+
+ /*
+ * Both CC1 and CC2 pins shall be independently terminated to
+ * ground through Rd.
+ */
+ tcpm_set_cc(port, TYPEC_CC_RD);
+
+ /* Set power role to sink */
+ tc_set_power_role(port, PD_ROLE_SINK);
+ tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
+}
+
+
+/**
+ * Super State CC_RP
+ */
+static void tc_cc_rp_entry(const int port)
+{
+ /* Disable VCONN */
+ if (IS_ENABLED(CONFIG_USBC_VCONN))
+ set_vconn(port, 0);
+
+ /* Set power role to source */
+ tc_set_power_role(port, PD_ROLE_SOURCE);
+ tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
+
+ /*
+ * Both CC1 and CC2 pins shall be independently pulled
+ * up through Rp.
+ */
+ tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP);
+ tcpm_set_cc(port, TYPEC_CC_RP);
+}
+
+/**
* Super State CC_OPEN
*/
static void tc_cc_open_entry(const int port)
@@ -2636,38 +2943,6 @@ static void tc_cc_open_entry(const int port)
}
}
-/**
- * Super State CC_RD
- */
-static void tc_cc_rd_entry(const int port)
-{
- set_rd(port);
-}
-
-/**
- * Super State CC_RP
- */
-static void tc_cc_rp_entry(const int port)
-{
- set_rp(port);
-}
-
-/**
- * Super State Unattached
- *
- * Ensures that any time we unattached we can perform an action without
- * repeating it during DRP toggle
- */
-static void tc_unattached_entry(const int port)
-{
- /* This only prints the first time we enter a unattached state */
- print_current_state(port);
-
- /* This disables the mux when we disconnect on a port */
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- set_usb_mux_with_current_data_role(port);
-}
-
void tc_run(const int port)
{
run_state(port, &tc[port].ctx);
@@ -2704,7 +2979,6 @@ int pd_is_debug_acc(int port)
* | TC_ATTACH_WAIT_SNK | | TC_ATTACH_WAIT_SRC |
* | TC_TRY_WAIT_SNK | | TC_TRY_SRC |
* | TC_DBG_ACC_SNK | | TC_UNORIENTED_DBG_ACC_SRC |
- * | TC_ATTACHED_SNK | | TC_ATTACHED_SRC |
* |-----------------------| |---------------------------------|
*
* |TC_CC_OPEN -----------|
@@ -2713,6 +2987,8 @@ int pd_is_debug_acc(int port)
* | TC_ERROR_RECOVERY |
* |----------------------|
*
+ * TC_ATTACHED_SNK TC_ATTACHED_SRC
+ *
*/
static const struct usb_state tc_states[] = {
/* Super States */
@@ -2725,9 +3001,6 @@ static const struct usb_state tc_states[] = {
[TC_CC_RP] = {
.entry = tc_cc_rp_entry,
},
- [TC_UNATTACHED] = {
- .entry = tc_unattached_entry,
- },
/* Normal States */
[TC_DISABLED] = {
.entry = tc_disabled_entry,
@@ -2743,7 +3016,7 @@ static const struct usb_state tc_states[] = {
[TC_UNATTACHED_SNK] = {
.entry = tc_unattached_snk_entry,
.run = tc_unattached_snk_run,
- .parent = &tc_states[TC_UNATTACHED],
+ .parent = &tc_states[TC_CC_RD],
},
[TC_ATTACH_WAIT_SNK] = {
.entry = tc_attach_wait_snk_entry,
@@ -2754,7 +3027,6 @@ static const struct usb_state tc_states[] = {
.entry = tc_attached_snk_entry,
.run = tc_attached_snk_run,
.exit = tc_attached_snk_exit,
- .parent = &tc_states[TC_CC_RD],
},
[TC_UNORIENTED_DBG_ACC_SRC] = {
.entry = tc_unoriented_dbg_acc_src_entry,
@@ -2769,7 +3041,7 @@ static const struct usb_state tc_states[] = {
[TC_UNATTACHED_SRC] = {
.entry = tc_unattached_src_entry,
.run = tc_unattached_src_run,
- .parent = &tc_states[TC_UNATTACHED],
+ .parent = &tc_states[TC_CC_RP],
},
[TC_ATTACH_WAIT_SRC] = {
.entry = tc_attach_wait_src_entry,
@@ -2780,7 +3052,6 @@ static const struct usb_state tc_states[] = {
.entry = tc_attached_src_entry,
.run = tc_attached_src_run,
.exit = tc_attached_src_exit,
- .parent = &tc_states[TC_CC_RP],
},
#ifdef CONFIG_USB_PD_TRY_SRC
[TC_TRY_SRC] = {