Unified Host Event Programming Interface (UHEPI) enables a unified host command EC_CMD_PROGRAM_HOST_EVENT to set/get/clear different host events. Old host event commands (0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F) is supported for backward compatibility. But newer version of BIOS/OS is expected to use UHEPI command (EC_CMD_PROGRAM_HOST_EVENT) The UHEPI also enables the active and lazy wake masks. Active wake mask is the mask that is programmed in the LPC driver (i.e. the mask that is actively used by LPC driver for waking the host during suspended state). It is same as the current wake mask that is set by the smihandler on host just before entering sleep state S3/S5. On the other hand, lazy wake masks are per-sleep masks (S0ix, S3, S5) so that they can be used by EC to set the active wake mask depending upon the type of sleep that the host has entered. This allows the host BIOS to perform one-time programming of the wake masks for each supported sleep type and then EC can take care of appropriately setting the active mask when host enters a particular sleep state. BRANCH=none BUG=b:63969337 TEST=verify masks with ec hostevent command on S0,S3,S5 and S0ix 1). Verified wake masks with ec hostevent command on S0,S3,S5 and S0ix 2). suspend_stress_test with S3 and S0ix 3). Verified "mosys eventlog list" in S3 and s0ix resume to confirm wake sources (Lid, power buttton and Mode change) 4). Verified "mosys eventlog list" in S5 resume to confirm wake sources (Power Button) 5). Verified above scenarios with combination of Old BIOS + New EC and New BIOS + Old EC Change-Id: I4917a222c79b6aaecb71d7704ffde57bf3bc99d9 Signed-off-by: Jenny TC <jenny.tc@intel.com> Reviewed-on: https://review.coreboot.org/21085 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Furquan Shaikh <furquan@google.com>
116 lines
2.7 KiB
C
116 lines
2.7 KiB
C
/*
|
|
* This file is part of the coreboot project.
|
|
*
|
|
* Copyright 2016 Google Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <arch/acpi.h>
|
|
#include <console/console.h>
|
|
#include <cpu/x86/smm.h>
|
|
#include <ec/google/chromeec/ec.h>
|
|
#include <elog.h>
|
|
#include <halt.h>
|
|
#include "smm.h"
|
|
|
|
static int chromeec_process_one_event(void)
|
|
{
|
|
uint8_t event = google_chromeec_get_event();
|
|
|
|
/* Log this event */
|
|
if (IS_ENABLED(CONFIG_ELOG_GSMI) && event)
|
|
elog_add_event_byte(ELOG_TYPE_EC_EVENT, event);
|
|
|
|
switch (event) {
|
|
case EC_HOST_EVENT_LID_CLOSED:
|
|
printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n");
|
|
|
|
poweroff();
|
|
break;
|
|
}
|
|
return !!event;
|
|
}
|
|
|
|
void chromeec_smi_process_events(void)
|
|
{
|
|
/* Process all pending events */
|
|
while (chromeec_process_one_event())
|
|
;
|
|
}
|
|
|
|
static void clear_pending_events(void)
|
|
{
|
|
struct ec_response_get_next_event mkbp_event;
|
|
|
|
while (google_chromeec_get_event() != 0)
|
|
;
|
|
|
|
while (google_chromeec_get_mkbp_event(&mkbp_event) == 0)
|
|
;
|
|
}
|
|
|
|
void chromeec_smi_sleep(int slp_type, uint64_t s3_mask, uint64_t s5_mask)
|
|
{
|
|
if (!google_chromeec_is_uhepi_supported()) {
|
|
switch (slp_type) {
|
|
case ACPI_S3:
|
|
/* Enable wake events */
|
|
google_chromeec_set_wake_mask(s3_mask);
|
|
break;
|
|
case ACPI_S5:
|
|
/* Enable wake events */
|
|
google_chromeec_set_wake_mask(s5_mask);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Disable SCI and SMI events */
|
|
google_chromeec_set_smi_mask(0);
|
|
google_chromeec_set_sci_mask(0);
|
|
|
|
/* Clear pending events that may trigger immediate wake */
|
|
clear_pending_events();
|
|
}
|
|
|
|
void chromeec_smi_device_event_sleep(int slp_type, uint64_t s3_mask,
|
|
uint64_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, uint64_t sci_mask, uint64_t smi_mask)
|
|
{
|
|
switch (apmc) {
|
|
case APM_CNT_ACPI_ENABLE:
|
|
google_chromeec_set_smi_mask(0);
|
|
clear_pending_events();
|
|
google_chromeec_set_sci_mask(sci_mask);
|
|
break;
|
|
case APM_CNT_ACPI_DISABLE:
|
|
google_chromeec_set_sci_mask(0);
|
|
clear_pending_events();
|
|
google_chromeec_set_smi_mask(smi_mask);
|
|
break;
|
|
}
|
|
}
|