summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJett Rink <jettrink@chromium.org>2018-08-17 13:34:05 -0600
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2019-04-15 20:45:07 +0000
commit88abf21ec14f9e886bc2191e64a0f624e5ba08b8 (patch)
treede4b8449c5cda162bdccfef44f818ebdccb7b16a
parent78ca31cb534ade92a9c00b6a4dc076ad5b53bed1 (diff)
downloadchrome-ec-88abf21ec14f9e886bc2191e64a0f624e5ba08b8.tar.gz
tcpm: add higher priority tasks to handle TCPC int
See go/usb-pd-slow-response-time for more information BRANCH=none BUG=b:112088135 BUG=b/127896055 TEST=CL stack on fleex and bobba consistently meet PD timing spec Also tested that PD firmare upgrade still works (uses PD suspend) on phaser. Change-Id: If789e79dcb9b69bc7ab5cb729189ca7b651b3a46 Signed-off-by: Jett Rink <jettrink@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1185728 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1565459 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org> Commit-Queue: Daisuke Nojiri <dnojiri@chromium.org> Tested-by: Daisuke Nojiri <dnojiri@chromium.org>
-rw-r--r--common/usb_pd_protocol.c58
-rw-r--r--include/usb_pd.h3
2 files changed, 61 insertions, 0 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 275d04c7ab..a354a848bd 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -2181,6 +2181,55 @@ static int pd_restart_tcpc(int port)
}
#endif
+#ifdef HAS_TASK_PD_INT_C0
+/* Events for pd_interrupt_handler_task */
+#define PD_PROCESS_INTERRUPT (1<<0)
+
+static uint8_t pd_int_task_id[CONFIG_USB_PD_PORT_COUNT];
+
+void schedule_deferred_pd_interrupt(const int port)
+{
+ task_set_event(pd_int_task_id[port], PD_PROCESS_INTERRUPT, 0);
+}
+
+/**
+ * Main task entry point that handles PD interrupts for a single port
+ *
+ * @param p The PD port number for which to handle interrupts (pointer is
+ * reinterpreted as an integer directly).
+ */
+void pd_interrupt_handler_task(void *p)
+{
+ const int port = (int) p;
+ const int port_mask = (PD_STATUS_TCPC_ALERT_0 << port);
+
+ ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_COUNT);
+
+ pd_int_task_id[port] = task_get_current();
+
+ while (1) {
+ const int evt = task_wait_event(-1);
+
+ if (evt & PD_PROCESS_INTERRUPT) {
+ /*
+ * While the interrupt signal is asserted; we have more
+ * work to do. This effectively makes the interrupt a
+ * level-interrupt instead of an edge-interrupt without
+ * having to enable/disable a real level-interrupt in
+ * multiple locations.
+ *
+ * Also, if the port is disabled do not process
+ * interrupts. Upon existing suspend, we schedule a
+ * PD_PROCESS_INTERRUPT to check if we missed anything.
+ */
+ while ((tcpc_get_alert_status() & port_mask) &&
+ pd_is_port_enabled(port))
+ tcpc_alert(port);
+ }
+ }
+}
+#endif /* HAS_TASK_PD_INT_C0 */
+
void pd_task(void *u)
{
int head;
@@ -3746,6 +3795,15 @@ void pd_set_suspend(int port, int enable)
CPRINTS("TCPC p%d suspend disable request "
"while not suspended!", port);
set_state(port, PD_DEFAULT_STATE(port));
+ /*
+ * Since we did not service interrupts while we were suspended,
+ * see if there is a waiting interrupt to be serviced. If the
+ * interrupt line isn't asserted, we won't communicate with the
+ * TCPC.
+ */
+#ifdef HAS_TASK_PD_INT_C0
+ schedule_deferred_pd_interrupt(port);
+#endif
task_wake(PD_PORT_TO_TASK_ID(port));
}
}
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 1f53fa7914..36ee209990 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -959,6 +959,9 @@ enum pd_data_msg_type {
/* --- Policy layer functions --- */
+/** Schedules the interrupt handler for the TCPC on a high priority task. */
+void schedule_deferred_pd_interrupt(int port);
+
/* Request types for pd_build_request() */
enum pd_request_type {
PD_REQUEST_VSAFE5V,