diff options
author | Nicolas Boichat <drinkcat@google.com> | 2017-07-11 15:38:12 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-08-06 02:33:37 -0700 |
commit | 686e3479f5ee4f9fdec199d15bc1af9a19d16d77 (patch) | |
tree | 1a37f9d5dbc6e89302ea23017b2ed9711b7f4816 | |
parent | a138c618170ecdac06ecaf06f74a1bde06781590 (diff) | |
download | chrome-ec-686e3479f5ee4f9fdec199d15bc1af9a19d16d77.tar.gz |
chip/stm32/usb: Fix resume handler in usb_wake
In the previous version of the code, we were counting ESOF (every
ms) to figure out when to clear the resume bit, and then using ESOF
counts again to wait for the USB interface to resume.
This missed the fact that ESOF (expected SOF) interrupts are not
triggered when SOF are actually received.
Somehow, this worked fine in most cases, except that sometimes the
last ESOF would race with the RXDP/RXDM going to state 2, and we
would not know that the resume completed successfully.
Let's also count SOF interrupts, and also take a received SOF as an
indicator of a successful resume.
While we're at it, trim down USB debugging messages, and add a line
when resume is successful.
BRANCH=none
BUG=b:35587173
TEST=Connect hammer, force autosuspend using:
DEVICE=$(dirname $(grep 5022 /sys/bus/usb/devices/*/idProduct))
echo 500 > $DEVICE/power/autosuspend_delay_ms
echo auto > $DEVICE/power/control
Add debugging in hammer code, make sure that usb_wake_done goes
back to 1 after resume succeeds.
Change-Id: I206c9c6b3066a3a337b6bd2370c9d0c6a9e2396c
Reviewed-on: https://chromium-review.googlesource.com/569522
Commit-Ready: Nicolas Boichat <drinkcat@chromium.org>
Tested-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | chip/stm32/usb.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/chip/stm32/usb.c b/chip/stm32/usb.c index fa292d7aca..d22022de0c 100644 --- a/chip/stm32/usb.c +++ b/chip/stm32/usb.c @@ -324,7 +324,7 @@ static void usb_reset(void) /* See RM0091 Reference Manual 30.5.5 Suspend/Resume events */ static void usb_suspend(void) { - CPRINTF("USB suspend!\n"); + CPRINTF("SUS\n"); /* Set FSUSP bit to activate suspend mode */ STM32_USB_CNTR |= STM32_USB_CNTR_FSUSP; @@ -340,10 +340,7 @@ static void usb_suspend(void) static void usb_resume(void) { - int state = (STM32_USB_FNR & STM32_USB_FNR_RXDP_RXDM_MASK) - >> STM32_USB_FNR_RXDP_RXDM_SHIFT; - - CPRINTF("USB resume %x\n", state); + CPRINTF("RSM\n"); /* * TODO(crosbug.com/p/63273): Reference manual suggests going back to @@ -393,7 +390,7 @@ void usb_wake(void) if (!atomic_read_clear(&usb_wake_done)) return; - CPRINTF("USB wake\n"); + CPRINTF("WAKE\n"); /* * Set RESUME bit for 1 to 15 ms, then clear it. We ask the interrupt @@ -401,7 +398,8 @@ void usb_wake(void) * 2 and 3 ms. */ esof_count = 3; - STM32_USB_CNTR |= STM32_USB_CNTR_RESUME | STM32_USB_CNTR_ESOFM; + STM32_USB_CNTR |= STM32_USB_CNTR_RESUME | + STM32_USB_CNTR_ESOFM | STM32_USB_CNTR_SOFM; /* Try side-band wake as well. */ board_usb_wake(); @@ -438,7 +436,8 @@ void usb_interrupt(void) * per millisecond), then disable RESUME, then wait for resume to * complete. */ - if (status & STM32_USB_ISTR_ESOF && !usb_wake_done) { + if (status & (STM32_USB_ISTR_ESOF | STM32_USB_ISTR_SOF) && + !usb_wake_done) { esof_count--; /* Clear RESUME bit. */ @@ -448,19 +447,30 @@ void usb_interrupt(void) /* Then count down until state is resumed. */ if (esof_count <= 0) { int state; + int good; state = (STM32_USB_FNR & STM32_USB_FNR_RXDP_RXDM_MASK) >> STM32_USB_FNR_RXDP_RXDM_SHIFT; + /* + * state 2, or receiving an SOF, means resume + * completed successfully. + */ + good = (status & STM32_USB_ISTR_SOF) || (state == 2); + /* Either: state is ready, or we timed out. */ - if (state == 2 || state == 3 || + if (good || state == 3 || esof_count <= -USB_RESUME_TIMEOUT_MS) { - STM32_USB_CNTR &= ~STM32_USB_CNTR_ESOFM; + STM32_USB_CNTR &= ~(STM32_USB_CNTR_ESOFM | + STM32_USB_CNTR_SOFM); usb_wake_done = 1; - if (state != 2) { + if (!good) { CPRINTF("wake error: cnt=%d state=%d\n", esof_count, state); usb_suspend(); + } else { + CPRINTF("RSMOK%d %d\n", + -esof_count, state); } } } |