summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-11-18 09:57:12 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-11-21 04:37:34 +0000
commiteb936b8df82276dbc027b113ee454e032813a30e (patch)
treea400512a053ca9da0c63eb819c179f3180fafe08
parent1c86fa9f6dff9eaff5be29de434252daa063d4eb (diff)
downloadchrome-ec-eb936b8df82276dbc027b113ee454e032813a30e.tar.gz
pd: add explicit contract flag
Add flag for whether or not a type-C port is in an explicit contract. This flag will be used in the future to determine if VDMs can be sent. BUG=chrome-os-partner:33861 BRANCH=samus TEST=load onto samus. plug in to zinger, use pd 1 state to verify explicit contract bit is set. plug in to another samus, issue a power swap, see contract bit go away and come back when contract is established. Signed-off-by: Alec Berg <alecaberg@chromium.org> Change-Id: I9404e7cc920ebe0b37d9efae758436cc6aa7be85 Reviewed-on: https://chromium-review.googlesource.com/230520 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--common/usb_pd_protocol.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 465e2394c4..81f4df1f60 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -226,20 +226,22 @@ static uint32_t pd_src_caps[PD_PORT_COUNT][PDO_MAX_OBJECTS];
static int pd_src_cap_cnt[PD_PORT_COUNT];
#endif
-#define PD_FLAGS_PING_ENABLED (1 << 0) /* SRC_READY pings enabled */
-#define PD_FLAGS_PARTNER_DR_POWER (1 << 1) /* port partner is dual-role power */
-#define PD_FLAGS_PARTNER_DR_DATA (1 << 2) /* port partner is dual-role data */
-#define PD_FLAGS_DATA_SWAPPED (1 << 3) /* data swap complete */
-#define PD_FLAGS_SNK_CAP_RECVD (1 << 4) /* sink capabilities received */
-#define PD_FLAGS_GET_SNK_CAP_SENT (1 << 5) /* get sink cap sent */
-#define PD_FLAGS_NEW_CONTRACT (1 << 6) /* new power contract established */
+#define PD_FLAGS_PING_ENABLED (1 << 0) /* SRC_READY pings enabled */
+#define PD_FLAGS_PARTNER_DR_POWER (1 << 1) /* port partner is dualrole power */
+#define PD_FLAGS_PARTNER_DR_DATA (1 << 2) /* port partner is dualrole data */
+#define PD_FLAGS_DATA_SWAPPED (1 << 3) /* data swap complete */
+#define PD_FLAGS_SNK_CAP_RECVD (1 << 4) /* sink capabilities received */
+#define PD_FLAGS_GET_SNK_CAP_SENT (1 << 5) /* get sink cap sent */
+#define PD_FLAGS_NEW_CONTRACT (1 << 6) /* new power contract established */
+#define PD_FLAGS_EXPLICIT_CONTRACT (1 << 7) /* explicit pwr contract in place */
/* Flags to clear on a disconnect */
#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \
PD_FLAGS_PARTNER_DR_DATA | \
PD_FLAGS_DATA_SWAPPED | \
PD_FLAGS_SNK_CAP_RECVD | \
PD_FLAGS_GET_SNK_CAP_SENT | \
- PD_FLAGS_NEW_CONTRACT)
+ PD_FLAGS_NEW_CONTRACT | \
+ PD_FLAGS_EXPLICIT_CONTRACT)
static struct pd_protocol {
/* current port power role (SOURCE or SINK) */
@@ -860,8 +862,17 @@ static void handle_data_request(int port, uint16_t head,
case PD_DATA_REQUEST:
if ((pd[port].power_role == PD_ROLE_SOURCE) && (cnt == 1))
if (!pd_check_requested_voltage(payload[0])) {
+ if (send_control(port, PD_CTRL_ACCEPT) < 0)
+ /*
+ * if we fail to send accept, do
+ * nothing and let sink timeout and
+ * send hard reset
+ */
+ return;
+
+ /* explicit contract is now in place */
+ pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT;
pd[port].requested_idx = payload[0] >> 28;
- send_control(port, PD_CTRL_ACCEPT);
set_state(port, PD_STATE_SRC_ACCEPTED);
return;
}
@@ -1000,9 +1011,17 @@ static void handle_ctrl_request(int port, uint16_t head,
pd_dr_swap(port);
set_state(port, PD_STATE_SNK_READY);
} else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) {
+ /* explicit contract goes away for power swap */
+ pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT;
set_state(port, PD_STATE_SRC_SWAP_SNK_DISABLE);
} else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT) {
+ /* explicit contract goes away for power swap */
+ pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT;
set_state(port, PD_STATE_SNK_SWAP_SNK_DISABLE);
+ } else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) {
+ /* explicit contract is now in place */
+ pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT;
+ set_state(port, PD_STATE_SNK_TRANSITION);
}
#endif
break;
@@ -1885,7 +1904,6 @@ void pd_task(void)
break;
case PD_STATE_SNK_REQUESTED:
/* Ensure the power supply actually becomes ready */
- set_state(port, PD_STATE_SNK_TRANSITION);
hard_reset_count = 0;
timeout = 10 * MSEC;
break;
@@ -2480,11 +2498,13 @@ static int command_pd(int argc, char **argv)
};
BUILD_ASSERT(ARRAY_SIZE(state_names) == PD_STATE_COUNT);
ccprintf("Port C%d, %s - Role: %s-%s Polarity: CC%d "
- "Partner: %s%s, State: %s\n",
- port, pd_comm_enabled ? "Enabled" : "Disabled",
+ "Contract: %s, Partner: %s%s, State: %s\n",
+ port, pd_comm_enabled ? "Ena" : "Dis",
pd[port].power_role == PD_ROLE_SOURCE ? "SRC" : "SNK",
pd[port].data_role == PD_ROLE_DFP ? "DFP" : "UFP",
pd[port].polarity + 1,
+ pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT ?
+ "Yes" : "No",
(pd[port].flags & PD_FLAGS_PARTNER_DR_POWER) ?
"PR_SWAP," : "",
(pd[port].flags & PD_FLAGS_PARTNER_DR_DATA) ?