summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);