summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2016-08-12 16:31:01 +0200
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-01-20 09:53:53 +0000
commitc210b2e57454a30084b5484af7adf51871e2620c (patch)
tree7bc346217a814a63178f787afe484de5cfdbb8fd
parent92b3623dad47f47e06168bc5f4a04417254b7028 (diff)
downloadchrome-ec-c210b2e57454a30084b5484af7adf51871e2620c.tar.gz
pd: support Rp/Rp debug accessories
Support Rp/Rp debug accessories in the USB PD state machine including detecting the polarity and the available type-C current. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=none BUG=chrome-os-partner:52592 TEST=manual, plug a Suzy-Q reworked with Rp3A0/Rp1A5 resistors on a Kevin, and see the PD state machine is going to PD_STATE_SNK_ACCESSORY (and leaving it on unplug). Re-verify a few existing accessories (Rd/Rd SuzyQ, legacy RpUSB cable, Rp3A0 power supply). Reviewed-on: https://chromium-review.googlesource.com/368700 Commit-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Mary Ruthven <mruthven@chromium.org> Reviewed-by: Shawn N <shawnn@chromium.org> (cherry picked from commit 1b9096116c9a82d9ab0beb5d5d983f9f12a14274) Change-Id: I1fb578395876e5f723caf154ae2d66ca92c9c659 Reviewed-on: https://chromium-review.googlesource.com/430610 Reviewed-by: Shawn N <shawnn@chromium.org> Commit-Queue: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--common/usb_pd_protocol.c125
-rw-r--r--include/usb_pd.h1
2 files changed, 99 insertions, 27 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index d3b1c4972a..13a60b5a9a 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -149,7 +149,7 @@ static const char * const pd_state_names[] = {
"DISABLED", "SUSPENDED",
#ifdef CONFIG_USB_PD_DUAL_ROLE
"SNK_DISCONNECTED", "SNK_DISCONNECTED_DEBOUNCE",
- "SNK_HARD_RESET_RECOVER",
+ "SNK_ACCESSORY", "SNK_HARD_RESET_RECOVER",
"SNK_DISCOVERY", "SNK_REQUESTED", "SNK_TRANSITION", "SNK_READY",
"SNK_SWAP_INIT", "SNK_SWAP_SNK_DISABLE",
"SNK_SWAP_SRC_DISABLE", "SNK_SWAP_STANDBY", "SNK_SWAP_COMPLETE",
@@ -221,7 +221,8 @@ static int pd_snk_debug_acc_toggle(int port)
static int pd_debug_acc_plugged(int port)
{
#ifdef CONFIG_CASE_CLOSED_DEBUG
- return pd[port].task_state == PD_STATE_SRC_ACCESSORY;
+ return pd[port].task_state == PD_STATE_SRC_ACCESSORY ||
+ pd[port].task_state == PD_STATE_SNK_ACCESSORY;
#else
/* Debug accessories not supported */
return 0;
@@ -1288,16 +1289,52 @@ void pd_ping_enable(int port, int enable)
pd[port].flags &= ~PD_FLAGS_PING_ENABLED;
}
+/**
+ * Returns whether the sink has detected a Rp resistor on the other side.
+ */
+static inline int cc_is_rp(int cc)
+{
+ return (cc == TYPEC_CC_VOLT_SNK_DEF) || (cc == TYPEC_CC_VOLT_SNK_1_5) ||
+ (cc == TYPEC_CC_VOLT_SNK_3_0);
+}
+
+/*
+ * CC values for regular sources and Debug sources (aka DTS)
+ *
+ * Source type Mode of Operation CC1 CC2
+ * ---------------------------------------------
+ * Regular Default USB Power RpUSB Open
+ * Regular USB-C @ 1.5 A Rp1A5 Open
+ * Regular USB-C @ 3 A Rp3A0 Open
+ * DTS Default USB Power Rp3A0 Rp1A5
+ * DTS USB-C @ 1.5 A Rp1A5 RpUSB
+ * DTS USB-C @ 3 A Rp3A0 RpUSB
+*/
+
+/**
+ * Returns the polarity of a Sink.
+ */
+static inline int get_snk_polarity(int cc1, int cc2)
+{
+ /* the following assumes:
+ * TYPEC_CC_VOLT_SNK_3_0 > TYPEC_CC_VOLT_SNK_1_5
+ * TYPEC_CC_VOLT_SNK_1_5 > TYPEC_CC_VOLT_SNK_DEF
+ * TYPEC_CC_VOLT_SNK_DEF > TYPEC_CC_VOLT_OPEN
+ */
+ return (cc2 > cc1);
+}
+
#ifdef CONFIG_CHARGE_MANAGER
/**
* Returns type C current limit (mA) based upon cc_voltage (mV).
*/
-static inline int get_typec_current_limit(int cc)
+static inline int get_typec_current_limit(int polarity, int cc1, int cc2)
{
int charge;
+ int cc = polarity ? cc2 : cc1;
+ int cc_alt = polarity ? cc1 : cc2;
- /* Detect type C charger current limit based upon vbus voltage. */
- if (cc == TYPEC_CC_VOLT_SNK_3_0)
+ if (cc == TYPEC_CC_VOLT_SNK_3_0 && cc_alt != TYPEC_CC_VOLT_SNK_1_5)
charge = 3000;
else if (cc == TYPEC_CC_VOLT_SNK_1_5)
charge = 1500;
@@ -1879,7 +1916,7 @@ void pd_task(void)
cc2 != TYPEC_CC_VOLT_OPEN) {
pd[port].cc_state = PD_CC_NONE;
hard_reset_count = 0;
- new_cc_state = PD_CC_DFP_ATTACHED;
+ new_cc_state = PD_CC_NONE;
pd[port].cc_debounce = get_time().val +
PD_T_CC_DEBOUNCE;
set_state(port,
@@ -1908,8 +1945,13 @@ void pd_task(void)
break;
case PD_STATE_SNK_DISCONNECTED_DEBOUNCE:
tcpm_get_cc(port, &cc1, &cc2);
- if (cc1 == TYPEC_CC_VOLT_OPEN &&
- cc2 == TYPEC_CC_VOLT_OPEN) {
+
+ if (cc_is_rp(cc1) && cc_is_rp(cc2)) {
+ /* Debug accessory */
+ new_cc_state = PD_CC_DEBUG_ACC;
+ } else if (cc_is_rp(cc1) || cc_is_rp(cc2)) {
+ new_cc_state = PD_CC_DFP_ATTACHED;
+ } else {
/* No connection any more */
set_state(port, PD_STATE_SNK_DISCONNECTED);
timeout = 5*MSEC;
@@ -1918,21 +1960,28 @@ void pd_task(void)
timeout = 20*MSEC;
+ /* 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;
+ }
/* Wait for CC debounce and VBUS present */
if (get_time().val < pd[port].cc_debounce ||
!pd_snk_is_vbus_provided(port))
break;
/* We are attached */
- pd[port].polarity = (cc2 != TYPEC_CC_VOLT_OPEN);
+ pd[port].polarity = get_snk_polarity(cc1, cc2);
tcpm_set_polarity(port, pd[port].polarity);
/* reset message ID on connection */
pd[port].msg_id = 0;
/* initial data role for sink is UFP */
pd_set_data_role(port, PD_ROLE_UFP);
#ifdef CONFIG_CHARGE_MANAGER
- typec_curr = get_typec_current_limit(
- pd[port].polarity ? cc2 : cc1);
+ typec_curr = get_typec_current_limit(pd[port].polarity,
+ cc1, cc2);
typec_set_input_current_limit(
port, typec_curr, TYPE_C_VOLTAGE);
#endif
@@ -1940,18 +1989,41 @@ void pd_task(void)
if (pd_comm_enabled)
tcpm_set_rx_enable(port, 1);
- /*
- * fake set data role swapped flag so we send
- * discover identity when we enter SRC_READY
- */
- pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE |
- PD_FLAGS_CHECK_DR_ROLE |
- PD_FLAGS_DATA_SWAPPED;
- set_state(port, PD_STATE_SNK_DISCOVERY);
- timeout = 10*MSEC;
- hook_call_deferred(
- pd_usb_billboard_deferred,
- PD_T_AME);
+ /* DFP is attached */
+ if (new_cc_state == PD_CC_DFP_ATTACHED) {
+ /*
+ * fake set data role swapped flag so we send
+ * discover identity when we enter SRC_READY
+ */
+ pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE |
+ PD_FLAGS_CHECK_DR_ROLE |
+ PD_FLAGS_DATA_SWAPPED;
+ set_state(port, PD_STATE_SNK_DISCOVERY);
+ timeout = 10*MSEC;
+ hook_call_deferred(
+ &pd_usb_billboard_deferred, PD_T_AME);
+ }
+#ifdef CONFIG_CASE_CLOSED_DEBUG
+ else if (new_cc_state == PD_CC_DEBUG_ACC) {
+ ccd_set_mode(system_is_locked() ?
+ CCD_MODE_PARTIAL :
+ CCD_MODE_ENABLED);
+ set_state(port, PD_STATE_SNK_ACCESSORY);
+ }
+ break;
+ case PD_STATE_SNK_ACCESSORY:
+ /* debug accessory state */
+ timeout = 100*MSEC;
+
+ tcpm_get_cc(port, &cc1, &cc2);
+
+ /* If accessory becomes detached */
+ if (!cc_is_rp(cc1) || !cc_is_rp(cc2)) {
+ set_state(port, PD_STATE_SNK_DISCONNECTED);
+ ccd_set_mode(CCD_MODE_DISABLED);
+ timeout = 10*MSEC;
+ }
+#endif
break;
case PD_STATE_SNK_HARD_RESET_RECOVER:
if (pd[port].last_state != pd[port].task_state)
@@ -2042,14 +2114,13 @@ void pd_task(void)
/* Check if CC pull-up has changed */
tcpm_get_cc(port, &cc1, &cc2);
- if (pd[port].polarity)
- cc1 = cc2;
- if (typec_curr != get_typec_current_limit(cc1)) {
+ if (typec_curr != get_typec_current_limit(
+ pd[port].polarity, cc1, cc2)) {
/* debounce signal by requiring two reads */
if (typec_curr_change) {
/* set new input current limit */
typec_curr = get_typec_current_limit(
- cc1);
+ pd[port].polarity, cc1, cc2);
typec_set_input_current_limit(
port, typec_curr, TYPE_C_VOLTAGE);
} else {
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 46d04bde9a..3e22b2e4e0 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -628,6 +628,7 @@ enum pd_states {
#ifdef CONFIG_USB_PD_DUAL_ROLE
PD_STATE_SNK_DISCONNECTED,
PD_STATE_SNK_DISCONNECTED_DEBOUNCE,
+ PD_STATE_SNK_ACCESSORY,
PD_STATE_SNK_HARD_RESET_RECOVER,
PD_STATE_SNK_DISCOVERY,
PD_STATE_SNK_REQUESTED,