pd: Add Try.SRC functionality to the pd_protocol state machine

1. Added new config option CONFIG_USB_PD_TRY_SRC
	2. Added pd_try_source_enable global flag with console command
	3. Added bit to pd.flags to indicate Try.SRC states are active

BUG=chrome-os-partner:39724
TEST=Manual samus to samus with the Try.SRC enabled on both and just
     one samus. Tested Samus to Honeybuns and Samus to Zinger connections.
BRANCH=TOT

Change-Id: Ifa5d5d82e443f376e546aaf852ff24d92ef04d72
Signed-off-by: Scott Collyer <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/282052
Reviewed-by: Alec Berg <alecaberg@chromium.org>
Tested-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
Scott
2015-06-19 11:03:34 -07:00
committed by ChromeOS Commit Bot
parent 4cd2b6c011
commit e9cd229216
4 changed files with 122 additions and 17 deletions

View File

@@ -52,6 +52,7 @@
#define CONFIG_USB_PD_COMM_ENABLED 0
#define CONFIG_USB_PD_CUSTOM_VDM
#define CONFIG_USB_PD_DUAL_ROLE
#define CONFIG_USB_PD_TRY_SRC
#define CONFIG_USB_PD_FLASH_ERASE_CHECK
#define CONFIG_USB_PD_INTERNAL_COMP
#define CONFIG_USB_PD_LOGGING

View File

@@ -87,6 +87,9 @@ enum pd_dual_role_states drp_state = PD_DRP_TOGGLE_OFF;
/* Last received source cap */
static uint32_t pd_src_caps[CONFIG_USB_PD_PORT_COUNT][PDO_MAX_OBJECTS];
static int pd_src_cap_cnt[CONFIG_USB_PD_PORT_COUNT];
/* Enable varible for Try.SRC states */
static uint8_t pd_try_src_enable;
#endif
static struct pd_protocol {
@@ -127,6 +130,8 @@ static struct pd_protocol {
int new_power_request;
/* Store previously requested voltage request */
int prev_request_mv;
/* Time for Try.SRC states */
uint64_t try_src_marker;
#endif
/* PD state for Vendor Defined Messages */
@@ -260,6 +265,9 @@ static inline void set_state(int port, enum pd_states next_state)
typec_set_input_current_limit(port, 0, 0);
charge_manager_set_ceil(port, CHARGE_CEIL_NONE);
#endif
#ifdef CONFIG_USBC_VCONN
tcpm_set_vconn(port, 0);
#endif
#else /* CONFIG_USB_PD_DUAL_ROLE */
if (next_state == PD_STATE_SRC_DISCONNECTED) {
#endif
@@ -274,9 +282,6 @@ static inline void set_state(int port, enum pd_states next_state)
#ifdef CONFIG_USBC_SS_MUX
usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT,
pd[port].polarity);
#endif
#ifdef CONFIG_USBC_VCONN
tcpm_set_vconn(port, 0);
#endif
/* Disable TCPC RX */
tcpm_set_rx_enable(port, 0);
@@ -1166,6 +1171,18 @@ void pd_set_dual_role(enum pd_dual_role_states state)
int i;
drp_state = state;
#ifdef CONFIG_USB_PD_TRY_SRC
pd_try_src_enable = (state == PD_DRP_TOGGLE_ON) ? 1 : 0;
for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) {
/*
* Clear this flag to cover case where a TrySrc
* mode went from enabled to disabled and trying_source
* was active at that time.
*/
pd[i].flags &= ~PD_FLAGS_TRY_SRC;
}
#endif
for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) {
/*
* Change to sink if port is currently a source AND (new DRP
@@ -1416,13 +1433,25 @@ void pd_task(void)
PD_STATE_SRC_DISCONNECTED_DEBOUNCE);
}
#ifdef CONFIG_USB_PD_DUAL_ROLE
/* Swap roles if time expired */
else if (drp_state != PD_DRP_FORCE_SOURCE &&
get_time().val >= next_role_swap) {
/*
* Try.SRC state is embedded here. Wait for SNK
* detect, or if timer expires, transition to
* SNK_DISCONNETED.
*
* If Try.SRC state is not active, then this block
* handles the normal DRP toggle from SRC->SNK
*/
else if ((pd[port].flags & PD_FLAGS_TRY_SRC &&
get_time().val >= pd[port].try_src_marker) ||
(!(pd[port].flags & PD_FLAGS_TRY_SRC) &&
drp_state != PD_DRP_FORCE_SOURCE &&
get_time().val >= next_role_swap)) {
pd[port].power_role = PD_ROLE_SINK;
set_state(port, PD_STATE_SNK_DISCONNECTED);
tcpm_set_cc(port, TYPEC_CC_RD);
next_role_swap = get_time().val + PD_T_DRP_SNK;
pd[port].try_src_marker = get_time().val
+ PD_T_TRY_WAIT;
/* Swap states quickly */
timeout = 2*MSEC;
@@ -1455,15 +1484,18 @@ void pd_task(void)
timeout = 5*MSEC;
break;
}
/* Debounce the cc state */
if (new_cc_state != pd[port].cc_state) {
pd[port].cc_debounce = get_time().val +
PD_T_CC_DEBOUNCE;
pd[port].cc_state = new_cc_state;
break;
} else if (get_time().val < pd[port].cc_debounce) {
break;
/* If in Try.SRC state, then don't need to debounce */
if (!(pd[port].flags & PD_FLAGS_TRY_SRC)) {
/* Debounce the cc state */
if (new_cc_state != pd[port].cc_state) {
pd[port].cc_debounce = get_time().val +
PD_T_CC_DEBOUNCE;
pd[port].cc_state = new_cc_state;
break;
} else if (get_time().val <
pd[port].cc_debounce) {
break;
}
}
/* Debounce complete */
@@ -1857,6 +1889,18 @@ void pd_task(void)
break;
}
/*
* If Try.SRC is active and failed to detect a SNK,
* then it transitions to TryWait.SNK. Need to prevent
* normal dual role toggle until tDRPTryWait timer
* expires.
*/
if (pd[port].flags & PD_FLAGS_TRY_SRC) {
if (get_time().val > pd[port].try_src_marker)
pd[port].flags &= ~PD_FLAGS_TRY_SRC;
break;
}
/*
* If no source detected, check for role toggle.
* If VBUS is detected, and we are in the debug
@@ -1892,6 +1936,24 @@ void pd_task(void)
!pd_snk_is_vbus_provided(port))
break;
if (pd_try_src_enable &&
!(pd[port].flags & PD_FLAGS_TRY_SRC)) {
/*
* If TRY_SRC is enabled, but not active,
* then force attempt to connect as source.
*/
pd[port].try_src_marker = get_time().val
+ PD_T_TRY_SRC;
/* Swap roles to source */
pd[port].power_role = PD_ROLE_SOURCE;
tcpm_set_cc(port, TYPEC_CC_RP);
timeout = 2*MSEC;
set_state(port, PD_STATE_SRC_DISCONNECTED);
/* Set flag after the state change */
pd[port].flags |= PD_FLAGS_TRY_SRC;
break;
}
/* We are attached */
pd[port].polarity = (cc2 != TYPEC_CC_VOLT_OPEN);
tcpm_set_polarity(port, pd[port].polarity);
@@ -2376,6 +2438,26 @@ void pd_task(void)
set_state(port, PD_STATE_SRC_DISCONNECTED);
/* Debouncing */
timeout = 10*MSEC;
#ifdef CONFIG_USB_PD_DUAL_ROLE
/*
* If Try.SRC is configured, then ATTACHED_SRC
* needs to transition to TryWait.SNK. Change
* power role to SNK and start state timer.
*/
if (pd_try_src_enable) {
/* Swap roles to sink */
pd[port].power_role = PD_ROLE_SINK;
tcpm_set_cc(port, TYPEC_CC_RD);
/* Set timer for TryWait.SNK state */
pd[port].try_src_marker = get_time().val
+ PD_T_TRY_WAIT;
/* Advance to TryWait.SNK state */
set_state(port,
PD_STATE_SNK_DISCONNECTED);
/* Mark state as TryWait.SNK */
pd[port].flags |= PD_FLAGS_TRY_SRC;
}
#endif
}
}
#ifdef CONFIG_USB_PD_DUAL_ROLE
@@ -2678,7 +2760,21 @@ static int command_pd(int argc, char **argv)
return EC_SUCCESS;
}
#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */
#ifdef CONFIG_USB_PD_TRY_SRC
else if (!strncasecmp(argv[1], "trysrc", 6)) {
int enable;
if (argc < 3)
return EC_ERROR_PARAM_COUNT;
enable = strtoi(argv[2], &e, 10);
if (*e)
return EC_ERROR_PARAM3;
pd_try_src_enable = enable ? 1 : 0;
ccprintf("Try.SRC %s\n", enable ? "on" : "off");
return EC_SUCCESS;
}
#endif
#endif
/* command: pd <port> <subcmd> [args] */
port = strtoi(argv[1], &e, 10);
@@ -2800,7 +2896,8 @@ static int command_pd(int argc, char **argv)
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(pd, command_pd,
"dualrole|dump|enable [0|1]|rwhashtable|\n\t<port> "
"dualrole|dump|enable [0|1]|rwhashtable"
"trysrc [0|1]\n\t<port> "
"[tx|bist_rx|bist_tx|charger|clock|dev"
"|soft|hash|hard|ping|state|swap [power|data]|"
"vdm [ping | curr | vers]]",

View File

@@ -1535,6 +1535,9 @@
/* Define the type-c port controller I2C base address. */
#undef CONFIG_TCPC_I2C_BASE_ADDR
/* Use this option to enable Try.SRC mode for Dual Role devices */
#undef CONFIG_USB_PD_TRY_SRC
/* Alternative configuration keeping only the TX part of PHY */
#undef CONFIG_USB_PD_TX_PHY_ONLY

View File

@@ -160,6 +160,8 @@ enum pd_rx_errors {
#define PD_T_BIST_TRANSMIT (50*MSEC) /* 50ms (used for task_wait arg) */
#define PD_T_BIST_RECEIVE (60*MSEC) /* 60ms (max time to process bist) */
#define PD_T_VCONN_SOURCE_ON (100*MSEC) /* 100ms */
#define PD_T_TRY_SRC (125*MSEC) /* Max time for Try.SRC state */
#define PD_T_TRY_WAIT (600*MSEC) /* Max time for TryWait.SNK state */
/* number of edges and time window to detect CC line is not idle */
#define PD_RX_TRANSITION_COUNT 3
@@ -699,6 +701,7 @@ enum pd_states {
#define PD_FLAGS_CHECK_DR_ROLE (1 << 10)/* check data role in READY */
#define PD_FLAGS_PARTNER_EXTPOWER (1 << 11)/* port partner has external pwr */
#define PD_FLAGS_VCONN_ON (1 << 12)/* vconn is being sourced */
#define PD_FLAGS_TRY_SRC (1 << 13)/* Try.SRC states are active */
/* Flags to clear on a disconnect */
#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \
PD_FLAGS_PARTNER_DR_DATA | \
@@ -710,7 +713,8 @@ enum pd_states {
PD_FLAGS_CHECK_PR_ROLE | \
PD_FLAGS_CHECK_DR_ROLE | \
PD_FLAGS_PARTNER_EXTPOWER | \
PD_FLAGS_VCONN_ON)
PD_FLAGS_VCONN_ON | \
PD_FLAGS_TRY_SRC)
enum pd_cc_states {