diff options
author | Jett Rink <jettrink@chromium.org> | 2020-06-29 13:14:43 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-07-10 22:21:58 +0000 |
commit | 23ea3fbd4a6e52b8a54f4278bbed8975af34cca7 (patch) | |
tree | 84b8b0ee67f7fdbb9d9ad44695ed7659439c7c06 | |
parent | 0f713b36be38449cddea2196d1a135d7bdcfb82a (diff) | |
download | chrome-ec-23ea3fbd4a6e52b8a54f4278bbed8975af34cca7.tar.gz |
tcpmv2: perform partner reset on startup, remove BBRAM
- Reset the port partner by applying CC Open on both CC lines
- Reuse the existing error recovery state to apply CC values
- Extend error recovery timer to 240 msec to account for us being able
to source Vconn
- Since we always reset on startup, we don't need to store previous
contracts in BBRAM.
BRANCH=none
BUG=b:159495742,b:158802939
TEST=see that we apply CC Open upon reset
TEST=see that we do not get a fault on Trembyle went setting CC open
TEST=apple 3-1 dongle with display port and power on Puff will come back
with power and display after a `reboot` EC command (which will trigger
the ErrorRecovery brownout path)
Signed-off-by: Jett Rink <jettrink@chromium.org>
Change-Id: Iaac09d62e4a31557492cebb354d3a34371c1e9bb
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2271002
Reviewed-by: Denis Brockus <dbrockus@chromium.org>
Reviewed-by: Diana Z <dzigterman@chromium.org>
-rw-r--r-- | board/puff/board.c | 3 | ||||
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 41 | ||||
-rw-r--r-- | common/usbc/usb_tc_drp_acc_trysrc_sm.c | 203 | ||||
-rw-r--r-- | common/usbc/usbc_task.c | 12 | ||||
-rw-r--r-- | include/config.h | 5 | ||||
-rw-r--r-- | include/usb_pd.h | 2 | ||||
-rw-r--r-- | include/usb_pe_sm.h | 5 | ||||
-rw-r--r-- | test/usb_typec_drp_acc_trysrc.c | 63 |
8 files changed, 163 insertions, 171 deletions
diff --git a/board/puff/board.c b/board/puff/board.c index 397d62daf3..c59ce541ad 100644 --- a/board/puff/board.c +++ b/board/puff/board.c @@ -567,9 +567,6 @@ void board_reset_pd_mcu(void) gpio_set_level(GPIO_USB_C0_TCPC_RST, !level); if (BOARD_TCPC_C0_RESET_POST_DELAY) msleep(BOARD_TCPC_C0_RESET_POST_DELAY); - /* Reset any saved state for previous connections. */ - pd_update_saved_port_flags(USB_PD_PORT_TCPC_0, - PD_BBRMFLG_EXPLICIT_CONTRACT, 0); } int board_set_active_charge_port(int port) diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index 9221002c40..a4a30c8f92 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -189,9 +189,6 @@ */ typedef int (*svdm_rsp_func)(int port, uint32_t *payload); -/* This is true only if a sysjump has occurred */ -static bool sysjump_occurred; - /* List of all Policy Engine level states */ enum usb_pe_state { /* Normal States */ @@ -766,11 +763,6 @@ void pe_run(int port, int evt, int en) } } -void pe_set_sysjump(void) -{ - sysjump_occurred = true; -} - int pe_is_explicit_contract(int port) { return PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT); @@ -860,7 +852,6 @@ static void pe_set_frs_enable(int port, int enable) void pe_set_explicit_contract(int port) { PE_SET_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT); - pd_update_saved_port_flags(port, PD_BBRMFLG_EXPLICIT_CONTRACT, 1); /* Set Rp for collision avoidance */ if (IS_ENABLED(CONFIG_USB_PD_REV30)) @@ -873,7 +864,6 @@ void pe_invalidate_explicit_contract(int port) pe_set_frs_enable(port, 0); PE_CLR_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT); - pd_update_saved_port_flags(port, PD_BBRMFLG_EXPLICIT_CONTRACT, 0); /* Set Rp for current limit */ if (IS_ENABLED(CONFIG_USB_PD_REV30)) @@ -2331,14 +2321,8 @@ static void pe_snk_startup_entry(int port) /* Set initial power role */ pe[port].power_role = PD_ROLE_SINK; - /* - * An explicit contract must be maintained across sysjumps, - * so do not invalidate it if a sysjump has occurred - */ - if (!sysjump_occurred) { - /* Invalidate explicit contract */ - pe_invalidate_explicit_contract(port); - } + /* Invalidate explicit contract */ + pe_invalidate_explicit_contract(port); if (PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)) { PE_CLR_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE); @@ -2372,22 +2356,11 @@ static void pe_snk_startup_run(int port) if (!prl_is_running(port)) return; - /* Soft reset the charger on sysjump */ - if (sysjump_occurred) { - /* - * The sysjump flag is no longer needed, so clear it. - * After Soft Reset is sent, PE_ATTACHED_SNK state - * is entered. - */ - sysjump_occurred = false; - pe_send_soft_reset(port, TCPC_TX_SOP); - } else { - /* - * Once the reset process completes, the Policy Engine Shall - * transition to the PE_SNK_Discovery state - */ - set_state_pe(port, PE_SNK_DISCOVERY); - } + /* + * Once the reset process completes, the Policy Engine Shall + * transition to the PE_SNK_Discovery state + */ + set_state_pe(port, PE_SNK_DISCOVERY); } /** diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c index 79fe431dbb..467b5c3f3e 100644 --- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c +++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c @@ -19,6 +19,7 @@ #include "usb_sm.h" #include "usb_tc_sm.h" #include "usbc_ppc.h" +#include "vboot.h" /* * USB Type-C DRP with Accessory and Try.SRC module @@ -115,12 +116,6 @@ #define TC_FLAGS_CHECK_CONNECTION BIT(20) /* Flag to note pd_set_suspend SUSPEND state */ #define TC_FLAGS_SUSPEND BIT(21) -/* - * Flag to note TC_ATTACHED_SNK is coming from a warm start through - * tc_state_init and the default data role should not be changed from - * what is currently set - */ -#define TC_FLAGS_TC_WARM_ATTACHED_SNK BIT(22) /* * Clear all flags except TC_FLAGS_LPM_ENGAGED and TC_FLAGS_SUSPEND. @@ -421,8 +416,6 @@ 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}; -static uint8_t saved_flgs[CONFIG_USB_PD_PORT_MAX_COUNT]; - static void set_vconn(int port, int enable); /* Forward declare common, private functions */ @@ -559,12 +552,20 @@ void tc_request_power_swap(int port) } } +static bool pd_comm_allowed_by_policy(void) +{ + return IS_ENABLED(CONFIG_SYSTEM_UNLOCKED) || system_is_in_rw() || + vboot_allow_usb_pd(); +} + static void tc_policy_pd_enable(int port, int en) { if (en) atomic_clear(&tc[port].pd_disabled_mask, PD_DISABLED_BY_POLICY); else atomic_or(&tc[port].pd_disabled_mask, PD_DISABLED_BY_POLICY); + + CPRINTS("C%d: PD comm policy %sabled", port, en ? "en" : "dis"); } static void tc_enable_pd(int port, int en) @@ -592,7 +593,6 @@ static void tc_detached(int port) hook_notify(HOOK_USB_PD_DISCONNECT); tc_pd_connection(port, 0); tcpm_debug_accessory(port, 0); - pd_update_saved_port_flags(port, PD_BBRMFLG_DBGACC_ROLE, 0); } static inline void pd_set_dual_role_and_event(int port, @@ -1229,8 +1229,9 @@ static bool tc_perform_snk_hard_reset(int port) void tc_start_error_recovery(int port) { + assert(port == TASK_ID_TO_PD_PORT(task_get_current())); + /* - * Async. function call: * The port should transition to the ErrorRecovery state * from any other state when directed. */ @@ -1239,12 +1240,21 @@ void tc_start_error_recovery(int port) static void restart_tc_sm(int port, enum usb_tc_state start_state) { - int res = 0; + int res; + + /* Clear flags before we transitions states */ + tc[port].flags = 0; res = tcpm_init(port); CPRINTS("C%d: TCPC init %s", port, res ? "failed" : "ready"); + /* + * Update the Rp Value. We don't need to update CC lines though as that + * happens in below set_state transition. + */ + typec_select_src_current_limit_rp(port, CONFIG_USB_PD_PULLUP); + /* Disable if restart failed, otherwise start in default state. */ set_state_tc(port, res ? TC_DISABLED : start_state); @@ -1252,9 +1262,16 @@ static void restart_tc_sm(int port, enum usb_tc_state start_state) /* Initialize USB mux to its default state */ usb_mux_init(port); - /* Update the Rp Value */ - typec_select_src_current_limit_rp(port, CONFIG_USB_PD_PULLUP); - typec_update_cc(port); + if (IS_ENABLED(CONFIG_USBC_PPC)) { + /* + * Wait to initialize the PPC after tcpc, which sets + * the correct Rd values; otherwise the TCPC might + * not be pulling the CC lines down when the PPC connects the + * CC lines from the USB connector to the TCPC cause the source + * to drop Vbus causing a brown out. + */ + ppc_init(port); + } if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { /* Initialize PD and type-C supplier current limits to 0 */ @@ -1263,8 +1280,6 @@ static void restart_tc_sm(int port, enum usb_tc_state start_state) charge_manager_update_dualrole(port, CAP_UNKNOWN); } - tc[port].flags = 0; - #ifdef CONFIG_USB_PE_SM tc_enable_pd(port, 0); tc[port].ps_reset_state = PS_STATE0; @@ -1273,6 +1288,8 @@ static void restart_tc_sm(int port, enum usb_tc_state start_state) void tc_state_init(int port) { + enum usb_tc_state first_state; + /* For test builds, replicate static initialization */ if (IS_ENABLED(TEST_BUILD)) { int i; @@ -1288,82 +1305,16 @@ void tc_state_init(int port) tc_enable_pd(port, 0); tc_pause_event_loop(port); TC_SET_FLAG(port, TC_FLAGS_SUSPEND); - set_state_tc(port, TC_DISABLED); return; } - /* Default to not jumping warm to ATTACHED_SNK */ - TC_CLR_FLAG(port, TC_FLAGS_TC_WARM_ATTACHED_SNK); - - /* - * If there's an explicit contract in place, let's restore the data and - * power roles such that any messages we send to the port partner will - * still be valid. - */ - if (pd_comm_is_enabled(port) && - (pd_get_saved_port_flags(port, &saved_flgs[port]) == - EC_SUCCESS) && - (saved_flgs[port] & PD_BBRMFLG_EXPLICIT_CONTRACT)) { - /* Only attempt to maintain previous sink contracts */ - if ((saved_flgs[port] & PD_BBRMFLG_POWER_ROLE) == - PD_ROLE_SINK) { - tc[port].power_role = - (saved_flgs[port] & PD_BBRMFLG_POWER_ROLE) - ? PD_ROLE_SOURCE - : PD_ROLE_SINK; - tc[port].data_role = - (saved_flgs[port] & PD_BBRMFLG_DATA_ROLE) - ? PD_ROLE_DFP - : PD_ROLE_UFP; -#ifdef CONFIG_USBC_VCONN - set_vconn(port, - (saved_flgs[port] & PD_BBRMFLG_VCONN_ROLE) ? - PD_ROLE_VCONN_ON : PD_ROLE_VCONN_OFF); -#endif /* CONFIG_USBC_VCONN */ - if (IS_ENABLED(CONFIG_USB_PE_SM)) - pe_set_sysjump(); - - /* - * We are jumping warm to ATTACHED_SNK, so don't - * change the data role when we get to the state. - */ - TC_SET_FLAG(port, TC_FLAGS_TC_WARM_ATTACHED_SNK); - if (saved_flgs[port] & PD_BBRMFLG_DBGACC_ROLE) - TC_SET_FLAG(port, TC_FLAGS_TS_DTS_PARTNER); - set_state_tc(port, TC_ATTACHED_SNK); - } else { - restart_tc_sm(port, TC_UNATTACHED_SNK); - /* - * Vbus was turned off during the power supply reset - * earlier, so clear the contract flag and re-start as - * default role - */ - pd_update_saved_port_flags(port, - PD_BBRMFLG_EXPLICIT_CONTRACT, 0); - } - /* - * Set the TCPC reset event such that we can set our CC - * terminations, determine polarity, and enable RX so we - * can hear back from our port partner if maintaining our old - * connection. - */ - task_set_event(task_get_current(), PD_EVENT_TCPC_RESET, 0); - } else { - /* Unattached.SNK is the default starting state. */ - restart_tc_sm(port, TC_UNATTACHED_SNK); - - /* Disable VBUS; VBUS may be sourced before reboot */ - tc_src_power_off(port); - } - /* Allow system to set try src enable */ tc_try_src_override(TRY_SRC_NO_OVERRIDE); /* - * Allowing PD by policy and host or console commands - * can disable PD by policy later. + * Set initial PD communication policy. */ - tc_policy_pd_enable(port, 1); + tc_policy_pd_enable(port, pd_comm_allowed_by_policy()); /* Set dual-role state based on chipset power state */ if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) @@ -1372,6 +1323,23 @@ void tc_state_init(int port) pd_set_dual_role_and_event(port, PD_DRP_TOGGLE_OFF, 0); else /* CHIPSET_STATE_ON */ pd_set_dual_role_and_event(port, PD_DRP_TOGGLE_ON, 0); + + /* + * If we just lost power, don't apply CC open. Otherwise we would boot + * loop, and if this is a fresh power on, then we know there isn't any + * stale PD state as well. + */ + if (system_get_reset_flags() & + (EC_RESET_FLAG_BROWNOUT | EC_RESET_FLAG_POWER_ON)) + first_state = TC_UNATTACHED_SNK; + else + first_state = TC_ERROR_RECOVERY; + + /* + * Start with ErrorRecovery state if we can to put us in + * a clean state from any previous boots. + */ + restart_tc_sm(port, first_state); } enum pd_cable_plug tc_get_cable_plug(int port) @@ -1406,7 +1374,6 @@ bool pd_alt_mode_capable(int port) void tc_set_power_role(int port, enum pd_power_role role) { tc[port].power_role = role; - pd_update_saved_port_flags(port, PD_BBRMFLG_POWER_ROLE, role); } /* @@ -1508,8 +1475,6 @@ void tc_set_data_role(int port, enum pd_data_role role) { tc[port].data_role = role; - pd_update_saved_port_flags(port, PD_BBRMFLG_DATA_ROLE, role); - if (IS_ENABLED(CONFIG_USBC_SS_MUX)) set_usb_mux_with_current_data_role(port); @@ -1557,13 +1522,6 @@ static void set_vconn(int port, int enable) else TC_CLR_FLAG(port, TC_FLAGS_VCONN_ON); - pd_update_saved_port_flags(port, PD_BBRMFLG_VCONN_ROLE, enable); - - /* - * TODO(chromium:951681): When we are sourcing VCONN, we should make - * sure to remove our termination on that CC line first. - */ - /* * We always need to tell the TCPC to enable Vconn first, otherwise some * TCPCs get confused and think the CC line is in over voltage mode and @@ -1884,10 +1842,25 @@ static void tc_error_recovery_entry(const int port) static void tc_error_recovery_run(const int port) { - if (tc[port].timeout > 0 && get_time().val > tc[port].timeout) { - tc[port].timeout = 0; - restart_tc_sm(port, TC_UNATTACHED_SRC); + if (get_time().val < tc[port].timeout) + return; + + /* + * If we transitioned to error recovery as the first state and we + * didn't brown out, we don't need to reinitialized the tc statemachine + * because we just did that. So transition to the state directly. + */ + if (tc[port].ctx.previous == NULL) { + set_state_tc(port, TC_UNATTACHED_SNK); + return; } + + /* + * If try src support is active (e.g. in S0). Then try to become the + * SRC, otherwise we should try to be the sink. + */ + restart_tc_sm(port, is_try_src_enabled(port) ? TC_UNATTACHED_SRC : + TC_UNATTACHED_SNK); } /** @@ -2157,17 +2130,7 @@ static void tc_attached_snk_entry(const int port) tc[port].polarity = get_snk_polarity(cc1, cc2); pd_set_polarity(port, tc[port].polarity); - /* - * Initial data role for sink is UFP unless this is a warm - * attach. If it is a warm attach, the data role will be - * restored to the current connect role and will already - * have called tc_set_data_role with the appropriate role. - * This also sets the usb mux - */ - if (TC_CHK_FLAG(port, TC_FLAGS_TC_WARM_ATTACHED_SNK)) - TC_CLR_FLAG(port, TC_FLAGS_TC_WARM_ATTACHED_SNK); - else - tc_set_data_role(port, PD_ROLE_UFP); + tc_set_data_role(port, PD_ROLE_UFP); hook_notify(HOOK_USB_PD_CONNECT); @@ -2195,11 +2158,8 @@ static void tc_attached_snk_entry(const int port) if (IS_ENABLED(CONFIG_USB_PE_SM)) tc_enable_pd(port, 1); - if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) { + if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) tcpm_debug_accessory(port, 1); - /* Save our current connection is a DEBUG ACCESSORY */ - pd_update_saved_port_flags(port, PD_BBRMFLG_DBGACC_ROLE, 1); - } } static void tc_attached_snk_run(const int port) @@ -2680,11 +2640,8 @@ static void tc_attached_src_entry(const int port) hook_notify(HOOK_USB_PD_CONNECT); } - if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) { + if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) tcpm_debug_accessory(port, 1); - /* Save our current connection is a DEBUG ACCESSORY */ - pd_update_saved_port_flags(port, PD_BBRMFLG_DBGACC_ROLE, 1); - } } static void tc_attached_src_run(const int port) @@ -3309,10 +3266,24 @@ static void tc_cc_rp_entry(const int port) */ static void tc_cc_open_entry(const int port) { + /* Ensure we are not sourcing Vbus */ + tc_src_power_off(port); + /* Disable VCONN */ if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON)) set_vconn(port, 0); + /* + * Ensure we disable discharging before setting CC lines to open. + * If we were sourcing above, then we already drained Vbus. If partner + * is sourcing Vbus they will drain Vbus if they are PD-capable. + */ + tcpm_enable_auto_discharge_disconnect(port, 0); + + /* We may brown out after applying CC open, so flush console first. */ + CPRINTS("C%d: Applying CC Open!", port); + cflush(); + /* Remove terminations from CC */ typec_select_pull(port, TYPEC_CC_OPEN); typec_update_cc(port); diff --git a/common/usbc/usbc_task.c b/common/usbc/usbc_task.c index 7bd0cdddd8..5c14903619 100644 --- a/common/usbc/usbc_task.c +++ b/common/usbc/usbc_task.c @@ -157,18 +157,6 @@ test_only_restart: if (IS_ENABLED(CONFIG_USB_TYPEC_SM)) tc_state_init(port); - if (IS_ENABLED(CONFIG_USBC_PPC) && - port < board_get_usb_pd_port_count()) { - /* - * Wait to initialize the PPC after tc_state_init(), which sets - * the correct Rd values in the TCPC; otherwise the TCPC might - * not be pulling the CC lines down when the PPC connects the - * CC lines from the USB connector to the TCPC cause the source - * to drop Vbus causing a brown out. - */ - ppc_init(port); - } - /* * Since most boards configure the TCPC interrupt as edge * and it is possible that the interrupt line was asserted between init diff --git a/include/config.h b/include/config.h index 26c3bc608c..96b412703e 100644 --- a/include/config.h +++ b/include/config.h @@ -3340,6 +3340,8 @@ * * When defined, CBI allows ectool to reprogram all the fields. Once undefined, * it refuses to change certain fields. (e.g. board version, OEM ID) + * + * Also, this will enable PD in RO for TCPMv2. */ #undef CONFIG_SYSTEM_UNLOCKED @@ -3791,6 +3793,9 @@ * We don't want to allow communication to outside world until * we jump to RW. This can by overridden with the removal of * the write protect screw to allow for easier testing. + * + * Note: this is assumed for TCPMv2. See also CONFIG_BRINGUP for enabling PD in + * RO. */ #undef CONFIG_USB_PD_COMM_LOCKED diff --git a/include/usb_pd.h b/include/usb_pd.h index b2707f5f2b..24271db6f6 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -200,7 +200,7 @@ enum pd_rx_errors { #define PD_T_PS_SOURCE_ON (480*MSEC) /* between 390ms and 480ms */ #define PD_T_PS_SOURCE_OFF (920*MSEC) /* between 750ms and 920ms */ #define PD_T_PS_HARD_RESET (25*MSEC) /* between 25ms and 35ms */ -#define PD_T_ERROR_RECOVERY (25*MSEC) /* 25ms */ +#define PD_T_ERROR_RECOVERY (240*MSEC) /* min 240ms if sourcing VConn */ #define PD_T_CC_DEBOUNCE (100*MSEC) /* between 100ms and 200ms */ /* DRP_SNK + DRP_SRC must be between 50ms and 100ms with 30%-70% duty cycle */ #define PD_T_DRP_SNK (40*MSEC) /* toggle time for sink DRP */ diff --git a/include/usb_pe_sm.h b/include/usb_pe_sm.h index 2ad41991a2..78c1f27759 100644 --- a/include/usb_pe_sm.h +++ b/include/usb_pe_sm.h @@ -175,11 +175,6 @@ void pe_dpm_request(int port, enum pe_dpm_request req); int pd_is_port_partner_dualrole(int port); /* - * Informs the Policy Engine that a sysjump has occurred - */ -void pe_set_sysjump(void); - -/* * Informs the Policy Engine that it should invalidate the * explicit contract. * diff --git a/test/usb_typec_drp_acc_trysrc.c b/test/usb_typec_drp_acc_trysrc.c index fbaa8018aa..9c47bedbf0 100644 --- a/test/usb_typec_drp_acc_trysrc.c +++ b/test/usb_typec_drp_acc_trysrc.c @@ -7,6 +7,7 @@ #include "charge_manager.h" #include "mock/tcpc_mock.h" #include "mock/usb_mux_mock.h" +#include "system.h" #include "task.h" #include "test_util.h" #include "timer.h" @@ -600,6 +601,65 @@ __maybe_unused static int test_try_src_partner_does_not_switch_no_vbus(void) return EC_SUCCESS; } +/* Record the cc voltages */ +static enum tcpc_cc_pull cc_pull[16]; +static int cc_pull_count; +static int record_cc_pull(int port, int pull) +{ + if (cc_pull_count < ARRAY_SIZE(cc_pull)) + cc_pull[cc_pull_count++] = pull; + + return EC_SUCCESS; +}; + +__maybe_unused static int test_cc_open_on_normal_reset(void) +{ + uint32_t flags = system_get_reset_flags(); + + cc_pull_count = 0; + mock_tcpc.callbacks.set_cc = &record_cc_pull; + + system_clear_reset_flags(EC_RESET_FLAG_POWER_ON); + + task_set_event(TASK_ID_PD_C0, TASK_EVENT_RESET_DONE, 0); + task_wait_event(SECOND * 10); + + /* Ensure that the first CC set call was to open (error recovery). */ + TEST_GT(cc_pull_count, 0, "%d"); + TEST_EQ(cc_pull[0], TYPEC_CC_OPEN, "%d"); + + /* Ensure that the second CC set call was to Rd (sink) */ + TEST_GT(cc_pull_count, 1, "%d"); + TEST_EQ(cc_pull[1], TYPEC_CC_RD, "%d"); + + /* Reset system flags after test */ + system_set_reset_flags(flags); + + return EC_SUCCESS; +} + +__maybe_unused static int test_cc_rd_on_por_reset(void) +{ + uint32_t flags = system_get_reset_flags(); + + cc_pull_count = 0; + mock_tcpc.callbacks.set_cc = &record_cc_pull; + + system_set_reset_flags(EC_RESET_FLAG_POWER_ON); + + task_set_event(TASK_ID_PD_C0, TASK_EVENT_RESET_DONE, 0); + task_wait_event(SECOND * 10); + + /* Ensure that the first CC set call was to Rd (sink) */ + TEST_GT(cc_pull_count, 0, "%d"); + TEST_EQ(cc_pull[0], TYPEC_CC_RD, "%d"); + + /* Reset system flags after test */ + system_clear_reset_flags(~flags); + + return EC_SUCCESS; +} + /* TODO(b/153071799): test as SNK monitor for Vbus disconnect (not CC line) */ /* TODO(b/153071799): test as SRC monitor for CC line state change */ @@ -646,6 +706,9 @@ void run_test(int argc, char **argv) RUN_TEST(test_try_src_partner_does_not_switch_vbus); RUN_TEST(test_try_src_partner_does_not_switch_no_vbus); + RUN_TEST(test_cc_open_on_normal_reset); + RUN_TEST(test_cc_rd_on_por_reset); + /* Do basic state machine sanity checks last. */ RUN_TEST(test_tc_no_parent_cycles); RUN_TEST(test_tc_no_empty_state); |