summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorJameson Thies <jthies@google.com>2022-04-08 23:17:00 +0000
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-04-30 00:23:55 +0000
commitc61069ad5167b4f6f21c22e9b8241eaf57dd22cc (patch)
tree6ea5c7318b122608de0985f5c5839bb2ae4a3bd9 /common
parent90aa0fa4ae504b2b17bfb19ea90803be9c8495af (diff)
downloadchrome-ec-c61069ad5167b4f6f21c22e9b8241eaf57dd22cc.tar.gz
TCPMV2: Send alerts with ADO based on alert function call
Currently, USB PD alert messages are built based on whether a port is a source or a sink. If the port is a source, the EC assumes an OCP event and if the port is a sink the EC assumes an OVP event. To support other types of alert messages, the EC must change how they are built. This CL adds alert data object (ADO) information to the PE state and functions in usb_common to set the ADO and send alerts on one or all ports. It will allow the alert message to be defined where it is triggered. BUG=b:226228461 TEST=triggered alert message from power state change and observed Alert->Get_Status->Status transactions with OWC TBT4 dock on a twinkie. BRANCH=None Signed-off-by: Jameson Thies <jthies@google.com> Change-Id: Ib4ad0ead9eaaff792c17836bcb0061789dcccaf7 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3587509 Tested-by: Jameson Thies <jthies@google.com> Reviewed-by: Abe Levkoy <alevkoy@chromium.org> Commit-Queue: Jameson Thies <jthies@google.com>
Diffstat (limited to 'common')
-rw-r--r--common/usb_common.c38
-rw-r--r--common/usbc/usb_pe_drp_sm.c45
2 files changed, 69 insertions, 14 deletions
diff --git a/common/usb_common.c b/common/usb_common.c
index fcd6862264..a0764b45e0 100644
--- a/common/usb_common.c
+++ b/common/usb_common.c
@@ -29,6 +29,7 @@
#include "usb_pd_dpm.h"
#include "usb_pd_flags.h"
#include "usb_pd_tcpm.h"
+#include "usb_pe_sm.h"
#include "usbc_ocp.h"
#include "usbc_ppc.h"
#include "util.h"
@@ -1059,24 +1060,35 @@ void pd_srccaps_dump(int port)
}
}
-int pd_build_alert_msg(uint32_t *msg, uint32_t *len, enum pd_power_role pr)
+int pd_broadcast_alert_msg(uint32_t ado)
{
- if (msg == NULL || len == NULL)
- return EC_ERROR_INVAL;
+#if defined(CONFIG_USB_PD_TCPMV2) && defined(CONFIG_USB_PE_SM) && \
+ !defined(CONFIG_USB_VPD) && !defined(CONFIG_USB_CTVPD)
+ int ret = EC_SUCCESS;
- /*
- * SOURCE: currently only supports OCP
- * SINK: currently only supports OVP
- */
- if (pr == PD_ROLE_SOURCE)
- *msg = ADO_OCP_EVENT;
- else
- *msg = ADO_OVP_EVENT;
+ for (int i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
+ if (pd_send_alert_msg(i, ado) != EC_SUCCESS)
+ ret = EC_ERROR_BUSY;
+ }
+
+ return ret;
+#else
+ return EC_ERROR_INVALID_CONFIG;
+#endif
+}
- /* Alert data is 4 bytes */
- *len = 4;
+int pd_send_alert_msg(int port, uint32_t ado)
+{
+#if defined(CONFIG_USB_PD_TCPMV2) && defined(CONFIG_USB_PE_SM) && \
+ !defined(CONFIG_USB_VPD) && !defined(CONFIG_USB_CTVPD)
+ if (pe_set_ado(port, ado) != EC_SUCCESS)
+ return EC_ERROR_BUSY;
+ pd_dpm_request(port, DPM_REQUEST_SEND_ALERT);
return EC_SUCCESS;
+#else
+ return EC_ERROR_INVALID_CONFIG;
+#endif
}
#if defined(HAS_TASK_HOSTCMD) && !defined(TEST_BUILD)
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index dd66506b94..d5882a917a 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -553,6 +553,10 @@ static struct policy_engine {
uint32_t vdm_data[VDO_HDR_SIZE + VDO_MAX_SIZE];
uint8_t vdm_ack_min_data_objects;
+ /* ADO - Used to store information about alert messages */
+ uint32_t ado;
+ mutex_t ado_lock;
+
/* Counters */
/*
@@ -1338,6 +1342,9 @@ static void pe_clear_port_data(int port)
/* Clear any stored discovery data, but leave modes for alt mode exit */
pd_dfp_discovery_init(port);
+ /* Clear any pending alerts */
+ pe_clear_ado(port);
+
dpm_remove_sink(port);
dpm_remove_source(port);
@@ -1345,6 +1352,28 @@ static void pe_clear_port_data(int port)
tcpc_set_bist_test_mode(port, false);
}
+int pe_set_ado(int port, uint32_t data)
+{
+ /* return busy error if unable to set ado */
+ int ret = EC_ERROR_BUSY;
+
+ mutex_lock(&pe[port].ado_lock);
+ if (pe[port].ado == 0x0) {
+ pe[port].ado = data;
+ ret = EC_SUCCESS;
+ }
+
+ mutex_unlock(&pe[port].ado_lock);
+ return ret;
+}
+
+void pe_clear_ado(int port)
+{
+ mutex_lock(&pe[port].ado_lock);
+ pe[port].ado = 0x0;
+ mutex_unlock(&pe[port].ado_lock);
+}
+
static void pe_handle_detach(void)
{
const int port = TASK_ID_TO_PD_PORT(task_get_current());
@@ -2077,6 +2106,9 @@ static void pe_src_startup_entry(int port)
/* Clear explicit contract. */
pe_invalidate_explicit_contract(port);
+ /* Clear any pending PD events */
+ pe_clear_ado(port);
+
if (PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)) {
PE_CLR_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE);
/*
@@ -2948,6 +2980,9 @@ static void pe_snk_startup_entry(int port)
/* Invalidate explicit contract */
pe_invalidate_explicit_contract(port);
+ /* Clear any pending PD events */
+ pe_clear_ado(port);
+
if (PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)) {
PE_CLR_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE);
/*
@@ -4182,8 +4217,15 @@ static void pe_send_alert_entry(int port)
print_current_state(port);
- if (pd_build_alert_msg(msg, len, pe[port].power_role) != EC_SUCCESS)
+ if (msg == NULL || len == NULL) {
pe_set_ready_state(port);
+ } else {
+ /* Get ADO from PE state, the ADO is a uint32_t */
+ mutex_lock(&pe[port].ado_lock);
+ *msg = pe[port].ado;
+ *len = sizeof(pe[port].ado);
+ mutex_unlock(&pe[port].ado_lock);
+ }
/* Request the Protocol Layer to send Alert Message. */
send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_ALERT);
@@ -4193,6 +4235,7 @@ static void pe_send_alert_run(int port)
{
if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
+ pe_clear_ado(port);
pe_set_ready_state(port);
}
}