diff options
author | Duncan Laurie <dlaurie@chromium.org> | 2017-06-29 23:52:17 -0700 |
---|---|---|
committer | Duncan Laurie <dlaurie@chromium.org> | 2017-07-01 02:48:50 +0000 |
commit | 7378a1792a986ca5137da9bd0868bbc1b496839d (patch) | |
tree | 344b11bd9ef1f7bf6e8d73e07b6bc581560f49b3 /src | |
parent | b14aefece3079cff4af339c8f5a47d982c7630ea (diff) | |
download | coreboot-7378a1792a986ca5137da9bd0868bbc1b496839d.tar.xz |
ec/google/chromeec: Add support for EC device events
Add support for the new EC device event interface which is used to
report events from devices that are connected behind the EC.
This can be used to differentiate wake sources from the EC in the case
that the EC has the wake pins from various devices.
This can be used in case the AP is unable to directly wake from the
device itself, for example when using the Deep S3 state on Intel
platforms only a few pins can directly wake the AP.
BUG=b:30624430
TEST=build google/* boards that use chrome EC. Feature is used and
tested further in a subsequent commit.
Change-Id: I5126c6d6ffb6b0ef6e8db8dcd5aec62db925a371
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: https://review.coreboot.org/20426
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/ec/google/chromeec/ec.c | 83 | ||||
-rw-r--r-- | src/ec/google/chromeec/ec.h | 6 | ||||
-rw-r--r-- | src/ec/google/chromeec/smihandler.c | 18 | ||||
-rw-r--r-- | src/ec/google/chromeec/smm.h | 7 |
4 files changed, 113 insertions, 1 deletions
diff --git a/src/ec/google/chromeec/ec.c b/src/ec/google/chromeec/ec.c index de17495ff6..2efc66a77c 100644 --- a/src/ec/google/chromeec/ec.c +++ b/src/ec/google/chromeec/ec.c @@ -24,7 +24,6 @@ #include <elog.h> #include <halt.h> #include <reset.h> -#include <elog.h> #include <rtc.h> #include <stdlib.h> #include <vboot/vboot_common.h> @@ -161,6 +160,88 @@ int google_chromeec_clear_events_b(u32 mask) EC_CMD_HOST_EVENT_CLEAR_B, mask); } +/* Get the current device event mask */ +uint32_t google_chromeec_get_device_enabled_events(void) +{ + struct ec_params_device_event req; + struct ec_response_device_event rsp; + struct chromeec_command cmd; + + req.param = EC_DEVICE_EVENT_PARAM_GET_ENABLED_EVENTS; + cmd.cmd_code = EC_CMD_DEVICE_EVENT; + cmd.cmd_version = 0; + cmd.cmd_data_in = &req; + cmd.cmd_size_in = sizeof(req); + cmd.cmd_data_out = &rsp; + cmd.cmd_size_out = sizeof(rsp); + cmd.cmd_dev_index = 0; + + if (google_chromeec_command(&cmd) == 0) + return rsp.event_mask; + return 0; +} + +/* Set the current device event mask */ +int google_chromeec_set_device_enabled_events(uint32_t mask) +{ + struct ec_params_device_event req; + struct ec_response_device_event rsp; + struct chromeec_command cmd; + + req.event_mask = mask; + req.param = EC_DEVICE_EVENT_PARAM_SET_ENABLED_EVENTS; + cmd.cmd_code = EC_CMD_DEVICE_EVENT; + cmd.cmd_version = 0; + cmd.cmd_data_in = &req; + cmd.cmd_size_in = sizeof(req); + cmd.cmd_data_out = &rsp; + cmd.cmd_size_out = sizeof(rsp); + cmd.cmd_dev_index = 0; + + return google_chromeec_command(&cmd); +} + +/* Read and clear pending device events */ +uint32_t google_chromeec_get_device_current_events(void) +{ + struct ec_params_device_event req; + struct ec_response_device_event rsp; + struct chromeec_command cmd; + + req.param = EC_DEVICE_EVENT_PARAM_GET_CURRENT_EVENTS; + cmd.cmd_code = EC_CMD_DEVICE_EVENT; + cmd.cmd_version = 0; + cmd.cmd_data_in = &req; + cmd.cmd_size_in = sizeof(req); + cmd.cmd_data_out = &rsp; + cmd.cmd_size_out = sizeof(rsp); + cmd.cmd_dev_index = 0; + + if (google_chromeec_command(&cmd) == 0) + return rsp.event_mask; + return 0; +} + +void google_chromeec_log_device_events(uint32_t mask) +{ + uint32_t events; + int i; + + if (!IS_ENABLED(CONFIG_ELOG)) + return; + + if (google_chromeec_check_feature(EC_FEATURE_DEVICE_EVENT) != 1) + return; + + events = google_chromeec_get_device_current_events() & mask; + printk(BIOS_INFO, "EC Device Events: 0x%08x\n", events); + + for (i = 0; i < sizeof(events) * 8; i++) { + if (EC_DEVICE_EVENT_MASK(i) & events) + elog_add_event_byte(ELOG_TYPE_EC_DEVICE_EVENT, i); + } +} + int google_chromeec_check_feature(int feature) { struct chromeec_command cmd; diff --git a/src/ec/google/chromeec/ec.h b/src/ec/google/chromeec/ec.h index 4a45f7f4ab..b2b63e8e5f 100644 --- a/src/ec/google/chromeec/ec.h +++ b/src/ec/google/chromeec/ec.h @@ -34,6 +34,12 @@ u8 google_chromeec_get_event(void); int google_ec_running_ro(void); void google_chromeec_init(void); +/* Device events */ +uint32_t google_chromeec_get_device_enabled_events(void); +int google_chromeec_set_device_enabled_events(uint32_t mask); +uint32_t google_chromeec_get_device_current_events(void); +void google_chromeec_log_device_events(uint32_t mask); + /* If recovery mode is enabled and EC is not running RO firmware reboot. */ void google_chromeec_early_init(void); /* Reboot if EC firmware is not expected type. */ diff --git a/src/ec/google/chromeec/smihandler.c b/src/ec/google/chromeec/smihandler.c index 75636ea8c1..379ff68019 100644 --- a/src/ec/google/chromeec/smihandler.c +++ b/src/ec/google/chromeec/smihandler.c @@ -73,6 +73,24 @@ void chromeec_smi_sleep(int slp_type, uint32_t s3_mask, uint32_t s5_mask) clear_pending_events(); } +void chromeec_smi_device_event_sleep(int slp_type, uint32_t s3_mask, + uint32_t s5_mask) +{ + switch (slp_type) { + case ACPI_S3: + /* Enable device wake events */ + google_chromeec_set_device_enabled_events(s3_mask); + break; + case ACPI_S5: + /* Enable device wake events */ + google_chromeec_set_device_enabled_events(s5_mask); + break; + } + + /* Read and clear pending events that may trigger immediate wake */ + google_chromeec_get_device_current_events(); +} + void chromeec_smi_apmc(int apmc, uint32_t sci_mask, uint32_t smi_mask) { switch (apmc) { diff --git a/src/ec/google/chromeec/smm.h b/src/ec/google/chromeec/smm.h index 03d6e0044f..8265cddcfd 100644 --- a/src/ec/google/chromeec/smm.h +++ b/src/ec/google/chromeec/smm.h @@ -28,6 +28,13 @@ void chromeec_smi_process_events(void); void chromeec_smi_sleep(int slp_type, uint32_t s3_mask, uint32_t s5_mask); /* + * Set device event masks according to sleep type, + * and clear any pending device events. + */ +void chromeec_smi_device_event_sleep(int slp_type, uint32_t s3_mask, + uint32_t s5_mask); + +/* * Provided the APMC command do the following while clearing pending events. * APM_CNT_ACPI_ENABLE: clear SMI mask. set SCI mask. * APM_CNT_ACPI_DISABLE: clear SCI mask. set SMI mask. |