summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott <scollyer@chromium.org>2015-06-19 11:03:34 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-07-08 19:34:14 +0000
commite9cd22921615ab4c8c10749f0ac2129def4bcb93 (patch)
tree1f85534b6b8cfa697c34bff2a843724d56baece0
parent4cd2b6c011a7337dcdc3686336e2e1ce24ca419a (diff)
downloadchrome-ec-e9cd22921615ab4c8c10749f0ac2129def4bcb93.tar.gz
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>
-rw-r--r--board/samus_pd/board.h1
-rw-r--r--common/usb_pd_protocol.c129
-rw-r--r--include/config.h3
-rw-r--r--include/usb_pd.h6
4 files changed, 122 insertions, 17 deletions
diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h
index 1d54501e61..a2cba6d77c 100644
--- a/board/samus_pd/board.h
+++ b/board/samus_pd/board.h
@@ -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
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 25774cd62e..3ca0ab2733 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -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
@@ -275,9 +283,6 @@ static inline void set_state(int port, enum pd_states next_state)
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 */
@@ -1858,6 +1890,18 @@ void pd_task(void)
}
/*
+ * 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
* accessory toggle state, then allow toggling.
@@ -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]]",
diff --git a/include/config.h b/include/config.h
index 3bff029e2f..b456a81f39 100644
--- a/include/config.h
+++ b/include/config.h
@@ -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
diff --git a/include/usb_pd.h b/include/usb_pd.h
index a5bfe7ab3b..6950e8065b 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -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 {