summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFurquan Shaikh <furquan@chromium.org>2017-08-17 18:28:41 -0700
committerFurquan Shaikh <furquan@google.com>2017-08-19 00:33:04 +0000
commitaeb2d64c85ca2c3a77f50d57e3a92f6fc0a5c2d3 (patch)
tree1b0e09b0ff072bfeb3d300c709b24d1037362a08
parentaef8542d810b737fe2653dcca1d9566292b3b65d (diff)
soc/intel/skylake: Enable power button SMI when jumping to payload
Instead of enabling power button SMI unconditionally, add a boot state handler to enable power button SMI just before jumping to payload. This ensures that: 1. We do not respond to power button SMI until we know that coreboot is done. 2. On resume, there is no need to enable power button SMI. This avoids any power button presses during resume path from triggering a shutdown. BUG=b:64811381 Change-Id: Icc52dc0103555602c23e09660bc38bb4bfddbc11 Signed-off-by: Furquan Shaikh <furquan@chromium.org> Reviewed-on: https://review.coreboot.org/21082 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-by: Subrata Banik <subrata.banik@intel.com>
-rw-r--r--src/soc/intel/skylake/include/soc/pm.h2
-rw-r--r--src/soc/intel/skylake/pmutil.c16
-rw-r--r--src/soc/intel/skylake/smi.c18
-rw-r--r--src/soc/intel/skylake/smihandler.c3
4 files changed, 37 insertions, 2 deletions
diff --git a/src/soc/intel/skylake/include/soc/pm.h b/src/soc/intel/skylake/include/soc/pm.h
index 67b1f438b6..1e4520e687 100644
--- a/src/soc/intel/skylake/include/soc/pm.h
+++ b/src/soc/intel/skylake/include/soc/pm.h
@@ -159,6 +159,8 @@ void disable_pm1_control(uint32_t mask);
/* PM1 */
uint16_t clear_pm1_status(void);
void enable_pm1(uint16_t events);
+void update_pm1_enable(uint16_t events);
+uint16_t read_pm1_enable(void);
uint32_t clear_smi_status(void);
/* SMI */
diff --git a/src/soc/intel/skylake/pmutil.c b/src/soc/intel/skylake/pmutil.c
index 9b38531129..fa2dc2d039 100644
--- a/src/soc/intel/skylake/pmutil.c
+++ b/src/soc/intel/skylake/pmutil.c
@@ -142,6 +142,22 @@ void enable_pm1(u16 events)
outw(events, ACPI_BASE_ADDRESS + PM1_EN);
}
+/*
+ * Update supplied events in PM1_EN register. This does not disable any already
+ * set events.
+ */
+void update_pm1_enable(u16 events)
+{
+ u16 pm1_en = read_pm1_enable();
+ pm1_en |= events;
+ enable_pm1(pm1_en);
+}
+
+/* Read events set in PM1_EN register. */
+uint16_t read_pm1_enable(void)
+{
+ return inw(ACPI_BASE_ADDRESS + PM1_EN);
+}
/*
* SMI
diff --git a/src/soc/intel/skylake/smi.c b/src/soc/intel/skylake/smi.c
index 734363713e..feddf5084c 100644
--- a/src/soc/intel/skylake/smi.c
+++ b/src/soc/intel/skylake/smi.c
@@ -15,6 +15,7 @@
* GNU General Public License for more details.
*/
+#include <bootstate.h>
#include <device/device.h>
#include <device/pci.h>
#include <console/console.h>
@@ -54,7 +55,7 @@ void southbridge_smm_enable_smi(void)
{
printk(BIOS_DEBUG, "Enabling SMIs.\n");
/* Configure events */
- enable_pm1(PWRBTN_EN | GBL_EN);
+ enable_pm1(GBL_EN);
disable_gpe(PME_B0_EN);
/*
@@ -88,3 +89,18 @@ void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
"d" (APM_CNT)
);
}
+
+static void pm1_enable_pwrbtn_smi(void *unused)
+{
+ /*
+ * Enable power button SMI only before jumping to payload. This ensures
+ * that:
+ * 1. Power button SMI is enabled only after coreboot is done.
+ * 2. On resume path, power button SMI is not enabled and thus avoids
+ * any shutdowns because of power button presses due to power button
+ * press in resume path.
+ */
+ update_pm1_enable(PWRBTN_EN);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, pm1_enable_pwrbtn_smi, NULL);
diff --git a/src/soc/intel/skylake/smihandler.c b/src/soc/intel/skylake/smihandler.c
index d87994ea16..3e79065cda 100644
--- a/src/soc/intel/skylake/smihandler.c
+++ b/src/soc/intel/skylake/smihandler.c
@@ -343,12 +343,13 @@ static void southbridge_smi_apmc(void)
static void southbridge_smi_pm1(void)
{
u16 pm1_sts = clear_pm1_status();
+ u16 pm1_en = read_pm1_enable();
/*
* While OSPM is not active, poweroff immediately on a power button
* event.
*/
- if (pm1_sts & PWRBTN_STS) {
+ if ((pm1_sts & PWRBTN_STS) && (pm1_en & PWRBTN_EN)) {
/* power button pressed */
if (IS_ENABLED(CONFIG_ELOG_GSMI))
elog_add_event(ELOG_TYPE_POWER_BUTTON);