stoneyridge: Store wake parameters in NVS

ACPI _SWS needs information on PM1 and ACPI events (though events can be
read directly). Unfortunately PM1 is cleared in normal path and in resume
path. Save PM1 and ACPI events in NVS to be accessed by ACPI _SWS.

BUG=b:75996437
TEST=Build and boot grunt recording serial. Run suspend stress test, after
3 resumes closed file and examined for the message indicating what was
being saved to NVS. Two different path, normal boot (first boot) and
resume path had different PM1.

Change-Id: If3b191854afb27779b47c3d8d9f5671a255f51b5
Signed-off-by: Richard Spiegel <richard.spiegel@silverbackltd.com>
Reviewed-on: https://review.coreboot.org/26208
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Martin Roth <martinroth@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/soc/amd/stoneyridge/acpi.c b/src/soc/amd/stoneyridge/acpi.c
index 735990f..d7aa088 100644
--- a/src/soc/amd/stoneyridge/acpi.c
+++ b/src/soc/amd/stoneyridge/acpi.c
@@ -281,6 +281,7 @@
 
 	/* Set unknown wake source */
 	gnvs->pm1i = ~0ULL;
+	gnvs->gpei = ~0ULL;
 
 	/* CPU core count */
 	gnvs->pcnt = dev_count_cpu();
diff --git a/src/soc/amd/stoneyridge/southbridge.c b/src/soc/amd/stoneyridge/southbridge.c
index eb8820f..f01f534 100644
--- a/src/soc/amd/stoneyridge/southbridge.c
+++ b/src/soc/amd/stoneyridge/southbridge.c
@@ -32,6 +32,7 @@
 #include <delay.h>
 #include <soc/pci_devs.h>
 #include <agesa_headers.h>
+#include <soc/nvs.h>
 
 /*
  * Table of devices that need their AOAC registers enabled and waited
@@ -678,13 +679,50 @@
 		elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
 }
 
+struct soc_amd_sws {
+	uint32_t pm1i;
+	uint32_t gevent;
+};
+
+static struct soc_amd_sws sws;
+
+static void sb_save_sws(uint32_t pm1_status)
+{
+	uint32_t reg32;
+
+	sws.pm1i = pm1_status;
+	reg32 = inl(ACPI_GPE0_BLK);
+	outl(ACPI_GPE0_BLK, reg32);
+	reg32 &= inl(ACPI_GPE0_BLK + sizeof(uint32_t));
+	sws.gevent = reg32;
+}
+
 static void sb_clear_pm1_status(void)
 {
 	uint16_t pm1_sts = reset_pm1_status();
+
+	sb_save_sws(pm1_sts);
 	sb_log_pm1_status(pm1_sts);
 	print_pm1_status(pm1_sts);
 }
 
+static void set_nvs_sws(void *unused)
+{
+	struct global_nvs_t *gnvs;
+
+	gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
+	if (gnvs == NULL)
+		return;
+
+	gnvs->pm1i = sws.pm1i;
+	gnvs->gpei = sws.gevent;
+
+	printk(BIOS_DEBUG, "Loaded _SWS parameters PM1 0x%08x, EVENT 0x%08x into nvs\n",
+				sws.pm1i, sws.gevent);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, set_nvs_sws, NULL);
+
 void southbridge_init(void *chip_info)
 {
 	sb_init_acpi_ports();