diff options
author | Alec Berg <alecaberg@chromium.org> | 2014-11-18 09:57:12 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-11-21 04:37:34 +0000 |
commit | eb936b8df82276dbc027b113ee454e032813a30e (patch) | |
tree | a400512a053ca9da0c63eb819c179f3180fafe08 | |
parent | 1c86fa9f6dff9eaff5be29de434252daa063d4eb (diff) | |
download | chrome-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.c | 44 |
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) ? |