summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJett Rink <jettrink@chromium.org>2018-11-15 13:03:57 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-11-16 05:02:06 -0800
commitf9f3ed0467fe2062c7916c892ecbcf00f957095a (patch)
tree0771a0ccc8d08c8e225cb4f766dc34709e90fffa
parentb2f28faa3b7f4f9d37b76dd4d7dbb2b3d50db435 (diff)
downloadchrome-ec-f9f3ed0467fe2062c7916c892ecbcf00f957095a.tar.gz
usb-pd: preprocess pending interrupts after reset
If the EC resets while the TCPC interrupt line is asserted and the board configures the interrupt as edge trigger (which is very common), then the interrupt line will never present and edge and the ISR will never get called. Preemptively checking for pending interrupts should prevent this. BRANCH=none BUG=b:119564103 TEST=test that ec reboot with hub attached no longer malfunctions. Change-Id: I77ca5815e2bdc94e3173a621aeac8620bf332613 Signed-off-by: Jett Rink <jettrink@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1337466 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r--common/usb_pd_protocol.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 988443aba1..20d713f628 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -2463,6 +2463,9 @@ static int pd_restart_tcpc(int port)
#if defined(HAS_TASK_PD_INT_C0) || defined(HAS_TASK_PD_INT_C1) || \
defined(HAS_TASK_PD_INT_C2)
+/* Used to conditionally compile code in main pd task. */
+#define HAS_DEFFERED_INTERRUPT_HANDLER
+
/* Events for pd_interrupt_handler_task */
#define PD_PROCESS_INTERRUPT (1<<0)
@@ -2666,6 +2669,17 @@ void pd_task(void *u)
charge_manager_update_dualrole(port, CAP_UNKNOWN);
#endif
+#ifdef HAS_DEFFERED_INTERRUPT_HANDLER
+ /*
+ * Since most boards configure the TCPC interrupt as edge
+ * and it is possible that the interrupt line was asserted between init
+ * and calling set_state, we need to process any pending interrupts now.
+ * Otherwise future interrupts will never fire because another edge
+ * never happens. Note this needs to happen after set_state() is called.
+ */
+ schedule_deferred_pd_interrupt(port);
+#endif
+
while (1) {
#ifdef CONFIG_USB_PD_REV30
/* send any pending messages */