diff options
author | Jett Rink <jettrink@chromium.org> | 2018-08-17 13:34:05 -0600 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2019-04-15 20:45:07 +0000 |
commit | 88abf21ec14f9e886bc2191e64a0f624e5ba08b8 (patch) | |
tree | de4b8449c5cda162bdccfef44f818ebdccb7b16a | |
parent | 78ca31cb534ade92a9c00b6a4dc076ad5b53bed1 (diff) | |
download | chrome-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.c | 58 | ||||
-rw-r--r-- | include/usb_pd.h | 3 |
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, |