summaryrefslogtreecommitdiff
path: root/common/usbc/usb_tc_drp_acc_trysrc_sm.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/usbc/usb_tc_drp_acc_trysrc_sm.c')
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
index 32dff84fa1..c8bf4f589a 100644
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
@@ -395,6 +395,11 @@ static struct type_c {
* the state definitions.
*/
uint64_t pd_debounce;
+ /*
+ * Time to ignore Vbus absence due to external IC debounce detection
+ * logic immediately after a power role swap.
+ */
+ uint64_t vbus_debounce_time;
#ifdef CONFIG_USB_PD_TRY_SRC
/*
* Time a port shall wait before it can determine it is
@@ -805,6 +810,16 @@ void tc_pr_swap_complete(int port, bool success)
{
TC_CLR_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS);
+ if (IS_ATTACHED_SNK(port)) {
+ /*
+ * Give the ADCs in the TCPC or PPC time to react following
+ * a PS_RDY message received during a SRC to SNK swap.
+ * Note: This is empirically determined, not strictly
+ * part of the USB PD spec.
+ */
+ tc[port].vbus_debounce_time = get_time().val + PD_T_DEBOUNCE;
+ }
+
/*
* AutoDischargeDisconnect was either turned off near the SNK->SRC
* PR-Swap message or when we hit Safe0V on SRC->SNK PR-Swap.
@@ -2192,8 +2207,12 @@ static void tc_attached_snk_run(const int port)
*/
if (!TC_CHK_FLAG(port, TC_FLAGS_POWER_OFF_SNK) &&
!TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- /* Detach detection */
- if (!pd_is_vbus_present(port)) {
+ /*
+ * Detach detection, but only after allowing for a debounce
+ * of the VBUS state.
+ */
+ if ((tc[port].vbus_debounce_time < get_time().val) &&
+ !pd_is_vbus_present(port)) {
if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0);
pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0);