summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@google.com>2017-02-22 16:47:27 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-03-01 07:25:03 -0800
commitb8c255484c59161217becdc29e353424d1f7a364 (patch)
tree9599cc58c41139ddfcae5f8e39dd36ac797cfedb
parentc425cbae0be48cf9a9a5b30610c282ced1328d70 (diff)
downloadchrome-ec-b8c255484c59161217becdc29e353424d1f7a364.tar.gz
stm32/usb: Add support for USB suspend
This follows the basics of what is decribed in RM0091 Reference Manual 30.5.5 Suspend/Resume events . We call enable/disable_sleep at suspend/resume, to make sure the EC stays awake when USB is connected and active. We also call clock_enable/disable_module, which is stubbed on stm32f0, but can be used on other devices in the family. This also fixes interrupt handling in usb_interrupt, by only clearing interrupt bits that were handled instead of resetting them all, which is racy, and can potentially lead to issues if reset comes soon after a resume event. BRANCH=none BUG=chrome-os-partner:62325 TEST=build and flash hammer, connect to chell, suspend/resume, and see that hammer prints USB suspend and USB resume lines. Change-Id: Ie9d02fd4a114add3ebc98dc9393680bc9a64a522 Reviewed-on: https://chromium-review.googlesource.com/446239 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/registers.h4
-rw-r--r--chip/stm32/usb-stm32f0.c7
-rw-r--r--chip/stm32/usb-stm32f3.c7
-rw-r--r--chip/stm32/usb-stm32l.c7
-rw-r--r--chip/stm32/usb.c58
-rw-r--r--include/config.h3
6 files changed, 84 insertions, 2 deletions
diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h
index 57193b08af..4f79beb769 100644
--- a/chip/stm32/registers.h
+++ b/chip/stm32/registers.h
@@ -2157,6 +2157,10 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t;
#define STM32_USB_ISTR_CTR (1 << 15)
#define STM32_USB_FNR REG16(STM32_USB_FS_BASE + 0x48)
+
+#define STM32_USB_FNR_RXDP_RXDM_SHIFT (14)
+#define STM32_USB_FNR_RXDP_RXDM_MASK (3 << STM32_USB_FNR_RXDP_RXDM_SHIFT)
+
#define STM32_USB_DADDR REG16(STM32_USB_FS_BASE + 0x4C)
#define STM32_USB_BTABLE REG16(STM32_USB_FS_BASE + 0x50)
#define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54)
diff --git a/chip/stm32/usb-stm32f0.c b/chip/stm32/usb-stm32f0.c
index 1805c74e5e..97bb93cafd 100644
--- a/chip/stm32/usb-stm32f0.c
+++ b/chip/stm32/usb-stm32f0.c
@@ -6,10 +6,14 @@
*/
#include "registers.h"
+#include "system.h"
#include "usb_api.h"
void usb_connect(void)
{
+ /* USB is in use */
+ disable_sleep(SLEEP_MASK_USB_DEVICE);
+
STM32_USB_BCDR |= (1 << 15) /* DPPU */;
}
@@ -17,4 +21,7 @@ void usb_disconnect(void)
{
/* disable pull-up on DP to disconnect */
STM32_USB_BCDR &= ~(1 << 15) /* DPPU */;
+
+ /* USB is off, so sleep whenever */
+ enable_sleep(SLEEP_MASK_USB_DEVICE);
}
diff --git a/chip/stm32/usb-stm32f3.c b/chip/stm32/usb-stm32f3.c
index 8c16bd6b4a..d81548729b 100644
--- a/chip/stm32/usb-stm32f3.c
+++ b/chip/stm32/usb-stm32f3.c
@@ -7,14 +7,21 @@
#include "usb-stm32f3.h"
+#include "system.h"
#include "usb_api.h"
void usb_connect(void)
{
+ /* USB is in use */
+ disable_sleep(SLEEP_MASK_USB_DEVICE);
+
usb_board_connect();
}
void usb_disconnect(void)
{
usb_board_disconnect();
+
+ /* USB is off, so sleep whenever */
+ enable_sleep(SLEEP_MASK_USB_DEVICE);
}
diff --git a/chip/stm32/usb-stm32l.c b/chip/stm32/usb-stm32l.c
index c5d58257cb..0fa3cd0b9d 100644
--- a/chip/stm32/usb-stm32l.c
+++ b/chip/stm32/usb-stm32l.c
@@ -6,10 +6,14 @@
*/
#include "registers.h"
+#include "system.h"
#include "usb_api.h"
void usb_connect(void)
{
+ /* USB is in use */
+ disable_sleep(SLEEP_MASK_USB_DEVICE);
+
STM32_SYSCFG_PMC |= 1;
}
@@ -17,4 +21,7 @@ void usb_disconnect(void)
{
/* disable pull-up on DP to disconnect */
STM32_SYSCFG_PMC &= ~1;
+
+ /* USB is off, so sleep whenever */
+ enable_sleep(SLEEP_MASK_USB_DEVICE);
}
diff --git a/chip/stm32/usb.c b/chip/stm32/usb.c
index ea34877c6d..4cdfe0828c 100644
--- a/chip/stm32/usb.c
+++ b/chip/stm32/usb.c
@@ -12,6 +12,7 @@
#include "hooks.h"
#include "link_defs.h"
#include "registers.h"
+#include "system.h"
#include "task.h"
#include "timer.h"
#include "util.h"
@@ -292,6 +293,47 @@ static void usb_reset(void)
CPRINTF("RST EP0 %04x\n", STM32_USB_EP(0));
}
+#ifdef CONFIG_USB_SUSPEND
+/* See RM0091 Reference Manual 30.5.5 Suspend/Resume events */
+static void usb_suspend(void)
+{
+ CPRINTF("USB suspend!\n");
+
+ /* Set FSUSP bit to activate suspend mode */
+ STM32_USB_CNTR |= STM32_USB_CNTR_FSUSP;
+
+ /* Set USB low power mode */
+ STM32_USB_CNTR |= STM32_USB_CNTR_LP_MODE;
+
+ clock_enable_module(MODULE_USB, 0);
+
+ /* USB is not in use anymore, we can (hopefully) sleep now. */
+ enable_sleep(SLEEP_MASK_USB_DEVICE);
+}
+
+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);
+
+ /*
+ * TODO(crosbug.com/p/63273): Reference manual suggests going back to
+ * sleep if state is 10 or 11, but this seems to cause other problems
+ * (see bug). Ignore them for now.
+ */
+
+ clock_enable_module(MODULE_USB, 1);
+
+ /* Clear FSUSP bit to exit suspend mode */
+ STM32_USB_CNTR &= ~STM32_USB_CNTR_FSUSP;
+
+ /* USB is in use again */
+ disable_sleep(SLEEP_MASK_USB_DEVICE);
+}
+#endif /* CONFIG_USB_SUSPEND */
+
void usb_interrupt(void)
{
uint16_t status = STM32_USB_ISTR;
@@ -299,6 +341,14 @@ void usb_interrupt(void)
if (status & STM32_USB_ISTR_RESET)
usb_reset();
+#ifdef CONFIG_USB_SUSPEND
+ if (status & STM32_USB_ISTR_SUSP)
+ usb_suspend();
+
+ if (status & STM32_USB_ISTR_WKUP)
+ usb_resume();
+#endif
+
if (status & STM32_USB_ISTR_CTR) {
int ep = status & STM32_USB_ISTR_EP_ID_MASK;
if (ep < USB_EP_COUNT) {
@@ -311,8 +361,8 @@ void usb_interrupt(void)
/* task_set_event(, 1 << ep_task); */
}
- /* ack interrupts */
- STM32_USB_ISTR = 0;
+ /* ack only interrupts that we handled */
+ STM32_USB_ISTR = ~status;
}
DECLARE_IRQ(STM32_IRQ_USB_LP, usb_interrupt, 1);
@@ -350,6 +400,10 @@ void usb_init(void)
STM32_USB_CNTR = STM32_USB_CNTR_CTRM |
STM32_USB_CNTR_PMAOVRM |
STM32_USB_CNTR_ERRM |
+#ifdef CONFIG_USB_SUSPEND
+ STM32_USB_CNTR_WKUPM |
+ STM32_USB_CNTR_SUSPM |
+#endif
STM32_USB_CNTR_RESETM;
#ifdef CONFIG_USB_SERIALNO
diff --git a/include/config.h b/include/config.h
index d9597d01cd..5811e0f2b5 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2442,6 +2442,9 @@
/* Support reporting as self powered in USB configuration. */
#undef CONFIG_USB_SELF_POWERED
+/* Support correct handling of USB suspend (host-initiated). */
+#undef CONFIG_USB_SUSPEND
+
/* Default pull-up value on the USB-C ports when they are used as source. */
#define CONFIG_USB_PD_PULLUP TYPEC_RP_1A5
/*