| /* 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)); |