summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2014-10-20 23:31:28 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-10-24 01:37:58 +0000
commitd1ed75815efe513449c653d28fe7bd3c53a3441d (patch)
tree48a256c4154ad8f195ef5447abce6eeb99e3fd42
parentbe2ed33b1976e407d107b20e90441a194f7b5fb7 (diff)
downloadchrome-ec-d1ed75815efe513449c653d28fe7bd3c53a3441d.tar.gz
MKBP event signalling implementation
This implements a new API for EC modules to define MKBP event sources and send MKBP event to the AP. Also, a new host command EC_CMD_GET_NEXT_EVENT is added for the AP to query the pending MKBP events. Each event type may have custom event data sent along with the event. BRANCH=None BUG=chrome-os-partner:33194 TEST=Enable MKBP event on Ryu. Set a host event from EC console, run 'ectool nextevent', and see MKBP event 0x01 (HOST_EVENT) and the set host event. Signed-off-by: Vic Yang <victoryang@chromium.org> Change-Id: I28a1b7e826bcc102bbe39016c9bb3e37d125664c Reviewed-on: https://chromium-review.googlesource.com/224905 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--common/build.mk1
-rw-r--r--common/host_event_commands.c18
-rw-r--r--common/keyboard_mkbp.c24
-rw-r--r--common/mkbp_event.c95
-rw-r--r--core/cortex-m/ec.lds.S5
-rw-r--r--core/cortex-m0/ec.lds.S5
-rw-r--r--include/config.h3
-rw-r--r--include/ec_commands.h23
-rw-r--r--include/link_defs.h5
-rw-r--r--include/mkbp_event.h37
-rw-r--r--util/ectool.c26
11 files changed, 241 insertions, 1 deletions
diff --git a/common/build.mk b/common/build.mk
index ed2fb92456..267de3a7bf 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -54,6 +54,7 @@ common-$(CONFIG_LED_COMMON)+=led_common.o
common-$(CONFIG_LID_ANGLE_KEY_SCAN)+=lid_angle.o
common-$(CONFIG_LID_SWITCH)+=lid_switch.o
common-$(CONFIG_LPC)+=acpi.o port80.o
+common-$(CONFIG_MKBP_EVENT)+=mkbp_event.o
common-$(CONFIG_ONEWIRE)+=onewire.o
common-$(CONFIG_POWER_BUTTON)+=power_button.o
common-$(CONFIG_POWER_BUTTON_X86)+=power_button_x86.o
diff --git a/common/host_event_commands.c b/common/host_event_commands.c
index 7d369b60db..feb1d93552 100644
--- a/common/host_event_commands.c
+++ b/common/host_event_commands.c
@@ -10,6 +10,7 @@
#include "console.h"
#include "host_command.h"
#include "lpc.h"
+#include "mkbp_event.h"
#include "util.h"
/* Console output macros */
@@ -51,6 +52,10 @@ void host_set_events(uint32_t mask)
#else
*(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = events;
#endif
+
+#ifdef CONFIG_MKBP_EVENT
+ mkbp_send_event(EC_MKBP_EVENT_HOST_EVENT);
+#endif
}
void host_clear_events(uint32_t mask)
@@ -66,7 +71,20 @@ void host_clear_events(uint32_t mask)
#else
*(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = events;
#endif
+
+#ifdef CONFIG_MKBP_EVENT
+ mkbp_send_event(EC_MKBP_EVENT_HOST_EVENT);
+#endif
+}
+
+static int host_get_next_event(uint8_t *out)
+{
+ uint32_t event_out = events;
+ memcpy(out, &event_out, sizeof(event_out));
+ atomic_clear(&events, event_out);
+ return sizeof(event_out);
}
+DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_HOST_EVENT, host_get_next_event);
/**
* Clear one or more host event bits from copy B.
diff --git a/common/keyboard_mkbp.c b/common/keyboard_mkbp.c
index 7e9f6f5c45..82fc93bdf2 100644
--- a/common/keyboard_mkbp.c
+++ b/common/keyboard_mkbp.c
@@ -15,6 +15,7 @@
#include "keyboard_raw.h"
#include "keyboard_scan.h"
#include "keyboard_test.h"
+#include "mkbp_event.h"
#include "system.h"
#include "task.h"
#include "timer.h"
@@ -146,12 +147,33 @@ test_mockable int keyboard_fifo_add(const uint8_t *buffp)
kb_fifo_push_done:
- if (ret == EC_SUCCESS)
+ if (ret == EC_SUCCESS) {
set_host_interrupt(1);
+#ifdef CONFIG_MKBP_EVENT
+ mkbp_send_event(EC_MKBP_EVENT_KEY_MATRIX);
+#endif
+ }
return ret;
}
+#ifdef CONFIG_MKBP_EVENT
+static int keyboard_get_next_event(uint8_t *out)
+{
+ if (!kb_fifo_entries)
+ return -1;
+
+ kb_fifo_remove(out);
+
+ /* Keep sending events if FIFO is not empty */
+ if (kb_fifo_entries)
+ mkbp_send_event(EC_MKBP_EVENT_KEY_MATRIX);
+
+ return KEYBOARD_COLS;
+}
+DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_KEY_MATRIX, keyboard_get_next_event);
+#endif
+
void keyboard_send_battery_key(void)
{
uint8_t state[KEYBOARD_COLS];
diff --git a/common/mkbp_event.c b/common/mkbp_event.c
new file mode 100644
index 0000000000..d78db48a2d
--- /dev/null
+++ b/common/mkbp_event.c
@@ -0,0 +1,95 @@
+/* Copyright (c) 2014 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.
+ *
+ * Event handling in MKBP keyboard protocol
+ */
+
+#include "atomic.h"
+#include "gpio.h"
+#include "host_command.h"
+#include "link_defs.h"
+#include "mkbp_event.h"
+#include "util.h"
+
+static uint32_t events;
+
+static void set_event(uint8_t event_type)
+{
+ atomic_or(&events, 1 << event_type);
+}
+
+static void clear_event(uint8_t event_type)
+{
+ atomic_clear(&events, 1 << event_type);
+}
+
+static int event_is_set(uint8_t event_type)
+{
+ return events & (1 << event_type);
+}
+
+/**
+ * Assert host keyboard interrupt line.
+ */
+static void set_host_interrupt(int active)
+{
+ /* interrupt host by using active low EC_INT signal */
+ gpio_set_level(GPIO_EC_INT, !active);
+}
+
+void mkbp_send_event(uint8_t event_type)
+{
+ set_event(event_type);
+ set_host_interrupt(1);
+}
+
+static int mkbp_get_next_event(struct host_cmd_handler_args *args)
+{
+ static int last;
+ int i, data_size, evt;
+ uint8_t *resp = args->response;
+ const struct mkbp_event_source *src;
+
+ /*
+ * Find the next event to service. We do this in a round-robin
+ * way to make sure no event gets starved.
+ */
+ for (i = 0; i < EC_MKBP_EVENT_COUNT; ++i)
+ if (event_is_set((last + i) % EC_MKBP_EVENT_COUNT))
+ break;
+
+ if (i == EC_MKBP_EVENT_COUNT)
+ return EC_RES_ERROR;
+
+ evt = (i + last) % EC_MKBP_EVENT_COUNT;
+ last = evt + 1;
+
+ /*
+ * Clear the event before retrieving the event data in case the
+ * event source wants to send the same event.
+ */
+ clear_event(evt);
+
+ for (src = __mkbp_evt_srcs; src < __mkbp_evt_srcs_end; ++src)
+ if (src->event_type == evt)
+ break;
+
+ if (src == __mkbp_evt_srcs_end)
+ return EC_RES_ERROR;
+
+ resp[0] = evt; /* Event type */
+ data_size = src->get_data(resp + 1);
+ if (data_size < 0)
+ return EC_RES_ERROR;
+ args->response_size = 1 + data_size;
+
+ if (!events)
+ set_host_interrupt(0);
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_GET_NEXT_EVENT,
+ mkbp_get_next_event,
+ EC_VER_MASK(0));
+
diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S
index ad0de62289..9eda0bc8c9 100644
--- a/core/cortex-m/ec.lds.S
+++ b/core/cortex-m/ec.lds.S
@@ -58,6 +58,11 @@ SECTIONS
KEEP(*(.rodata.hcmds))
__hcmds_end = .;
+ . = ALIGN(4);
+ __mkbp_evt_srcs = .;
+ KEEP(*(.rodata.evtsrcs))
+ __mkbp_evt_srcs_end = .;
+
. = ALIGN(4);
__hooks_init = .;
KEEP(*(.rodata.HOOK_INIT))
diff --git a/core/cortex-m0/ec.lds.S b/core/cortex-m0/ec.lds.S
index a2e372ad8a..fc858216f2 100644
--- a/core/cortex-m0/ec.lds.S
+++ b/core/cortex-m0/ec.lds.S
@@ -58,6 +58,11 @@ SECTIONS
KEEP(*(.rodata.hcmds))
__hcmds_end = .;
+ . = ALIGN(4);
+ __mkbp_evt_srcs = .;
+ KEEP(*(.rodata.evtsrcs))
+ __mkbp_evt_srcs_end = .;
+
. = ALIGN(4);
__hooks_init = .;
KEEP(*(.rodata.HOOK_INIT))
diff --git a/include/config.h b/include/config.h
index e6c0aa8583..7f637423d8 100644
--- a/include/config.h
+++ b/include/config.h
@@ -751,6 +751,9 @@
/* Support LPC interface */
#undef CONFIG_LPC
+/* Support MKBP event */
+#undef CONFIG_MKBP_EVENT
+
/* Support memory protection unit (MPU) */
#undef CONFIG_MPU
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 3675dfa6d9..3cea697cf9 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1811,6 +1811,29 @@ struct ec_result_keyscan_seq_ctrl {
};
} __packed;
+/*
+ * Get the next pending MKBP event.
+ *
+ * Returns EC_RES_UNAVAILABLE if there is no event pending.
+ */
+#define EC_CMD_GET_NEXT_EVENT 0x67
+
+enum ec_mkbp_event {
+ /* Keyboard matrix changed. The event data is the new matrix state. */
+ EC_MKBP_EVENT_KEY_MATRIX = 0,
+
+ /* New host event. The event data is 4 bytes of host event flags. */
+ EC_MKBP_EVENT_HOST_EVENT = 1,
+
+ /* Number of MKBP events */
+ EC_MKBP_EVENT_COUNT,
+};
+
+struct ec_response_get_next_event {
+ uint8_t event_type;
+ /* Followed by event data if any */
+} __packed;
+
/*****************************************************************************/
/* Temperature sensor commands */
diff --git a/include/link_defs.h b/include/link_defs.h
index 0aab55befe..67ae9779d2 100644
--- a/include/link_defs.h
+++ b/include/link_defs.h
@@ -11,6 +11,7 @@
#include "console.h"
#include "hooks.h"
#include "host_command.h"
+#include "mkbp_event.h"
#include "task.h"
#include "test_util.h"
@@ -75,6 +76,10 @@ extern const struct test_i2c_read_string_dev __test_i2c_read_string_end[];
extern const struct host_command __hcmds[];
extern const struct host_command __hcmds_end[];
+/* MKBP events */
+extern const struct mkbp_event_source __mkbp_evt_srcs[];
+extern const struct mkbp_event_source __mkbp_evt_srcs_end[];
+
/* IRQs (interrupt handlers) */
extern const struct irq_priority __irqprio[];
extern const struct irq_priority __irqprio_end[];
diff --git a/include/mkbp_event.h b/include/mkbp_event.h
new file mode 100644
index 0000000000..8da19fc02d
--- /dev/null
+++ b/include/mkbp_event.h
@@ -0,0 +1,37 @@
+/* Copyright 2014 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.
+ *
+ * Event handling in MKBP keyboard protocol
+ */
+
+#ifndef __CROS_EC_MKBP_EVENT_H
+#define __CROS_EC_MKBP_EVENT_H
+
+/*
+ * Sends an event to the AP.
+ *
+ * When this is called, the event data must be ready for query. Otherwise,
+ * when the AP queries the event, an error is returned and the event is lost.
+ *
+ * @param event_type One of EC_MKBP_EVENT_*.
+ */
+void mkbp_send_event(uint8_t event_type);
+
+/*
+ * The struct to store the event source definition. The get_data routine is
+ * responsible for returning the event data when queried by the AP. The
+ * parameter 'data' points to where the event data needs to be stored, and
+ * the size of the event data should be returned.
+ */
+struct mkbp_event_source {
+ uint8_t event_type;
+ int (*get_data)(uint8_t *data);
+};
+
+#define DECLARE_EVENT_SOURCE(type, func) \
+ const struct mkbp_event_source __evt_src_##type \
+ __attribute__((section(".rodata.evtsrcs"))) \
+ = {type, func}
+
+#endif /* __CROS_EC_MKBP_EVENT_H */
diff --git a/util/ectool.c b/util/ectool.c
index c873677438..526807566f 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -2593,6 +2593,31 @@ static int cmd_motionsense(int argc, char **argv)
return ms_help(argv[0]);
}
+int cmd_next_event(int argc, char *argv[])
+{
+ uint8_t *rdata = (uint8_t *)ec_inbuf;
+ int rv;
+ int i;
+
+ rv = ec_command(EC_CMD_GET_NEXT_EVENT, 0,
+ NULL, 0, rdata, ec_max_insize);
+ if (rv < 0)
+ return rv;
+
+ printf("Next event is 0x%02x\n", rdata[0]);
+ if (rv > 1) {
+ printf("Event data:\n");
+ for (i = 1; i < rv; ++i) {
+ printf("%02x ", rdata[i]);
+ if (!(i & 0xf))
+ printf("\n");
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
+
static int find_led_color_by_name(const char *color)
{
int i;
@@ -5026,6 +5051,7 @@ const struct command commands[] = {
{"keyconfig", cmd_keyconfig},
{"keyscan", cmd_keyscan},
{"motionsense", cmd_motionsense},
+ {"nextevent", cmd_next_event},
{"panicinfo", cmd_panic_info},
{"pause_in_s5", cmd_s5},
{"port80read", cmd_port80_read},