summaryrefslogtreecommitdiff
path: root/common/usbc
diff options
context:
space:
mode:
authorDenis Brockus <dbrockus@google.com>2020-08-27 15:34:03 -0600
committerCommit Bot <commit-bot@chromium.org>2020-09-02 21:50:25 +0000
commitbc7b14284465675c69cfa186da6a3389debfde16 (patch)
treea0e3705a72ba983e7cfca0fe5bf75e73a8e31c0c /common/usbc
parent44302acb01290bea42acf35bd15a390a36a6688d (diff)
downloadchrome-ec-bc7b14284465675c69cfa186da6a3389debfde16.tar.gz
TCPMv2: Add DPM_REQUEST_GET_SRC_CAP
As a SRC that runs on battery it can be handy to determine if the connected partner has unconstrained power available so we can try to PR_Swap to let them power us. This only requests the information, if it is not already available, and leaves it to other code to determine if the swap is a good idea. BUG=b:166446426 BRANCH=none TEST=connect a sink device and determine it performed the action Signed-off-by: Denis Brockus <dbrockus@google.com> Change-Id: If45801a33df8b75e541989d7ee8f36ed316ffcc6 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2381408 Tested-by: Denis Brockus <dbrockus@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org> Commit-Queue: Jett Rink <jettrink@chromium.org> Auto-Submit: Denis Brockus <dbrockus@chromium.org>
Diffstat (limited to 'common/usbc')
-rw-r--r--common/usbc/usb_pe_drp_sm.c96
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c10
2 files changed, 101 insertions, 5 deletions
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index 60924579b4..9c489fccf8 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -276,6 +276,7 @@ enum usb_pe_state {
PE_DEU_SEND_ENTER_USB,
PE_DR_SNK_GET_SINK_CAP,
PE_DR_SNK_GIVE_SOURCE_CAP,
+ PE_DR_SRC_GET_SOURCE_CAP,
/* PD3.0 only states below here*/
PE_FRS_SNK_SRC_START_AMS,
@@ -397,6 +398,7 @@ static const char * const pe_state_names[] = {
[PE_DR_SNK_GET_SINK_CAP] = "PE_DR_SNK_Get_Sink_Cap",
#endif
[PE_DR_SNK_GIVE_SOURCE_CAP] = "PE_DR_SNK_Give_Source_Cap",
+ [PE_DR_SRC_GET_SOURCE_CAP] = "PE_DR_SRC_Get_Source_Cap",
/* PD3.0 only states below here*/
#ifdef CONFIG_USB_PD_REV30
@@ -2068,6 +2070,14 @@ static void pe_src_transition_supply_run(int port)
*/
PE_SET_FLAG(port, PE_FLAGS_FIRST_MSG);
+ /*
+ * Setup to get Device Policy Manager to request
+ * Source Capabilities, if needed, for possible
+ * PR_Swap
+ */
+ if (pd_get_src_cap_cnt(port) == 0)
+ pe_dpm_request(port, DPM_REQUEST_GET_SRC_CAPS);
+
set_state_pe(port, PE_SRC_READY);
} else {
/* NOTE: First pass through this code block */
@@ -2326,6 +2336,11 @@ static void pe_src_ready_run(int port)
DPM_REQUEST_SRC_CAP_CHANGE);
set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
} else if (PE_CHK_DPM_REQUEST(port,
+ DPM_REQUEST_GET_SRC_CAPS)) {
+ pe_set_dpm_curr_request(port,
+ DPM_REQUEST_GET_SRC_CAPS);
+ set_state_pe(port, PE_DR_SRC_GET_SOURCE_CAP);
+ } else if (PE_CHK_DPM_REQUEST(port,
DPM_REQUEST_SEND_PING)) {
pe_set_dpm_curr_request(port,
DPM_REQUEST_SEND_PING);
@@ -2641,7 +2656,6 @@ static void pe_snk_evaluate_capability_entry(int port)
{
uint32_t *pdo = (uint32_t *)rx_emsg[port].buf;
uint32_t num = rx_emsg[port].len >> 2;
- int i;
print_current_state(port);
@@ -2659,10 +2673,7 @@ static void pe_snk_evaluate_capability_entry(int port)
if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20)
prl_set_rev(port, TCPC_TX_SOP_PRIME, PD_REV20);
- pe[port].src_cap_cnt = num;
-
- for (i = 0; i < num; i++)
- pe[port].src_caps[i] = pdo[i];
+ pd_set_src_caps(port, num, pdo);
/* src cap 0 should be fixed PDO */
pe_update_pdo_flags(port, pdo[0]);
@@ -5850,6 +5861,77 @@ static void pe_dr_snk_give_source_cap_run(int port)
}
}
+/*
+ * PE_DR_SRC_Get_Source_Cap
+ */
+static void pe_dr_src_get_source_cap_entry(int port)
+{
+ print_current_state(port);
+
+ /* Send a Get_Source_Cap Message */
+ tx_emsg[port].len = 0;
+ send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_GET_SOURCE_CAP);
+ pe_sender_response_msg_entry(port);
+}
+
+static void pe_dr_src_get_source_cap_run(int port)
+{
+ int type;
+ int cnt;
+ int ext;
+ enum pe_msg_check msg_check;
+
+ /*
+ * Check the state of the message sent
+ */
+ msg_check = pe_sender_response_msg_run(port);
+
+ /*
+ * Transition to PE_SRC_Ready when:
+ * 1) A Source Capabilities Message is received.
+ * 2) A Reject Message is received.
+ */
+ if ((msg_check & PE_MSG_SENT) &&
+ PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
+ PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
+
+ type = PD_HEADER_TYPE(rx_emsg[port].header);
+ cnt = PD_HEADER_CNT(rx_emsg[port].header);
+ ext = PD_HEADER_EXT(rx_emsg[port].header);
+
+ if (ext == 0) {
+ if ((cnt > 0) && (type == PD_DATA_SOURCE_CAP)) {
+ uint32_t *payload =
+ (uint32_t *)rx_emsg[port].buf;
+
+ /*
+ * src_caps[0] & PDO_FIXED_UNCONSTRAINED
+ * has useful information to help guide us
+ * to possibly perform a PR_Swap if that is
+ * desired
+ */
+ pd_set_src_caps(port, cnt, payload);
+ set_state_pe(port, PE_SRC_READY);
+ } else if (type == PD_CTRL_REJECT ||
+ type == PD_CTRL_NOT_SUPPORTED) {
+ set_state_pe(port, PE_SRC_READY);
+ } else {
+ set_state_pe(port, PE_SEND_SOFT_RESET);
+ }
+ return;
+ }
+ }
+
+ /*
+ * Transition to PE_SRC_Ready state when:
+ * 1) the SenderResponseTimer times out.
+ * 2) Message was discarded.
+ */
+ if ((msg_check & PE_MSG_DISCARDED) ||
+ get_time().val > pe[port].sender_response_timer)
+ set_state_pe(port, PE_SRC_READY);
+}
+
const uint32_t * const pd_get_src_caps(int port)
{
return pe[port].src_caps;
@@ -6212,6 +6294,10 @@ static const struct usb_state pe_states[] = {
.entry = pe_dr_snk_give_source_cap_entry,
.run = pe_dr_snk_give_source_cap_run,
},
+ [PE_DR_SRC_GET_SOURCE_CAP] = {
+ .entry = pe_dr_src_get_source_cap_entry,
+ .run = pe_dr_src_get_source_cap_run,
+ },
#ifdef CONFIG_USB_PD_REV30
[PE_FRS_SNK_SRC_START_AMS] = {
.entry = pe_frs_snk_src_start_ams_entry,
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
index c2a9ef0985..2dbcb294f9 100644
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
@@ -1927,6 +1927,11 @@ static void tc_unattached_snk_entry(const int port)
tc[port].data_role = PD_ROLE_DISCONNECTED;
/*
+ * Saved SRC_Capabilities are no longer valid on disconnect
+ */
+ pd_set_src_caps(port, 0, NULL);
+
+ /*
* When data role set events are used to enable BC1.2, then CC
* detach events are used to notify BC1.2 that it can be powered
* down.
@@ -2404,6 +2409,11 @@ static void tc_unattached_src_entry(const int port)
tc[port].data_role = PD_ROLE_DISCONNECTED;
/*
+ * Saved SRC_Capabilities are no longer valid on disconnect
+ */
+ pd_set_src_caps(port, 0, NULL);
+
+ /*
* When data role set events are used to enable BC1.2, then CC
* detach events are used to notify BC1.2 that it can be powered
* down.