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.

OOT_bug:
Bug: 184308605
Bug: 168245874
Bug: 173252019
Change-Id: I278b34654a7e48990b6ebe25fbe17e3aa4165098
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
This commit is contained in:
Badhri Jagan Sridharan
2021-03-31 10:56:12 -07:00
parent 16ce7f9c5e
commit f694171a83
3 changed files with 76 additions and 20 deletions

View File

@@ -228,3 +228,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_reply);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_trans);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_preset);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_post_init_entity_util_avg);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_typec_tcpm_get_timer);

View File

@@ -31,6 +31,7 @@
#include <linux/usb/tcpm.h>
#include <linux/usb/typec_altmode.h>
#include <trace/hooks/typec.h>
#include <uapi/linux/sched/types.h>
#define FOREACH_STATE(S) \
@@ -3722,8 +3723,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;
port->enter_state = port->state;
switch (port->state) {
@@ -3753,17 +3755,20 @@ static void run_state_machine(struct tcpm_port *port)
break;
case SRC_ATTACH_WAIT:
port->debouncing = true;
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:
@@ -3815,7 +3820,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);
@@ -3986,15 +3994,18 @@ static void run_state_machine(struct tcpm_port *port)
break;
case SNK_ATTACH_WAIT:
port->debouncing = true;
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)) {
@@ -4037,8 +4048,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:
/*
@@ -4078,7 +4092,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, 500);
break;
case SNK_DISCOVERY:
if (port->vbus_present) {
@@ -4099,8 +4116,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) &&
@@ -4118,6 +4137,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
@@ -4127,10 +4149,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:
@@ -4218,7 +4240,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 */
@@ -4406,7 +4431,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)
@@ -4457,10 +4485,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:
/*
@@ -4483,6 +4514,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.
@@ -4490,8 +4524,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_set_cc(port, tcpm_rp_cc(port));
@@ -4628,9 +4661,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 */
@@ -5094,6 +5130,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) {
@@ -5105,9 +5143,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:

View File

@@ -13,6 +13,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));
@@ -32,6 +42,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 <trace/define_trace.h>