summaryrefslogtreecommitdiff
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
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>
-rw-r--r--common/usb_common.c38
-rw-r--r--common/usbc/usb_pe_drp_sm.c45
-rw-r--r--include/usb_common.h17
-rw-r--r--include/usb_pe_sm.h16
4 files changed, 97 insertions, 19 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);
}
}
diff --git a/include/usb_common.h b/include/usb_common.h
index 5fc215798f..98823c992f 100644
--- a/include/usb_common.h
+++ b/include/usb_common.h
@@ -226,14 +226,21 @@ int pd_get_saved_port_flags(int port, uint8_t *flags);
void pd_update_saved_port_flags(int port, uint8_t flag, uint8_t do_set);
/**
- * Build PD alert message
+ * Sets up and sends PD alert message with given ADO on all ports.
*
- * @param msg pointer where message is stored
- * @param len pointer where length of message is stored in bytes
- * @param pr current PD power role
+ * @param ado - Alert Data Object defining alert sent to the PD partner
* @return EC_SUCCESS on success else EC_ERROR_INVAL
*/
-int pd_build_alert_msg(uint32_t *msg, uint32_t *len, enum pd_power_role pr);
+int pd_broadcast_alert_msg(uint32_t ado);
+
+/**
+ * Sets up and sends PD alert message with given ADO on one port.
+ *
+ * @param port - the port to send the alert message on
+ * @param ado - Alert Data Object defining alert sent to the PD partner
+ * @return EC_SUCCESS on success else EC_ERROR_INVAL
+ */
+int pd_send_alert_msg(int port, uint32_t ado);
/**
* During USB retimer firmware update, process operation
diff --git a/include/usb_pe_sm.h b/include/usb_pe_sm.h
index d6ecb4d400..aef262ef49 100644
--- a/include/usb_pe_sm.h
+++ b/include/usb_pe_sm.h
@@ -176,6 +176,22 @@ const char *pe_get_current_state(int port);
*/
uint32_t pe_get_flags(int port);
+/**
+ * Sets the Alert Data Object (ADO) in the PE state
+ *
+ * @param port USB-C port number
+ * @param data - ADO data sent during alert messages
+ * @return EC_SUCCESS if successful and EC_ERROR_BUSY if not
+ */
+int pe_set_ado(int port, uint32_t data);
+
+/**
+ * Clears the Alert Data Object (ADO) in the PE state
+ *
+ * @param port USB-C port number
+ */
+void pe_clear_ado(int port);
+
#ifdef TEST_BUILD
/**
* Clears all internal port data, as we would on a detach event