diff options
Diffstat (limited to 'src/southbridge/intel/i82801gx/smi.c')
-rw-r--r-- | src/southbridge/intel/i82801gx/smi.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/src/southbridge/intel/i82801gx/smi.c b/src/southbridge/intel/i82801gx/smi.c index 95ec1129a3..5be24049be 100644 --- a/src/southbridge/intel/i82801gx/smi.c +++ b/src/southbridge/intel/i82801gx/smi.c @@ -320,6 +320,16 @@ static void smm_relocate(void) static int smm_handler_copied = 0; +static int is_wakeup(void) +{ + device_t dev0 = dev_find_slot(0, PCI_DEVFN(0,0)); + + if (!dev0) + return 0; + + return pci_read_config32(dev0, 0xdc) == SKPAD_ACPI_S3_MAGIC; +} + static void smm_install(void) { /* The first CPU running this gets to copy the SMM handler. But not all @@ -329,13 +339,19 @@ static void smm_install(void) return; smm_handler_copied = 1; - /* enable the SMM memory window */ - pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM, - D_OPEN | G_SMRAME | C_BASE_SEG); - /* copy the real SMM handler */ - memcpy((void *)0xa0000, &_binary_smm_start, (size_t)&_binary_smm_size); - wbinvd(); + /* if we're resuming from S3, the SMM code is already in place, + * so don't copy it again to keep the current SMM state */ + + if (!is_wakeup()) { + /* enable the SMM memory window */ + pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM, + D_OPEN | G_SMRAME | C_BASE_SEG); + + /* copy the real SMM handler */ + memcpy((void *)0xa0000, &_binary_smm_start, (size_t)&_binary_smm_size); + wbinvd(); + } /* close the SMM memory window and enable normal SMM */ pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM, |