summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@google.com>2017-06-29 07:14:58 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-06-30 03:08:42 -0700
commitbbb759ceaa843f548f90c35d1668e17c8879bad3 (patch)
tree7e1b84d8cd73740c01d3cad2398666581f16cee4
parent5e5788f3cac7fecd45072807bb6a79ce2b767961 (diff)
downloadchrome-ec-bbb759ceaa843f548f90c35d1668e17c8879bad3.tar.gz
Add support for reporting device events
In order to report specific wake events from differernt devices add a host command that allows setting device event mask, and triggering a host event when that device event is set. This is done as a separate command and mask because we are running out of host events, and it takes over the unused thermal overload event that was never used in EC or BIOS. The first use case for this is platforms that have AP wake events that go to the EC, for instance devices that use Deep S3 and have a limited set of wake pins. (such as Eve) This allows the AP to determine the exact wake source for an event so it can be logged and acted on by the AP if necessary. BUG=b:36024430 BRANCH=eve TEST=manual testing on eve with trackpad and dsp wake events Change-Id: I48d94014c00dc1dad098ab96af0ddc7860229762 Signed-off-by: Duncan Laurie <dlaurie@google.com> Reviewed-on: https://chromium-review.googlesource.com/555632 Reviewed-by: Scott Collyer <scollyer@chromium.org>
-rw-r--r--common/build.mk1
-rw-r--r--common/device_event.c129
-rw-r--r--common/host_command.c3
-rw-r--r--include/config.h4
-rw-r--r--include/device_event.h44
-rw-r--r--include/ec_commands.h35
6 files changed, 215 insertions, 1 deletions
diff --git a/common/build.mk b/common/build.mk
index cc190e08d6..d264c6c2e5 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -45,6 +45,7 @@ common-$(CONFIG_COMMON_RUNTIME)+=hooks.o main.o system.o
common-$(CONFIG_COMMON_TIMER)+=timer.o
common-$(CONFIG_CRC8)+= crc8.o
common-$(CONFIG_CURVE25519)+=curve25519.o
+common-$(CONFIG_DEVICE_EVENT)+=device_event.o
common-$(CONFIG_DEVICE_STATE)+=device_state.o
common-$(CONFIG_DPTF)+=dptf.o
common-$(CONFIG_EXTENSION_COMMAND)+=extension.o
diff --git a/common/device_event.c b/common/device_event.c
new file mode 100644
index 0000000000..4b4e37724c
--- /dev/null
+++ b/common/device_event.c
@@ -0,0 +1,129 @@
+/* Copyright (c) 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Device event commands for Chrome EC */
+
+#include "atomic.h"
+#include "common.h"
+#include "console.h"
+#include "host_command.h"
+#include "lpc.h"
+#include "mkbp_event.h"
+#include "util.h"
+
+/* Console output macros */
+#define CPUTS(outstr) cputs(CC_EVENTS, outstr)
+#define CPRINTS(format, args...) cprints(CC_EVENTS, format, ## args)
+
+static uint32_t device_current_events;
+static uint32_t device_enabled_events;
+
+uint32_t device_get_current_events(void)
+{
+ return device_current_events;
+}
+
+static uint32_t device_get_and_clear_events(void)
+{
+ return atomic_read_clear(&device_current_events);
+}
+
+static uint32_t device_get_enabled_events(void)
+{
+ return device_enabled_events;
+}
+
+void device_set_events(uint32_t mask)
+{
+ /* Ignore events that are not enabled */
+ mask &= device_enabled_events;
+
+ if ((device_current_events & mask) != mask)
+ CPRINTS("device event set 0x%08x", mask);
+
+ atomic_or(&device_current_events, mask);
+
+ /* Signal host that a device event is pending */
+ host_set_single_event(EC_HOST_EVENT_DEVICE);
+}
+
+void device_clear_events(uint32_t mask)
+{
+ /* Only print if something's about to change */
+ if (device_current_events & mask)
+ CPRINTS("device event clear 0x%08x", mask);
+
+ atomic_clear(&device_current_events, mask);
+}
+
+static void device_set_enabled_events(uint32_t mask)
+{
+ if ((device_enabled_events & mask) != mask)
+ CPRINTS("device enabled events set 0x%08x", mask);
+
+ device_enabled_events = mask;
+}
+
+/*****************************************************************************/
+/* Console commands */
+
+#ifdef CONFIG_CMD_DEVICE_EVENT
+static int command_device_event(int argc, char **argv)
+{
+ /* Handle sub-commands */
+ if (argc == 3) {
+ char *e;
+ int i = strtoi(argv[2], &e, 0);
+
+ if (*e)
+ return EC_ERROR_PARAM2;
+ else if (!strcasecmp(argv[1], "set"))
+ device_set_events(i);
+ else if (!strcasecmp(argv[1], "clear"))
+ device_clear_events(i);
+ else if (!strcasecmp(argv[1], "enable"))
+ device_set_enabled_events(i);
+ else
+ return EC_ERROR_PARAM1;
+ }
+
+ ccprintf("Enabled Events: 0x%08x\n", device_get_enabled_events());
+ ccprintf("Current Events: 0x%08x\n", device_get_current_events());
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(deviceevent, command_device_event,
+ "[set | clear | enable] [mask]",
+ "Print / set device event state");
+#endif
+
+/*****************************************************************************/
+/* Host commands */
+
+static int device_event_cmd(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_device_event *p = args->params;
+ struct ec_response_device_event *r = args->response;
+
+ switch (p->param) {
+ case EC_DEVICE_EVENT_PARAM_GET_CURRENT_EVENTS:
+ r->event_mask = device_get_and_clear_events();
+ break;
+ case EC_DEVICE_EVENT_PARAM_GET_ENABLED_EVENTS:
+ r->event_mask = device_get_enabled_events();
+ break;
+ case EC_DEVICE_EVENT_PARAM_SET_ENABLED_EVENTS:
+ device_set_enabled_events(p->event_mask);
+ r->event_mask = device_get_enabled_events();
+ break;
+ default:
+ return EC_RES_INVALID_PARAM;
+ }
+
+ args->response_size = sizeof(*r);
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_DEVICE_EVENT, device_event_cmd, EC_VER_MASK(0));
diff --git a/common/host_command.c b/common/host_command.c
index 06d687f51e..825515a66f 100644
--- a/common/host_command.c
+++ b/common/host_command.c
@@ -805,6 +805,9 @@ static int host_command_get_features(struct host_cmd_handler_args *args)
#ifdef HAS_TASK_RWSIG
| EC_FEATURE_MASK_0(EC_FEATURE_RWSIG)
#endif
+#ifdef CONFIG_DEVICE_EVENT
+ | EC_FEATURE_MASK_0(EC_FEATURE_DEVICE_EVENT)
+#endif
;
return EC_RES_SUCCESS;
}
diff --git a/include/config.h b/include/config.h
index 49f3c8c96f..5d41162d04 100644
--- a/include/config.h
+++ b/include/config.h
@@ -677,6 +677,7 @@
#undef CONFIG_CMD_CLOCKGATES
#undef CONFIG_CMD_COMXTEST
#define CONFIG_CMD_CRASH
+#define CONFIG_CMD_DEVICE_EVENT
#undef CONFIG_CMD_ECTEMP
#define CONFIG_CMD_FASTCHARGE
#undef CONFIG_CMD_FLASH
@@ -941,6 +942,9 @@
/*****************************************************************************/
+/* Support events from devices attached to the EC */
+#undef CONFIG_DEVICE_EVENT
+
/* Monitor the states of other devices */
#undef CONFIG_DEVICE_STATE
diff --git a/include/device_event.h b/include/device_event.h
new file mode 100644
index 0000000000..40d4114b16
--- /dev/null
+++ b/include/device_event.h
@@ -0,0 +1,44 @@
+/* Copyright (c) 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Device event module for Chrome EC */
+
+#ifndef __CROS_EC_DEVICE_EVENT_H
+#define __CROS_EC_DEVICE_EVENT_H
+
+#include "common.h"
+#include "ec_commands.h"
+
+/**
+ * Return the raw device event state.
+ */
+uint32_t device_get_events(void);
+
+/**
+ * Set one or more device event bits.
+ *
+ * @param mask Event bits to set (use EC_DEVICE_EVENT_MASK()).
+ */
+void device_set_events(uint32_t mask);
+
+/**
+ * Clear one or more device event bits.
+ *
+ * @param mask Event bits to clear (use EC_DEVICE_EVENT_MASK()).
+ * Write 1 to a bit to clear it.
+ */
+void device_clear_events(uint32_t mask);
+
+/**
+ * Set a single device event.
+ *
+ * @param event Event to set (EC_DEVICE_EVENT_*).
+ */
+static inline void device_set_single_event(int event)
+{
+ device_set_events(EC_DEVICE_EVENT_MASK(event));
+}
+
+#endif /* __CROS_EC_DEVICE_EVENT_H */
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 61bfa345fe..3bc98ae31a 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -502,7 +502,8 @@ enum host_event_code {
EC_HOST_EVENT_BATTERY_CRITICAL = 7,
EC_HOST_EVENT_BATTERY = 8,
EC_HOST_EVENT_THERMAL_THRESHOLD = 9,
- EC_HOST_EVENT_THERMAL_OVERLOAD = 10,
+ /* Event generated by a device attached to the EC */
+ EC_HOST_EVENT_DEVICE = 10,
EC_HOST_EVENT_THERMAL = 11,
EC_HOST_EVENT_USB_CHARGER = 12,
EC_HOST_EVENT_KEY_PRESSED = 13,
@@ -1086,6 +1087,8 @@ enum ec_feature_code {
EC_FEATURE_TOUCHPAD = 29,
/* The MCU has RWSIG task enabled */
EC_FEATURE_RWSIG = 30,
+ /* EC has device events support */
+ EC_FEATURE_DEVICE_EVENT = 31,
};
#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
@@ -3525,6 +3528,36 @@ struct __ec_align1 ec_params_host_sleep_event {
};
/*****************************************************************************/
+/* Device events */
+#define EC_CMD_DEVICE_EVENT 0x00AA
+
+enum ec_device_event {
+ EC_DEVICE_EVENT_TRACKPAD,
+ EC_DEVICE_EVENT_DSP,
+ EC_DEVICE_EVENT_WIFI,
+};
+
+enum ec_device_event_param {
+ /* Get and clear pending device events */
+ EC_DEVICE_EVENT_PARAM_GET_CURRENT_EVENTS,
+ /* Get device event mask */
+ EC_DEVICE_EVENT_PARAM_GET_ENABLED_EVENTS,
+ /* Set device event mask */
+ EC_DEVICE_EVENT_PARAM_SET_ENABLED_EVENTS,
+};
+
+#define EC_DEVICE_EVENT_MASK(event_code) (1UL << (event_code % 32))
+
+struct __ec_align_size1 ec_params_device_event {
+ uint32_t event_mask;
+ uint8_t param;
+};
+
+struct __ec_align4 ec_response_device_event {
+ uint32_t event_mask;
+};
+
+/*****************************************************************************/
/* Smart battery pass-through */
/* Get / Set 16-bit smart battery registers */