From fca91a7cfaf0b01901064e4d94bd8fd115dbf876 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Wed, 31 Mar 2021 10:56:12 -0700 Subject: [PATCH] ANDROID: usb: typec: tcpm: vendor hook for timer adjustments linux/usb/pd.h has a bunch of timers for which the Type-C spec defines a range of values. These values have to be tuned based on the latency observed in a specific architecture. However, linux opensource sets them to a specific value without providing a mechanism to set board specific values. While a generic way is figured out, a vendor hook is needed in the interim. For instance, tCCDebounce can have a value between 100msec - 200msec. Squashed "ANDROID: usb: typec: tcpm: Fixup the wait time for SNK_DISCOVERY" OOT_bug: Bug: 184308605 Bug: 168245874 Bug: 173252019 Bug: 271294543 Change-Id: I278b34654a7e48990b6ebe25fbe17e3aa4165098 Signed-off-by: Badhri Jagan Sridharan (cherry picked from commit 081a88febb8ce33dd560bd602c7708ef3abd8478) --- drivers/android/vendor_hooks.c | 1 + drivers/usb/typec/tcpm/tcpm.c | 81 +++++++++++++++++++++++++--------- include/trace/hooks/typec.h | 14 ++++++ 3 files changed, 76 insertions(+), 20 deletions(-) diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 36566a821b4b..47f69283c185 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -302,3 +302,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_si_meminfo); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_exit_signal); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_typec_tcpci_override_toggling); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_typec_tcpci_get_vbus); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_typec_tcpm_get_timer); diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index f560852360d4..53ffc427f157 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -31,6 +31,7 @@ #include #include +#include #include #define FOREACH_STATE(S) \ @@ -3854,8 +3855,9 @@ static void run_state_machine(struct tcpm_port *port) { int ret; enum typec_pwr_opmode opmode; - unsigned int msecs; + unsigned int msecs, timer_val_msecs; enum tcpm_state upcoming_state; + const char *state_name; if (port->tcpc->check_contaminant && port->state != CHECK_CONTAMINANT) port->potential_contaminant = ((port->enter_state == SRC_ATTACH_WAIT && @@ -3888,17 +3890,20 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, SNK_UNATTACHED, PD_T_DRP_SNK); break; case SRC_ATTACH_WAIT: + timer_val_msecs = PD_T_CC_DEBOUNCE; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[SRC_ATTACH_WAIT], + CC_DEBOUNCE, &timer_val_msecs); if (tcpm_port_is_debug(port)) tcpm_set_state(port, DEBUG_ACC_ATTACHED, - PD_T_CC_DEBOUNCE); + timer_val_msecs); else if (tcpm_port_is_audio(port)) tcpm_set_state(port, AUDIO_ACC_ATTACHED, - PD_T_CC_DEBOUNCE); + timer_val_msecs); else if (tcpm_port_is_source(port) && port->vbus_vsafe0v) tcpm_set_state(port, tcpm_try_snk(port) ? SNK_TRY : SRC_ATTACHED, - PD_T_CC_DEBOUNCE); + timer_val_msecs); break; case SNK_TRY: @@ -3949,7 +3954,10 @@ static void run_state_machine(struct tcpm_port *port) } break; case SRC_TRYWAIT_DEBOUNCE: - tcpm_set_state(port, SRC_ATTACHED, PD_T_CC_DEBOUNCE); + timer_val_msecs = PD_T_CC_DEBOUNCE; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[SRC_TRYWAIT_DEBOUNCE], + CC_DEBOUNCE, &timer_val_msecs); + tcpm_set_state(port, SRC_ATTACHED, timer_val_msecs); break; case SRC_TRYWAIT_UNATTACHED: tcpm_set_state(port, SNK_UNATTACHED, 0); @@ -4129,15 +4137,18 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, SRC_UNATTACHED, PD_T_DRP_SRC); break; case SNK_ATTACH_WAIT: + timer_val_msecs = PD_T_CC_DEBOUNCE; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[SNK_ATTACH_WAIT], + CC_DEBOUNCE, &timer_val_msecs); if ((port->cc1 == TYPEC_CC_OPEN && port->cc2 != TYPEC_CC_OPEN) || (port->cc1 != TYPEC_CC_OPEN && port->cc2 == TYPEC_CC_OPEN)) tcpm_set_state(port, SNK_DEBOUNCED, - PD_T_CC_DEBOUNCE); + timer_val_msecs); else if (tcpm_port_is_disconnected(port)) tcpm_set_state(port, SNK_UNATTACHED, - PD_T_PD_DEBOUNCE); + timer_val_msecs); break; case SNK_DEBOUNCED: if (tcpm_port_is_disconnected(port)) @@ -4173,8 +4184,11 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, SRC_ATTACHED, PD_T_PD_DEBOUNCE); break; case SNK_TRYWAIT: + timer_val_msecs = PD_T_CC_DEBOUNCE; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[SNK_TRYWAIT], + CC_DEBOUNCE, &timer_val_msecs); tcpm_set_cc(port, TYPEC_CC_RD); - tcpm_set_state(port, SNK_TRYWAIT_VBUS, PD_T_CC_DEBOUNCE); + tcpm_set_state(port, SNK_TRYWAIT_VBUS, timer_val_msecs); break; case SNK_TRYWAIT_VBUS: /* @@ -4214,7 +4228,10 @@ static void run_state_machine(struct tcpm_port *port) /* SRC -> SNK POWER/FAST_ROLE_SWAP finished */ tcpm_ams_finish(port); - tcpm_set_state(port, SNK_DISCOVERY, 0); + timer_val_msecs = 0; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[SNK_STARTUP], + SINK_DISCOVERY_BC12, &timer_val_msecs); + tcpm_set_state(port, SNK_DISCOVERY, timer_val_msecs); break; case SNK_DISCOVERY: if (port->vbus_present) { @@ -4240,8 +4257,10 @@ static void run_state_machine(struct tcpm_port *port) PD_T_DB_DETECT : PD_T_NO_RESPONSE); break; case SNK_DISCOVERY_DEBOUNCE: - tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE_DONE, - PD_T_CC_DEBOUNCE); + timer_val_msecs = PD_T_CC_DEBOUNCE; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[SNK_DISCOVERY_DEBOUNCE], + CC_DEBOUNCE, &timer_val_msecs); + tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE_DONE, timer_val_msecs); break; case SNK_DISCOVERY_DEBOUNCE_DONE: if (!tcpm_port_is_disconnected(port) && @@ -4259,6 +4278,9 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, SNK_READY, 0); break; } + timer_val_msecs = PD_T_SINK_WAIT_CAP; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[SNK_WAIT_CAPABILITIES], + SINK_WAIT_CAP, &timer_val_msecs); /* * If VBUS has never been low, and we time out waiting * for source cap, try a soft reset first, in case we @@ -4268,10 +4290,10 @@ static void run_state_machine(struct tcpm_port *port) if (port->vbus_never_low) { port->vbus_never_low = false; tcpm_set_state(port, SNK_SOFT_RESET, - PD_T_SINK_WAIT_CAP); + timer_val_msecs); } else { tcpm_set_state(port, hard_reset_state(port), - PD_T_SINK_WAIT_CAP); + timer_val_msecs); } break; case SNK_NEGOTIATE_CAPABILITIES: @@ -4397,7 +4419,10 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, ACC_UNATTACHED, 0); break; case AUDIO_ACC_DEBOUNCE: - tcpm_set_state(port, ACC_UNATTACHED, PD_T_CC_DEBOUNCE); + timer_val_msecs = PD_T_CC_DEBOUNCE; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[AUDIO_ACC_DEBOUNCE], + CC_DEBOUNCE, &timer_val_msecs); + tcpm_set_state(port, ACC_UNATTACHED, timer_val_msecs); break; /* Hard_Reset states */ @@ -4586,7 +4611,10 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, ERROR_RECOVERY, 0); break; case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF: - tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_OFF); + timer_val_msecs = PD_T_PS_SOURCE_OFF; + state_name = tcpm_states[FR_SWAP_SNK_SRC_TRANSITION_TO_OFF]; + trace_android_vh_typec_tcpm_get_timer(state_name, SOURCE_OFF, &timer_val_msecs); + tcpm_set_state(port, ERROR_RECOVERY, timer_val_msecs); break; case FR_SWAP_SNK_SRC_NEW_SINK_READY: if (port->vbus_source) @@ -4638,10 +4666,13 @@ static void run_state_machine(struct tcpm_port *port) PD_T_SRCSWAPSTDBY); break; case PR_SWAP_SRC_SNK_SOURCE_OFF: + timer_val_msecs = PD_T_CC_DEBOUNCE; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[PR_SWAP_SRC_SNK_SOURCE_OFF], + CC_DEBOUNCE, &timer_val_msecs); tcpm_set_cc(port, TYPEC_CC_RD); /* allow CC debounce */ tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED, - PD_T_CC_DEBOUNCE); + timer_val_msecs); break; case PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED: /* @@ -4665,6 +4696,9 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, SNK_STARTUP, 0); break; case PR_SWAP_SNK_SRC_SINK_OFF: + timer_val_msecs = PD_T_PS_SOURCE_OFF; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[PR_SWAP_SNK_SRC_SINK_OFF], + SOURCE_OFF, &timer_val_msecs); /* * Prevent vbus discharge circuit from turning on during PR_SWAP * as this is not a disconnect. @@ -4672,8 +4706,7 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, port->pps_data.active, 0); tcpm_set_charge(port, false); - tcpm_set_state(port, hard_reset_state(port), - PD_T_PS_SOURCE_OFF); + tcpm_set_state(port, hard_reset_state(port), timer_val_msecs); break; case PR_SWAP_SNK_SRC_SOURCE_ON: tcpm_enable_auto_vbus_discharge(port, true); @@ -4803,9 +4836,12 @@ static void run_state_machine(struct tcpm_port *port) PD_T_ERROR_RECOVERY); break; case PORT_RESET_WAIT_OFF: + timer_val_msecs = PD_T_PS_SOURCE_OFF; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[PORT_RESET_WAIT_OFF], + SOURCE_OFF, &timer_val_msecs); tcpm_set_state(port, tcpm_default_state(port), - port->vbus_present ? PD_T_PS_SOURCE_OFF : 0); + port->vbus_present ? timer_val_msecs : 0); break; /* AMS intermediate state */ @@ -5268,6 +5304,8 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port) static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port) { + unsigned int timer_val_msecs; + tcpm_log_force(port, "VBUS VSAFE0V"); port->vbus_vsafe0v = true; switch (port->state) { @@ -5279,9 +5317,12 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port) tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER); break; case SRC_ATTACH_WAIT: + timer_val_msecs = PD_T_CC_DEBOUNCE; + trace_android_vh_typec_tcpm_get_timer(tcpm_states[SRC_ATTACH_WAIT], + CC_DEBOUNCE, &timer_val_msecs); if (tcpm_port_is_source(port)) tcpm_set_state(port, tcpm_try_snk(port) ? SNK_TRY : SRC_ATTACHED, - PD_T_CC_DEBOUNCE); + timer_val_msecs); break; case SRC_STARTUP: case SRC_SEND_CAPABILITIES: diff --git a/include/trace/hooks/typec.h b/include/trace/hooks/typec.h index f4981494b35c..f7c832fca7cd 100644 --- a/include/trace/hooks/typec.h +++ b/include/trace/hooks/typec.h @@ -12,6 +12,16 @@ struct tcpci; struct tcpci_data; +#ifndef TYPEC_TIMER +#define TYPEC_TIMER +enum typec_timer { + SINK_WAIT_CAP, + SOURCE_OFF, + CC_DEBOUNCE, + SINK_DISCOVERY_BC12, +}; +#endif + DECLARE_HOOK(android_vh_typec_tcpci_override_toggling, TP_PROTO(struct tcpci *tcpci, struct tcpci_data *data, int *override_toggling), TP_ARGS(tcpci, data, override_toggling)); @@ -27,6 +37,10 @@ DECLARE_RESTRICTED_HOOK(android_rvh_typec_tcpci_get_vbus, TP_PROTO(struct tcpci *tcpci, struct tcpci_data *data, int *vbus, int *bypass), TP_ARGS(tcpci, data, vbus, bypass), 1); +DECLARE_HOOK(android_vh_typec_tcpm_get_timer, + TP_PROTO(const char *state, enum typec_timer timer, unsigned int *msecs), + TP_ARGS(state, timer, msecs)); + #endif /* _TRACE_HOOK_UFSHCD_H */ /* This part must be outside protection */ #include