diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2017-07-05 10:19:56 +0200 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-07-05 16:45:33 -0700 |
commit | 9f59c3df7599d9ecaf4a335556141769c65fee9e (patch) | |
tree | 7a5e6fc77955161c9f45560b01c4b7ec5241cc7d /chip | |
parent | 67759f3553555a7ea6c3a5296934cbbed2297c68 (diff) | |
download | chrome-ec-9f59c3df7599d9ecaf4a335556141769c65fee9e.tar.gz |
g: mitigate deep-sleep abortions when using USB
After entering prepare_to_sleep() and doing interrupt_disable(), if an
interrupt happens, it will stay pending (as the handler is masked).
Then, when calling 'wfi' in __idle(), we will go through the instruction
rather than entering deep-sleep (if requested) as we have a pending
interrupt.
The downside of this corner case is that we never undo the actions done
to prepare for deep-sleep in the IDLE_DEEP_SLEEP clause of
prepare_to_sleep(). For USB suspend, this means that on the subsequent
deep-sleep entry, we are going to try to save GR_USB_CFG/the USB
device address while the USB controller is already in reset/power-down,
recording a null value in SCRATCH18. Then, at resume time, we will
restore 0 in USB_CFG and the USB device will no longer work.
As the USB configuration is difficult to restore in case of deep-sleep
abortion, simply skip writing a bogus value in SCRATCH18 on the real
deep-sleep entry happening afterwards. This is good enough to resume
properly on USB.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BRANCH=cr50
BUG=b:38160821
TEST=manual: add a (long) panic_printf trace in prepare_to_sleep() in
order to dramatically increase the probability of getting an
interruption pending after entering the function. On cr52, trigger USB
suspends by suspending the host, and see we no longer regularly get a
null USB device address at USB resume.
Change-Id: Ied3fc003eefe7fc164a320b15b5f9d400551198e
Reviewed-on: https://chromium-review.googlesource.com/559332
Commit-Ready: Vincent Palatin <vpalatin@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Marius Schilder <mschilder@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/g/idle.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/chip/g/idle.c b/chip/g/idle.c index f2bd6fe3bd..ebdb747278 100644 --- a/chip/g/idle.c +++ b/chip/g/idle.c @@ -122,7 +122,8 @@ static void prepare_to_sleep(void) * need is the device address, since everything else can be * reinitialized on resume. */ - GREG32(PMU, PWRDN_SCRATCH18) = GR_USB_DCFG; + if (!GREAD_FIELD(USB, PCGCCTL, RSTPDWNMODULE)) + GREG32(PMU, PWRDN_SCRATCH18) = GR_USB_DCFG; /* Increment the deep sleep count */ GREG32(PMU, PWRDN_SCRATCH17) = |