diff options
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | common/device_event.c | 129 | ||||
-rw-r--r-- | common/host_command.c | 3 | ||||
-rw-r--r-- | include/config.h | 4 | ||||
-rw-r--r-- | include/device_event.h | 44 | ||||
-rw-r--r-- | include/ec_commands.h | 35 |
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 */ |