diff options
-rw-r--r-- | common/usb_pd_protocol.c | 44 | ||||
-rw-r--r-- | include/usb_pd_tcpm.h | 8 |
2 files changed, 42 insertions, 10 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index e245ddbd56..7d9ade5e2c 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -621,6 +621,14 @@ static void pd_update_saved_port_flags(int port, uint8_t flag, uint8_t val) } #endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */ +/** + * Returns true if the port is currently in the try src state. + */ +static inline int is_try_src(int port) +{ + return pd[port].flags & PD_FLAGS_TRY_SRC; +} + static inline void set_state(int port, enum pd_states next_state) { enum pd_states last_state = pd[port].task_state; @@ -2929,17 +2937,32 @@ void pd_task(void *u) */ if (auto_toggle_supported && !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) && - !(pd[port].flags & PD_FLAGS_TRY_SRC) && + !is_try_src(port) && cc_is_open(cc1, cc2)) { set_state(port, PD_STATE_DRP_AUTO_TOGGLE); timeout = 2*MSEC; break; } #endif - - /* Vnc monitoring */ - if (cc_is_at_least_one_rd(cc1, cc2) || - cc_is_audio_acc(cc1, cc2)) { + /* + * Transition to DEBOUNCE if we detect appropriate + * signals + * + * (from 4.5.2.2.10.2 Exiting from Try.SRC State) + * If try_src -and- + * have only one Rd (not both) => DEBOUNCE + * + * (from 4.5.2.2.7.2 Exiting from Unattached.SRC State) + * If not try_src -and- + * have at least one Rd => DEBOUNCE -or- + * have audio access => DEBOUNCE + * + * try_src should not exit if both pins are Rd + */ + if ((is_try_src(port) && cc_is_only_one_rd(cc1, cc2)) || + (!is_try_src(port) && + (cc_is_at_least_one_rd(cc1, cc2) || + cc_is_audio_acc(cc1, cc2)))) { #ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP /* Enable VBUS */ if (pd_set_power_supply_ready(port)) @@ -2960,7 +2983,7 @@ void pd_task(void *u) * (PD_T_TRY_TIMEOUT). Otherwise we should stay * within Try.SRC (break). */ - if (pd[port].flags & PD_FLAGS_TRY_SRC) { + if (is_try_src(port)) { if (now.val < pd[port].try_src_marker) { break; } else if (now.val < pd[port].try_timeout) { @@ -3024,9 +3047,10 @@ void pd_task(void *u) /* Set debounce timer */ if (new_cc_state != pd[port].cc_state) { - pd[port].cc_debounce = get_time().val + - (pd[port].flags & PD_FLAGS_TRY_SRC) ? - PD_T_DEBOUNCE : PD_T_CC_DEBOUNCE; + pd[port].cc_debounce = + get_time().val + + (is_try_src(port) ? PD_T_DEBOUNCE + : PD_T_CC_DEBOUNCE); pd[port].cc_state = new_cc_state; break; } @@ -3483,7 +3507,7 @@ void pd_task(void *u) */ if (auto_toggle_supported && !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) && - !(pd[port].flags & PD_FLAGS_TRY_SRC) && + !is_try_src(port) && cc_is_open(cc1, cc2)) { set_state(port, PD_STATE_DRP_AUTO_TOGGLE); timeout = 2*MSEC; diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h index 0a824cc657..2a9778c3dd 100644 --- a/include/usb_pd_tcpm.h +++ b/include/usb_pd_tcpm.h @@ -100,6 +100,14 @@ static inline int cc_is_at_least_one_rd(int cc1, int cc2) return cc1 == TYPEC_CC_VOLT_RD || cc2 == TYPEC_CC_VOLT_RD; } +/** + * Returns true if the port partner is presenting Rd on only one CC line. + */ +static inline int cc_is_only_one_rd(int cc1, int cc2) +{ + return cc_is_at_least_one_rd(cc1, cc2) && cc1 != cc2; +} + struct tcpm_drv { /** * Initialize TCPM driver and wait for TCPC readiness. |