summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@google.com>2017-07-11 15:38:12 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-08-06 02:33:37 -0700
commit686e3479f5ee4f9fdec199d15bc1af9a19d16d77 (patch)
tree1a37f9d5dbc6e89302ea23017b2ed9711b7f4816
parenta138c618170ecdac06ecaf06f74a1bde06781590 (diff)
downloadchrome-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.c32
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);
}
}
}