summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFurquan Shaikh <furquan@chromium.org>2017-10-13 13:08:34 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-04-16 09:20:28 +0000
commit161f09ca3e9726c122e0d1b8e05aecb3d1f2959c (patch)
tree3cf3e3d47dc1f6d3462aeed66aef7f1529533bcd
parentd5b068339e08b61864c4bd2ec1a89dad4e0da2de (diff)
downloadchrome-ec-161f09ca3e9726c122e0d1b8e05aecb3d1f2959c.tar.gz
host_event_commands: Add support for always reporting masks
Add a new mask type (ALWAYS_REPORT mask) that is set by default to certain host events that should always be reported to the host irrespective of the state of SCI, SMI and wake masks. This mask includes host events like critical events resulting in shutdown or reboot, events that are consumed by BIOS, etc. Now that ALWAYS_REPORT mask is added, this change also updates the way EC manages set/query operations for host events: 1. During set operation, EC will check if the host event is present in any of the 4 masks - SCI, SMI, wake and always report. If yes, then it is set in hostevents. 2. During query operation, EC will extract the lowest set event from hostevents, clear it and return it back to the host. In order to reflect the above change in EC behavior, a new feature bit is used EC_FEATURE_UNIFIED_WAKE_MASKS. This allows the host to decide when wake mask needs to be set before checking for host events. BUG=None BRANCH=None TEST=make -j buildall. Also verified following: 1. Wake from S3 works as expected. Host is able to log correct wake sources (Verified power button, lid open, base key press and tablet mode change on soraka). 2. Wake from S5 works as expected. Host is able to log correct wake sources (Verified power button, lid open on soraka). 3. Wake from S0ix works as expected (Verified power button, lid open on soraka). 4. Software method to trigger recovery still works fine: reboot ap-off hostevent set 0x4000 powerb Change-Id: Ifcc9b0a974373e169b8f2f35120fcef9f66d47d8 Signed-off-by: Furquan Shaikh <furquan@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/719578 Reviewed-by: Aaron Durbin <adurbin@chromium.org> (cherry picked from commit 5bd5f1b1fa005dbe1cc3c763919270e01a38b8d2) Reviewed-on: https://chromium-review.googlesource.com/989864 Reviewed-by: Joel Kitching <kitching@chromium.org> Commit-Queue: Joel Kitching <kitching@chromium.org> Tested-by: Joel Kitching <kitching@chromium.org> Trybot-Ready: Joel Kitching <kitching@chromium.org>
-rw-r--r--common/ec_features.c2
-rw-r--r--common/host_event_commands.c131
-rw-r--r--include/ec_commands.h2
-rw-r--r--include/lpc.h8
4 files changed, 109 insertions, 34 deletions
diff --git a/common/ec_features.c b/common/ec_features.c
index 01d666a9dc..8715fecd34 100644
--- a/common/ec_features.c
+++ b/common/ec_features.c
@@ -116,7 +116,7 @@ uint32_t get_feature_flags0(void)
uint32_t get_feature_flags1(void)
{
- uint32_t result = 0;
+ uint32_t result = EC_FEATURE_MASK_1(EC_FEATURE_UNIFIED_WAKE_MASKS);
#ifdef CONFIG_EC_FEATURE_BOARD_OVERRIDE
result = board_override_feature_flags1(result);
#endif
diff --git a/common/host_event_commands.c b/common/host_event_commands.c
index 714eaf42ec..d2fa584855 100644
--- a/common/host_event_commands.c
+++ b/common/host_event_commands.c
@@ -22,7 +22,37 @@
#ifdef CONFIG_LPC
#define LPC_SYSJUMP_TAG 0x4c50 /* "LP" */
-#define LPC_SYSJUMP_VERSION 1
+#define LPC_SYSJUMP_OLD_VERSION 1
+#define LPC_SYSJUMP_VERSION 2
+
+/*
+ * Always report mask includes mask of host events that need to be reported in
+ * host event always irrespective of the state of SCI, SMI and wake masks.
+ *
+ * Events that indicate critical shutdown/reboots that have occurred:
+ * - EC_HOST_EVENT_THERMAL_SHUTDOWN
+ * - EC_HOST_EVENT_BATTERY_SHUTDOWN
+ * - EC_HOST_EVENT_HANG_REBOOT
+ * - EC_HOST_EVENT_PANIC
+ *
+ * Events that are consumed by BIOS:
+ * - EC_HOST_EVENT_KEYBOARD_RECOVERY
+ * - EC_HOST_EVENT_KEYBOARD_FASTBOOT
+ * - EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT
+ *
+ * Events that are buffered and have separate data maintained of their own:
+ * - EC_HOST_EVENT_MKBP
+ *
+ */
+#define LPC_HOST_EVENT_ALWAYS_REPORT_DEFAULT_MASK \
+ (EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY) | \
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) | \
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN) | \
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_HANG_REBOOT) | \
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_PANIC) | \
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_FASTBOOT) | \
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_MKBP) | \
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT))
static uint32_t lpc_host_events;
static uint32_t lpc_host_event_mask[LPC_HOST_EVENT_COUNT];
@@ -38,6 +68,17 @@ uint32_t lpc_get_host_event_mask(enum lpc_host_event_type type)
return lpc_host_event_mask[type];
}
+static uint32_t lpc_get_all_host_event_masks(void)
+{
+ uint32_t or_mask = 0;
+ int i;
+
+ for (i = 0; i < LPC_HOST_EVENT_COUNT; i++)
+ or_mask |= lpc_get_host_event_mask(i);
+
+ return or_mask;
+}
+
static void lpc_set_host_event_state(uint32_t events)
{
if (events == lpc_host_events)
@@ -59,33 +100,11 @@ uint32_t lpc_get_host_events(void)
int lpc_get_next_host_event(void)
{
- int evt_index = 0;
- int i;
- const uint32_t any_mask = lpc_get_host_event_mask(LPC_HOST_EVENT_SMI) |
- lpc_get_host_event_mask(LPC_HOST_EVENT_SCI) |
- lpc_get_host_event_mask(LPC_HOST_EVENT_WAKE);
-
- for (i = 0; i < 32; i++) {
- const uint32_t e = (1 << i);
-
- if (lpc_host_events & e) {
- host_clear_events(e);
-
- /*
- * If host hasn't unmasked this event, drop it. We do
- * this at query time rather than event generation time
- * so that the host has a chance to unmask events
- * before they're dropped by a query.
- */
- if (!(e & any_mask))
- continue;
-
- evt_index = i + 1; /* Events are 1-based */
- break;
- }
- }
+ int evt_idx = __builtin_ffs(lpc_host_events);
- return evt_index;
+ if (evt_idx)
+ host_clear_events(1 << (evt_idx - 1));
+ return evt_idx;
}
static void lpc_sysjump_save_mask(void)
@@ -95,24 +114,53 @@ static void lpc_sysjump_save_mask(void)
}
DECLARE_HOOK(HOOK_SYSJUMP, lpc_sysjump_save_mask, HOOK_PRIO_DEFAULT);
-static void lpc_post_sysjump_restore_mask(void)
+/*
+ * Restore various LPC masks if they were saved before the sysjump.
+ *
+ * Returns:
+ * 1 = All masks were restored
+ * 0 = No masks were stashed before sysjump or EC performing sysjump did not
+ * support always report mask.
+ */
+static int lpc_post_sysjump_restore_mask(void)
{
const uint32_t *prev_mask;
int size, version;
prev_mask = (const uint32_t *)system_get_jump_tag(LPC_SYSJUMP_TAG,
&version, &size);
- if (!prev_mask || version != LPC_SYSJUMP_VERSION ||
- size != sizeof(lpc_host_event_mask))
- return;
+ if (!prev_mask || size != sizeof(lpc_host_event_mask) ||
+ (version != LPC_SYSJUMP_VERSION &&
+ version != LPC_SYSJUMP_OLD_VERSION))
+ return 0;
memcpy(lpc_host_event_mask, prev_mask, sizeof(lpc_host_event_mask));
+
+ return version == LPC_SYSJUMP_VERSION;
+}
+
+uint32_t __attribute__((weak)) lpc_override_always_report_mask(void)
+{
+ return LPC_HOST_EVENT_ALWAYS_REPORT_DEFAULT_MASK;
}
+
+static void lpc_init_mask(void)
+{
+ /*
+ * First check if masks were stashed before sysjump. If no masks were
+ * stashed or if the EC image performing sysjump does not support always
+ * report mask, then set always report mask now.
+ */
+ if (!lpc_post_sysjump_restore_mask())
+ lpc_host_event_mask[LPC_HOST_EVENT_ALWAYS_REPORT] =
+ lpc_override_always_report_mask();
+}
+
/*
* This hook is required to run before chip gets to initialize LPC because
* update host events will need the masks to be correctly restored.
*/
-DECLARE_HOOK(HOOK_INIT, lpc_post_sysjump_restore_mask, HOOK_PRIO_INIT_LPC - 1);
+DECLARE_HOOK(HOOK_INIT, lpc_init_mask, HOOK_PRIO_INIT_LPC - 1);
#endif
@@ -142,6 +190,18 @@ void host_set_events(uint32_t mask)
/* ignore host events the rest of board doesn't care about */
mask &= CONFIG_HOST_EVENT_REPORT_MASK;
+#ifdef CONFIG_LPC
+ /*
+ * Host only cares about the events for which the masks are set either
+ * in wake mask, SCI mask or SMI mask. In addition to that, there are
+ * certain events that need to be always reported (Please see
+ * LPC_HOST_EVENT_ALWAYS_REPORT_DEFAULT_MASK). Thus, when a new host
+ * event is being set, ensure that it is present in one of these
+ * masks. Else, there is no need to process that event.
+ */
+ mask &= lpc_get_all_host_event_masks();
+#endif
+
/* exit now if nothing has changed */
if (!((events & mask) != mask || (events_copy_b & mask) != mask))
return;
@@ -251,6 +311,9 @@ static int command_host_event(int argc, char **argv)
lpc_set_host_event_mask(LPC_HOST_EVENT_SCI, i);
else if (!strcasecmp(argv[1], "wake"))
lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, i);
+ else if (!strcasecmp(argv[1], "always_report"))
+ lpc_set_host_event_mask(LPC_HOST_EVENT_ALWAYS_REPORT,
+ i);
#endif
else
return EC_ERROR_PARAM1;
@@ -266,11 +329,13 @@ static int command_host_event(int argc, char **argv)
lpc_get_host_event_mask(LPC_HOST_EVENT_SCI));
ccprintf("Wake mask: 0x%08x\n",
lpc_get_host_event_mask(LPC_HOST_EVENT_WAKE));
+ ccprintf("Always report mask: 0x%08x\n",
+ lpc_get_host_event_mask(LPC_HOST_EVENT_ALWAYS_REPORT));
#endif
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(hostevent, command_host_event,
- "[set | clear | clearb | smi | sci | wake] [mask]",
+ "[set | clear | clearb | smi | sci | wake | always_report] [mask]",
"Print / set host event state");
/*****************************************************************************/
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 5797eb58f1..24cd099fe1 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1089,6 +1089,8 @@ enum ec_feature_code {
EC_FEATURE_RWSIG = 30,
/* EC has device events support */
EC_FEATURE_DEVICE_EVENT = 31,
+ /* EC supports the unified wake masks for LPC/eSPI systems */
+ EC_FEATURE_UNIFIED_WAKE_MASKS = 32,
};
#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
diff --git a/include/lpc.h b/include/lpc.h
index ff9642b6f5..a405e93d59 100644
--- a/include/lpc.h
+++ b/include/lpc.h
@@ -71,6 +71,7 @@ enum lpc_host_event_type {
LPC_HOST_EVENT_SMI = 0,
LPC_HOST_EVENT_SCI,
LPC_HOST_EVENT_WAKE,
+ LPC_HOST_EVENT_ALWAYS_REPORT,
LPC_HOST_EVENT_COUNT,
};
@@ -141,4 +142,11 @@ void lpc_enable_acpi_interrupts(void);
*/
void lpc_update_host_event_status(void);
+/*
+ * This is a weak function defined in host_events_commands.c to override the
+ * LPC_HOST_EVENT_ALWAYS_REPORT mask. It can be implemented by boards if there
+ * is a need to use custom mask.
+ */
+uint32_t lpc_override_always_report_mask(void);
+
#endif /* __CROS_EC_LPC_H */