summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@google.com>2017-02-22 16:43:41 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-03-01 09:31:27 -0800
commitbc819424626206be0cdafcb591c0c2fbdfb95642 (patch)
treef62b8955a1894216702f53d6e1e5a426f688c39b
parentb8c255484c59161217becdc29e353424d1f7a364 (diff)
downloadchrome-ec-bc819424626206be0cdafcb591c0c2fbdfb95642.tar.gz
stm32/usb: Add support for remote wake-up
USB uses a special mode the trigger remote wake-up during host suspend, by setting the K-state on the data differential pair, and setting a bit in the USB config descriptor attributes field. Let's enable that so that hammer can wake up host from S3. BRANCH=none BUG=chrome-os-partner:62325 TEST=Connect hammer to chell, put chell in S3. Press a key (or use ("kb 3 3 1; kb 3 3 0" in console), or touch trackpad => host wakes. Change-Id: Ib7b1e9047e01869f07ddd771c9c9bc640eef10d6 Reviewed-on: https://chromium-review.googlesource.com/446240 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/g/usb.c17
-rw-r--r--chip/stm32/usb.c32
-rw-r--r--chip/stm32/usb_dwc.c17
-rw-r--r--chip/stm32/usb_hid_keyboard.c5
-rw-r--r--chip/stm32/usb_hid_touchpad.c5
-rw-r--r--include/config.h6
-rw-r--r--include/usb_api.h8
7 files changed, 63 insertions, 27 deletions
diff --git a/chip/g/usb.c b/chip/g/usb.c
index 0fc4f62242..901a959e92 100644
--- a/chip/g/usb.c
+++ b/chip/g/usb.c
@@ -200,14 +200,6 @@ static void showregs(void)
#define CONFIG_USB_BCD_DEV 0x0100 /* 1.00 */
#endif
-#ifndef USB_BMATTRIBUTES
-#ifdef CONFIG_USB_SELF_POWERED
-#define USB_BMATTRIBUTES 0xc0 /* Self powered. */
-#else
-#define USB_BMATTRIBUTES 0x80 /* Bus powered. */
-#endif
-#endif
-
/* USB Standard Device Descriptor */
static const struct usb_device_descriptor dev_desc = {
.bLength = USB_DT_DEVICE_SIZE,
@@ -234,7 +226,14 @@ const struct usb_config_descriptor USB_CONF_DESC(conf) = {
.bNumInterfaces = USB_IFACE_COUNT,
.bConfigurationValue = 1, /* Caution: hard-coded value */
.iConfiguration = USB_STR_VERSION,
- .bmAttributes = USB_BMATTRIBUTES, /* bus or self powered */
+ .bmAttributes = 0x80 /* Reserved bit */
+#ifdef CONFIG_USB_SELF_POWERED /* bus or self powered */
+ | 0x40
+#endif
+#ifdef CONFIG_USB_REMOTE_WAKEUP
+ | 0x20
+#endif
+ ,
.bMaxPower = (CONFIG_USB_MAXPOWER_MA / 2),
};
diff --git a/chip/stm32/usb.c b/chip/stm32/usb.c
index 4cdfe0828c..ad1e76d65b 100644
--- a/chip/stm32/usb.c
+++ b/chip/stm32/usb.c
@@ -36,14 +36,6 @@
#define CONFIG_USB_BCD_DEV 0x0100 /* 1.00 */
#endif
-#ifndef USB_BMATTRIBUTES
-#ifdef CONFIG_USB_SELF_POWERED
-#define USB_BMATTRIBUTES 0xc0 /* Self powered. */
-#else
-#define USB_BMATTRIBUTES 0x80 /* Bus powered. */
-#endif
-#endif
-
#ifndef CONFIG_USB_SERIALNO
#define USB_STR_SERIALNO 0
#else
@@ -76,7 +68,14 @@ const struct usb_config_descriptor USB_CONF_DESC(conf) = {
.bNumInterfaces = USB_IFACE_COUNT,
.bConfigurationValue = 1,
.iConfiguration = USB_STR_VERSION,
- .bmAttributes = USB_BMATTRIBUTES, /* bus or self powered */
+ .bmAttributes = 0x80 /* Reserved bit */
+#ifdef CONFIG_USB_SELF_POWERED /* bus or self powered */
+ | 0x40
+#endif
+#ifdef CONFIG_USB_REMOTE_WAKEUP
+ | 0x20
+#endif
+ ,
.bMaxPower = (CONFIG_USB_MAXPOWER_MA / 2),
};
@@ -332,6 +331,21 @@ static void usb_resume(void)
/* USB is in use again */
disable_sleep(SLEEP_MASK_USB_DEVICE);
}
+
+#ifdef CONFIG_USB_REMOTE_WAKEUP
+void usb_wake(void)
+{
+ if (!(STM32_USB_CNTR & STM32_USB_CNTR_FSUSP)) {
+ /* USB is already woken up, nothing to do. */
+ return;
+ }
+
+ /* Set RESUME bit for 1 to 15 ms, then clear it. */
+ STM32_USB_CNTR |= STM32_USB_CNTR_RESUME;
+ msleep(5);
+ STM32_USB_CNTR &= ~STM32_USB_CNTR_RESUME;
+}
+#endif
#endif /* CONFIG_USB_SUSPEND */
void usb_interrupt(void)
diff --git a/chip/stm32/usb_dwc.c b/chip/stm32/usb_dwc.c
index 1b009a25cf..7ed0c20c60 100644
--- a/chip/stm32/usb_dwc.c
+++ b/chip/stm32/usb_dwc.c
@@ -52,14 +52,6 @@
#define CONFIG_USB_BCD_DEV 0x0100 /* 1.00 */
#endif
-#ifndef USB_BMATTRIBUTES
-#ifdef CONFIG_USB_SELF_POWERED
-#define USB_BMATTRIBUTES 0xc0 /* Self powered. */
-#else
-#define USB_BMATTRIBUTES 0x80 /* Bus powered. */
-#endif
-#endif
-
#ifndef CONFIG_USB_SERIALNO
#define USB_STR_SERIALNO 0
#else
@@ -93,7 +85,14 @@ const struct usb_config_descriptor USB_CONF_DESC(conf) = {
.bNumInterfaces = USB_IFACE_COUNT,
.bConfigurationValue = 1, /* Caution: hard-coded value */
.iConfiguration = USB_STR_VERSION,
- .bmAttributes = USB_BMATTRIBUTES, /* bus or self powered */
+ .bmAttributes = 0x80 /* Reserved bit */
+#ifdef CONFIG_USB_SELF_POWERED /* bus or self powered */
+ | 0x40
+#endif
+#ifdef CONFIG_USB_REMOTE_WAKEUP
+ | 0x20
+#endif
+ ,
.bMaxPower = (CONFIG_USB_MAXPOWER_MA / 2),
};
diff --git a/chip/stm32/usb_hid_keyboard.c b/chip/stm32/usb_hid_keyboard.c
index 38354815c3..91b8c8ed35 100644
--- a/chip/stm32/usb_hid_keyboard.c
+++ b/chip/stm32/usb_hid_keyboard.c
@@ -165,6 +165,11 @@ static void write_keyboard_report(void)
STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK,
EP_TX_VALID, 0);
}
+
+#ifdef CONFIG_USB_REMOTE_WAKEUP
+ /* Wake up host, if required. */
+ usb_wake();
+#endif
}
static void hid_keyboard_tx(void)
diff --git a/chip/stm32/usb_hid_touchpad.c b/chip/stm32/usb_hid_touchpad.c
index a0fc3b311a..92e1b09886 100644
--- a/chip/stm32/usb_hid_touchpad.c
+++ b/chip/stm32/usb_hid_touchpad.c
@@ -327,6 +327,11 @@ void set_touchpad_report(struct usb_hid_touchpad_report *report)
report, sizeof(*report));
/* enable TX */
STM32_TOGGLE_EP(USB_EP_HID_TOUCHPAD, EP_TX_MASK, EP_TX_VALID, 0);
+
+#ifdef CONFIG_USB_REMOTE_WAKEUP
+ /* Wake up host, if required. */
+ usb_wake();
+#endif
}
static void hid_touchpad_tx(void)
diff --git a/include/config.h b/include/config.h
index 5811e0f2b5..8577194e8a 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2433,6 +2433,12 @@
*/
#undef CONFIG_USB_PORT_POWER_SMART_INVERTED
+/*
+ * Support waking up host by setting the K-state on the data lines (requires
+ * CONFIG_USB_SUSPEND to be set as well).
+ */
+#undef CONFIG_USB_REMOTE_WAKEUP
+
/* Support programmable USB device iSerial field. */
#undef CONFIG_USB_SERIALNO
diff --git a/include/usb_api.h b/include/usb_api.h
index c2e365cf28..a251b3f857 100644
--- a/include/usb_api.h
+++ b/include/usb_api.h
@@ -42,6 +42,14 @@ void usb_disconnect(void);
*/
void usb_release(void);
+/*
+ * Tell the host to wake up. Requires CONFIG_USB_REMOTE_WAKEUP to be defined,
+ * and a chip that implements the function.
+ *
+ * This function sleeps, so it must not be used in interrupt context.
+ */
+void usb_wake(void);
+
#ifdef CONFIG_USB_SELECT_PHY
/* Select which PHY to use. */
void usb_select_phy(uint32_t phy);