diff options
author | Jett Rink <jettrink@chromium.org> | 2018-12-13 07:12:00 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2018-12-18 21:27:47 +0000 |
commit | 9b03aa4e66c18f9e37460a9cbe0eb16a3c20a9f7 (patch) | |
tree | ec25256c6ca9fc392344ea76b385e2ef4ad2ddff /common | |
parent | 85f6feabf4fd8747d88818af67c6b97be240a369 (diff) | |
download | chrome-ec-9b03aa4e66c18f9e37460a9cbe0eb16a3c20a9f7.tar.gz |
tcpc: wait for TCPC wake up upon first access
Previously we tried to perform i2c communication with the TCPC when it
was in low power mode and only if the i2c transaction failed did we wait
for the device to wake up. Now that the PS8751 will respond to i2c
transaction (ACK them) when it is in LPM, ensure the init happers before
we start talking to the device to handle an interrupt.
BRANCH=none
BUG=b:118063849,b:121109893
TEST=verify that plug and unplug for PS8751, ANX3429, and ANX3447 LPM
still works.
Change-Id: I8c18195e55ee6d04af7d4ff24230a3bd2d147d53
Signed-off-by: Jett Rink <jettrink@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1375102
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-by: Edward Hill <ecgh@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/1383318
Diffstat (limited to 'common')
-rw-r--r-- | common/usb_pd_protocol.c | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 33730fb9cd..ff8f5610cd 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -401,25 +401,7 @@ static void handle_device_access(int port) } } -/* - * This can be called from any task. If we are in the PD task, we can handle - * immediately. Otherwise, we need to notify the PD task via event. - */ -void pd_device_accessed(int port) -{ - if (port == TASK_ID_TO_PD_PORT(task_get_current())) { - /* Ignore any access to device while it is waking up */ - if (pd[port].flags & PD_FLAGS_LPM_TRANSITION) - return; - - handle_device_access(port); - } - else - task_set_event(PD_PORT_TO_TASK_ID(port), - PD_EVENT_DEVICE_ACCESSED, 0); -} - -int pd_device_in_low_power(int port) +static int pd_device_in_low_power(int port) { /* * If we are actively waking the device up in the PD task, do not @@ -449,6 +431,20 @@ static int reset_device_and_notify(int port) else CPRINTS("TCPC p%d init failed!", port); + /* + * Before getting the other tasks that are waiting, clear the reset + * event from this PD task to prevent multiple reset/init events + * occurring. + * + * The double reset event happens when the higher priority PD interrupt + * task gets an interrupt during the above tcpm_init function. When that + * occurs, the higher priority task waits correctly for us to finish + * waking the TCPC, but it has also set PD_EVENT_TCPC_RESET again, which + * would result in a second, unnecessary init. + */ + atomic_clear(task_get_event_bitmap(task_get_current()), + PD_EVENT_TCPC_RESET); + waiting_tasks = atomic_read_clear(&pd[port].tasks_waiting_on_reset); /* @@ -470,7 +466,7 @@ static int reset_device_and_notify(int port) return rv; } -void pd_wait_for_wakeup(int port) +static void pd_wait_for_wakeup(int port) { if (port == TASK_ID_TO_PD_PORT(task_get_current())) { /* If we are in the PD task, we can directly reset */ @@ -493,6 +489,30 @@ void pd_wait_for_wakeup(int port) } } +void pd_wait_exit_low_power(int port) +{ + if (pd_device_in_low_power(port)) + pd_wait_for_wakeup(port); +} + +/* + * This can be called from any task. If we are in the PD task, we can handle + * immediately. Otherwise, we need to notify the PD task via event. + */ +void pd_device_accessed(int port) +{ + if (port == TASK_ID_TO_PD_PORT(task_get_current())) { + /* Ignore any access to device while it is waking up */ + if (pd[port].flags & PD_FLAGS_LPM_TRANSITION) + return; + + handle_device_access(port); + } else { + task_set_event(PD_PORT_TO_TASK_ID(port), + PD_EVENT_DEVICE_ACCESSED, 0); + } +} + void pd_prevent_low_power_mode(int port, int prevent) { const int current_task_mask = (1 << task_get_current()); |