diff options
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 17 | ||||
-rw-r--r-- | common/usbc/usb_tc_drp_acc_trysrc_sm.c | 147 | ||||
-rw-r--r-- | include/usb_tc_sm.h | 10 | ||||
-rw-r--r-- | test/fake_usbc.c | 3 |
4 files changed, 88 insertions, 89 deletions
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index 1bc1eeeb60..5a7f008963 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -2183,12 +2183,6 @@ static void pe_src_transition_to_default_run(int port) } } -static void pe_src_transition_to_default_exit(int port) -{ - /* TC layer can now go unattached */ - tc_hard_reset_allow_unattach(port); -} - /** * PE_SNK_Startup State */ @@ -2338,16 +2332,6 @@ static void pe_snk_evaluate_capability_entry(int port) /* Reset Hard Reset counter to zero */ pe[port].hard_reset_counter = 0; - /* - * If we were in a Hard Reset condition we have to delay until - * now to let the TC know we are back to a stable connection. - * Up to this point we have sent the reset and there is no - * conversation from the other side until we receive the - * capabilities message - * TC layer can now go unattached - */ - tc_hard_reset_allow_unattach(port); - /* Set to highest revision supported by both ports. */ prl_set_rev(port, TCPC_TX_SOP, MIN(PD_REVISION, PD_HEADER_REV(rx_emsg[port].header))); @@ -5634,7 +5618,6 @@ static const struct usb_state pe_states[] = { [PE_SRC_TRANSITION_TO_DEFAULT] = { .entry = pe_src_transition_to_default_entry, .run = pe_src_transition_to_default_run, - .exit = pe_src_transition_to_default_exit, }, [PE_SNK_STARTUP] = { .entry = pe_snk_startup_entry, diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c index bf918ffdde..51207a9acb 100644 --- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c +++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c @@ -86,29 +86,24 @@ #define TC_FLAGS_PARTNER_PD_CAPABLE BIT(15) /* Flag to note hard reset has been requested */ #define TC_FLAGS_HARD_RESET_REQUESTED BIT(16) -/* - * Flag to note hard reset has been performed and we can't go to unattached - * until we have a source-sink connection again - */ -#define TC_FLAGS_HARD_RESET_NO_UNATTACH BIT(17) /* Flag to note port partner is USB comms capable */ -#define TC_FLAGS_PARTNER_USB_COMM BIT(18) +#define TC_FLAGS_PARTNER_USB_COMM BIT(17) /* Flag to note we are currently performing PR Swap */ -#define TC_FLAGS_PR_SWAP_IN_PROGRESS BIT(19) +#define TC_FLAGS_PR_SWAP_IN_PROGRESS BIT(18) /* Flag to note we need to perform PR Swap */ -#define TC_FLAGS_DO_PR_SWAP BIT(20) +#define TC_FLAGS_DO_PR_SWAP BIT(19) /* Flag to note we are performing Discover Identity */ -#define TC_FLAGS_DISC_IDENT_IN_PROGRESS BIT(21) +#define TC_FLAGS_DISC_IDENT_IN_PROGRESS BIT(20) /* Flag to note we should check for connection */ -#define TC_FLAGS_CHECK_CONNECTION BIT(22) +#define TC_FLAGS_CHECK_CONNECTION BIT(21) /* Flag to note pd_set_suspend SUSPEND state */ -#define TC_FLAGS_SUSPEND BIT(23) +#define TC_FLAGS_SUSPEND BIT(22) /* * 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(24) +#define TC_FLAGS_TC_WARM_ATTACHED_SNK BIT(23) /* * Clear all flags except TC_FLAGS_LPM_ENGAGED and TC_FLAGS_SUSPEND. @@ -136,7 +131,6 @@ enum ps_reset_sequence { PS_STATE0, PS_STATE1, PS_STATE2, - PS_STATE3 }; /* List of all TypeC-level states */ @@ -704,21 +698,6 @@ void tc_hard_reset_request(int port) task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0); } -/* - * Hard Reset happened and this is how the PE will unblock leaving - * the attached state. - */ -void tc_hard_reset_allow_unattach(int port) -{ - /* Only deal with HardReset if we are currently doing HardReset */ - if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH)) { - TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH); - - /* Enable AutoDischargeDisconnect */ - tcpm_enable_auto_discharge_disconnect(port, 1); - } -} - void tc_disc_ident_in_progress(int port) { TC_SET_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS); @@ -949,15 +928,17 @@ static bool tc_perform_src_hard_reset(int port) /* Turn off VCONN */ set_vconn(port, 1); - tc[port].ps_reset_state = PS_STATE3; + tc[port].ps_reset_state = PS_STATE2; tc[port].timeout = get_time().val + PD_POWER_SUPPLY_TURN_ON_DELAY; return false; case PS_STATE2: - case PS_STATE3: /* Tell Policy Engine Hard Reset is complete */ pe_ps_reset_complete(port); + /* Enable AutoDischargeDisconnect */ + tcpm_enable_auto_discharge_disconnect(port, 1); + tc[port].ps_reset_state = PS_STATE0; return true; } @@ -969,31 +950,69 @@ static bool tc_perform_src_hard_reset(int port) */ return true; } -#endif -static void tc_perform_snk_hard_reset(int port) +/* + * Wait for recovery after a hard reset. Call repeatedly until true is + * returned, signaling that the hard reset is complete. + */ +static bool tc_perform_snk_hard_reset(int port) { - tc_set_data_role(port, PD_ROLE_UFP); + switch (tc[port].ps_reset_state) { + case PS_STATE0: + /* Hard reset sets us back to default data role */ + tc_set_data_role(port, PD_ROLE_UFP); - /* Clear the input current limit */ - sink_stop_drawing_current(port); + /* Clear the input current limit */ + sink_stop_drawing_current(port); - /* - * When VCONN is supported, the Hard Reset Shall cause - * the Port with the Rd resistor asserted to turn off - * VCONN. - */ + /* + * When VCONN is supported, the Hard Reset Shall cause + * the Port with the Rd resistor asserted to turn off + * VCONN. + */ #ifdef CONFIG_USBC_VCONN - if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON)) - set_vconn(port, 0); + if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON)) + set_vconn(port, 0); #endif + /* Wait tSafe0V + tSrcRecover, then check for Vbus presence */ + tc[port].ps_reset_state = PS_STATE1; + tc[port].timeout = get_time().val + PD_T_SAFE_0V + + PD_T_SRC_RECOVER_MAX; + return false; + case PS_STATE1: + if (get_time().val < tc[port].timeout) + return false; - /* - * Inform policy engine that power supply - * reset is complete - */ - pe_ps_reset_complete(port); + /* Watch for Vbus to return */ + tc[port].ps_reset_state = PS_STATE2; + tc[port].timeout = get_time().val + PD_T_SRC_TURN_ON; + return false; + case PS_STATE2: + if (pd_is_vbus_present(port)) { + /* + * Inform policy engine that power supply + * reset is complete + */ + tc[port].ps_reset_state = PS_STATE0; + pe_ps_reset_complete(port); + + /* Enable AutoDischargeDisconnect */ + tcpm_enable_auto_discharge_disconnect(port, 1); + return true; + } + /* + * If Vbus isn't back after wait + tSrcTurnOn, go unattached + */ + if (get_time().val > tc[port].timeout) { + tc[port].ps_reset_state = PS_STATE0; + set_state_tc(port, TC_UNATTACHED_SNK); + return true; + } + } + + return false; } +#endif /* CONFIG_USB_PE_SM */ void tc_start_error_recovery(int port) { @@ -1935,20 +1954,23 @@ static void tc_attached_snk_run(const int port) * Perform Hard Reset */ if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) { - TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED); - TC_SET_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH); - tc_perform_snk_hard_reset(port); + /* + * Wait to clear the hard reset request until Vbus has returned + * to default (or, if it didn't return, we transition to + * unattached) + */ + if (tc_perform_snk_hard_reset(port)) + TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED); + + return; } /* * The sink will be powered off during a power role swap but we don't * want to trigger a disconnect. - * If we are working on a Hard Reset we have to remain attached - * even when vbus drops. */ if (!TC_CHK_FLAG(port, TC_FLAGS_POWER_OFF_SNK) && - !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS) && - !TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH)) { + !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) { /* Detach detection */ if (!pd_is_vbus_present(port)) { if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) @@ -2311,14 +2333,22 @@ static void tc_dbg_acc_snk_run(const int port) return; } +#ifdef CONFIG_USB_PE_SM /* * Perform Hard Reset */ if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) { - TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED); - TC_SET_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH); - tc_perform_snk_hard_reset(port); + /* + * Wait to clear the hard reset request until Vbus has returned + * to default (or, if it didn't return, we transition to + * unattached) + */ + if (tc_perform_snk_hard_reset(port)) + TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED); + + return; } +#endif /* * The sink will be powered off during a power role swap but we @@ -2327,8 +2357,7 @@ static void tc_dbg_acc_snk_run(const int port) * even when vbus drops. */ if (!TC_CHK_FLAG(port, TC_FLAGS_POWER_OFF_SNK) && - !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS) && - !TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH)) { + !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) { /* Detach detection */ if (!pd_is_vbus_present(port)) { if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) diff --git a/include/usb_tc_sm.h b/include/usb_tc_sm.h index b6ed917d4d..293ed55a10 100644 --- a/include/usb_tc_sm.h +++ b/include/usb_tc_sm.h @@ -322,16 +322,6 @@ void tc_start_error_recovery(int port); void tc_hard_reset_request(int port); /** - * Hard Reset was sent and we are required to remain attached until we have - * restored our connection for the TypeC port. - * A call to tc_hard_reset_allow_unattach will allow the connection to go - * to an unattached state - * - * @param port USB-C port number - */ -void tc_hard_reset_allow_unattach(int port); - -/** * Hard Reset is complete for the TypeC port * * @param port USB-C port number diff --git a/test/fake_usbc.c b/test/fake_usbc.c index 731e15c3de..13a1945a0a 100644 --- a/test/fake_usbc.c +++ b/test/fake_usbc.c @@ -87,9 +87,6 @@ int tc_is_vconn_src(int port) void tc_hard_reset_request(int port) {} -void tc_hard_reset_allow_unattach(int port) -{} - void tc_hard_reset_complete(int port) {} |