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 #include #include #include @@ -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);