summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2017-07-05 10:19:56 +0200
committerchrome-bot <chrome-bot@chromium.org>2017-07-05 16:45:33 -0700
commit9f59c3df7599d9ecaf4a335556141769c65fee9e (patch)
tree7a5e6fc77955161c9f45560b01c4b7ec5241cc7d
parent67759f3553555a7ea6c3a5296934cbbed2297c68 (diff)
downloadchrome-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>
-rw-r--r--chip/g/idle.c3
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) =