From dbbc7efacaeec510163ef0f0f802ab75cca8d94e Mon Sep 17 00:00:00 2001
From: Timothy Pearson <tpearson@raptorengineeringinc.com>
Date: Thu, 7 May 2015 01:32:08 -0500
Subject: [PATCH 023/143] mainboard/asus/kgpe-d16: Add initial Suspend to RAM
 (S3) support

Change-Id: I7da84b064287a445fd75a947e2f96ce1ae30d3de
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
---
 src/mainboard/asus/kgpe-d16/Kconfig          |    3 +
 src/mainboard/asus/kgpe-d16/acpi/pm_ctrl.asl |  639 +++++++++++++-------------
 src/mainboard/asus/kgpe-d16/dsdt.asl         |    5 +-
 src/mainboard/asus/kgpe-d16/romstage.c       |   34 +-
 src/mainboard/asus/kgpe-d16/spd_notes.txt    |   16 +
 5 files changed, 369 insertions(+), 328 deletions(-)

diff --git a/src/mainboard/asus/kgpe-d16/Kconfig b/src/mainboard/asus/kgpe-d16/Kconfig
index 95b3b5b..f9556fc 100644
--- a/src/mainboard/asus/kgpe-d16/Kconfig
+++ b/src/mainboard/asus/kgpe-d16/Kconfig
@@ -23,6 +23,9 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select BOARD_ROMSIZE_KB_2048
 	select ENABLE_APIC_EXT_ID
 	select MMCONF_SUPPORT_DEFAULT
+	select SPI_FLASH
+	select SPI_FLASH_WINBOND
+	select HAVE_ACPI_RESUME
 	select DRIVERS_I2C_W83795
 	select DRIVERS_ASPEED_AST2050
 	select MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG
diff --git a/src/mainboard/asus/kgpe-d16/acpi/pm_ctrl.asl b/src/mainboard/asus/kgpe-d16/acpi/pm_ctrl.asl
index b3c65ca..737d8cd 100644
--- a/src/mainboard/asus/kgpe-d16/acpi/pm_ctrl.asl
+++ b/src/mainboard/asus/kgpe-d16/acpi/pm_ctrl.asl
@@ -18,350 +18,359 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+/* Port 80 POST card debug */
+OperationRegion (DBG0, SystemIO, 0x80, One)
+	Field (DBG0, ByteAcc, NoLock, Preserve) {
+	DBG8, 8
+}
+
+/* SuperIO control port */
+Name (SPIO, 0x2E)
+
+/* SuperIO control map */
+OperationRegion (SPIM, SystemIO, SPIO, 0x02)
+	Field (SPIM, ByteAcc, NoLock, Preserve) {
+	INDX, 8,
+	DATA, 8
+}
+
+/* SuperIO control registers */
+IndexField (INDX, DATA, ByteAcc, NoLock, Preserve) {
+	Offset (0x07),
+	CR07, 8,		/* Logical device number */
+	Offset (0x2C),
+	CR2C, 8,		/* GPIO3 multiplexed pin selection */
+	Offset (0x30),
+	CR30, 8,		/* Logical device activation control register */
+	Offset (0xE0),
+	CRE0, 8,		/* Wake control register */
+	Offset (0xE4),
+	CRE4, 8,		/* Standby power control register */
+	Offset (0xE6),
+	CRE6, 8,		/* Mouse wake event configuration register */
+	Offset (0xF1),
+	CRF1, 8,		/* GPIO3 data register */
+	Offset (0xF3),
+	CRF3, 8,		/* SUSLED mode register */
+	Offset (0xF6),
+	CRF6, 8,		/* SMI/PME event generation control register */
+	Offset (0xF9),
+	CRF9, 8,		/* ACPI PME configuration register */
+}
+
+/* Power Management I/O registers */
+OperationRegion(PIOR, SystemIO, 0x00000CD6, 0x00000002)
+	Field(PIOR, ByteAcc, NoLock, Preserve) {
+	PIOI, 0x00000008,
+	PIOD, 0x00000008,
+}
+IndexField (PIOI, PIOD, ByteAcc, NoLock, Preserve) {
+	Offset(0x00),	/* MiscControl */
+	, 1,
+	T1EE, 1,
+	T2EE, 1,
+	Offset(0x01),	/* MiscStatus */
+	, 1,
+	T1E, 1,
+	T2E, 1,
+	Offset(0x04),	/* SmiWakeUpEventEnable3 */
+	, 7,
+	SSEN, 1,
+	Offset(0x07),	/* SmiWakeUpEventStatus3 */
+	, 7,
+	CSSM, 1,
+	Offset(0x10),	/* AcpiEnable */
+	, 6,
+	PWDE, 1,
+	Offset(0x1C),	/* ProgramIoEnable */
+	, 3,
+	MKME, 1,
+	IO3E, 1,
+	IO2E, 1,
+	IO1E, 1,
+	IO0E, 1,
+	Offset(0x1D),	/* IOMonitorStatus */
+	, 3,
+	MKMS, 1,
+	IO3S, 1,
+	IO2S, 1,
+	IO1S, 1,
+	IO0S,1,
+	Offset(0x20),	/* AcpiPmEvtBlk */
+	APEB, 16,
+	Offset(0x36),	/* GEvtLevelConfig */
+	, 6,
+	ELC6, 1,
+	ELC7, 1,
+	Offset(0x37),	/* GPMLevelConfig0 */
+	, 3,
+	PLC0, 1,
+	PLC1, 1,
+	PLC2, 1,
+	PLC3, 1,
+	PLC8, 1,
+	Offset(0x38),	/* GPMLevelConfig1 */
+	, 1,
+		PLC4, 1,
+		PLC5, 1,
+	, 1,
+		PLC6, 1,
+		PLC7, 1,
+	Offset(0x3B),	/* PMEStatus1 */
+	GP0S, 1,
+	GM4S, 1,
+	GM5S, 1,
+	APS, 1,
+	GM6S, 1,
+	GM7S, 1,
+	GP2S, 1,
+	STSS, 1,
+	Offset(0x55),	/* SoftPciRst */
+	SPRE, 1,
+	, 1,
+	, 1,
+	PNAT, 1,
+	PWMK, 1,
+	PWNS, 1,
+
+	/* 	Offset(0x61), */	/*  Options_1 */
+	/* 		,7,  */
+	/* 		R617,1, */
+
+	Offset(0x65),	/* UsbPMControl */
+	, 4,
+	URRE, 1,
+	, 2,
+	BCDL, 1,
+	Offset(0x68),	/* MiscEnable68 */
+	, 2,
+	MAPC, 1,
+	TMTE, 1,
+	, 1,
+	Offset(0x7C),	/* MiscEnable7C */
+	, 2,
+	BLNK, 2,
+	Offset(0x92),	/* GEVENTIN */
+	, 7,
+	E7IS, 1,
+	Offset(0x96),	/* GPM98IN */
+	G8IS, 1,
+	G9IS, 1,
+	Offset(0x9A),	/* EnhanceControl */
+	,7,
+	HPDE, 1,
+	Offset(0xA8),	/* PIO7654Enable */
+	IO4E, 1,
+	IO5E, 1,
+	IO6E, 1,
+	IO7E, 1,
+	Offset(0xA9),	/* PIO7654Status */
+	IO4S, 1,
+	IO5S, 1,
+	IO6S, 1,
+	IO7S, 1,
+}
+
+/* PM1 Event Block
+	* First word is PM1_Status, Second word is PM1_Enable
+	*/
+OperationRegion(P1EB, SystemIO, APEB, 0x04)
+	Field(P1EB, ByteAcc, NoLock, Preserve) {
+	TMST, 1,
+	,    3,
+	BMST,    1,
+	GBST,   1,
+	Offset(0x01),
+	PBST, 1,
+	, 1,
+	RTST, 1,
+	, 3,
+	PWST, 1,
+	SPWS, 1,
+	Offset(0x02),
+	TMEN, 1,
+	, 4,
+	GBEN, 1,
+	Offset(0x03),
+	PBEN, 1,
+	, 1,
+	RTEN, 1,
+	, 3,
+	PWDA, 1,
+}
+
+/* Wake status package */
+Name(WKST,Package() {Zero, Zero})
+
 /*
- * WARNING: Sleep/Wake is a work in progress and is still somewhat flaky!
+ *  \_WAK System Wake method
+ *
+ *	Entry:
+ *		Arg0=The value of the sleeping state S1=1, S2=2
+ *
+ *	Exit:
+ *		Return package of 2 DWords
+ *		Dword 1 - Status
+ *			0x00000000	wake succeeded
+ *			0x00000001	Wake was signaled but failed due to lack of power
+ *			0x00000002	Wake was signaled but failed due to thermal condition
+ *		Dword 2 - Power Supply state
+ *			if non-zero the effective S-state the power supply entered
  */
-
-	/* Port 80 POST card debug */
-	OperationRegion (DBG0, SystemIO, 0x80, One)
-		Field (DBG0, ByteAcc, NoLock, Preserve) {
-		DBG8, 8
-	}
-
-	/* SuperIO control port */
-	Name (SPIO, 0x2E)
-
-	/* SuperIO control map */
-	OperationRegion (SPIM, SystemIO, SPIO, 0x02)
-		Field (SPIM, ByteAcc, NoLock, Preserve) {
-		INDX, 8,
-		DATA, 8
-	}
-
-	/* SuperIO control registers */
-	IndexField (INDX, DATA, ByteAcc, NoLock, Preserve) {
-		Offset (0x07),
-		CR07, 8,		/* Logical device number */
-		Offset (0x2C),
-		CR2C, 8,		/* GPIO3 multiplexed pin selection */
-		Offset (0x30),
-		CR30, 8,		/* Logical device activation control register */
-		Offset (0xE0),
-		CRE0, 8,		/* Wake control register */
-		Offset (0xE6),
-		CRE6, 8,		/* Mouse wake event configuration register */
-		Offset (0xF1),
-		CRF1, 8,		/* GPIO3 data register */
-		Offset (0xF3),
-		CRF3, 8,		/* SUSLED mode register */
-		Offset (0xF6),
-		CRF6, 8,		/* SMI/PME event generation control register */
-		Offset (0xF9),
-		CRF9, 8,		/* ACPI PME configuration register */
+Method(\_WAK, 1) {
+	Store (0x20, DBG8)
+
+	/* Set up LEDs */
+	/* Set power LED to steady on */
+	Store(0x3, BLNK)
+
+	/* Configure SuperIO for wake */
+	/* Access SuperIO ACPI device */
+	Store(0x87, INDX)
+	Store(0x87, INDX)
+	Store(0x0A, CR07)
+
+	if (LEqual(Arg0, One))	/* Resuming from power state S1 */
+	{
+		/* Deactivate the ACPI device */
+		Store(Zero, CR30)
+
+		/* Disable PS/2 SMI/PME events */
+		And(CRF6, 0xCF, CRF6)
 	}
-
-	/* Power Management I/O registers */
-	OperationRegion(PIOR, SystemIO, 0x00000CD6, 0x00000002)
-		Field(PIOR, ByteAcc, NoLock, Preserve) {
-		PIOI, 0x00000008,
-		PIOD, 0x00000008,
-	}
-	IndexField (PIOI, PIOD, ByteAcc, NoLock, Preserve) {
-		Offset(0x00),	/* MiscControl */
-		, 1,
-		T1EE, 1,
-		T2EE, 1,
-		Offset(0x01),	/* MiscStatus */
-		, 1,
-		T1E, 1,
-		T2E, 1,
-		Offset(0x04),	/* SmiWakeUpEventEnable3 */
-		, 7,
-		SSEN, 1,
-		Offset(0x07),	/* SmiWakeUpEventStatus3 */
-		, 7,
-		CSSM, 1,
-		Offset(0x10),	/* AcpiEnable */
-		, 6,
-		PWDE, 1,
-		Offset(0x1C),	/* ProgramIoEnable */
-		, 3,
-		MKME, 1,
-		IO3E, 1,
-		IO2E, 1,
-		IO1E, 1,
-		IO0E, 1,
-		Offset(0x1D),	/* IOMonitorStatus */
-		, 3,
-		MKMS, 1,
-		IO3S, 1,
-		IO2S, 1,
-		IO1S, 1,
-		IO0S,1,
-		Offset(0x20),	/* AcpiPmEvtBlk */
-		APEB, 16,
-		Offset(0x36),	/* GEvtLevelConfig */
-		, 6,
-		ELC6, 1,
-		ELC7, 1,
-		Offset(0x37),	/* GPMLevelConfig0 */
-		, 3,
-		PLC0, 1,
-		PLC1, 1,
-		PLC2, 1,
-		PLC3, 1,
-		PLC8, 1,
-		Offset(0x38),	/* GPMLevelConfig1 */
-		, 1,
-		 PLC4, 1,
-		 PLC5, 1,
-		, 1,
-		 PLC6, 1,
-		 PLC7, 1,
-		Offset(0x3B),	/* PMEStatus1 */
-		GP0S, 1,
-		GM4S, 1,
-		GM5S, 1,
-		APS, 1,
-		GM6S, 1,
-		GM7S, 1,
-		GP2S, 1,
-		STSS, 1,
-		Offset(0x55),	/* SoftPciRst */
-		SPRE, 1,
-		, 1,
-		, 1,
-		PNAT, 1,
-		PWMK, 1,
-		PWNS, 1,
-
-		/* 	Offset(0x61), */	/*  Options_1 */
-		/* 		,7,  */
-		/* 		R617,1, */
-
-		Offset(0x65),	/* UsbPMControl */
-		, 4,
-		URRE, 1,
-		Offset(0x68),	/* MiscEnable68 */
-		, 3,
-		TMTE, 1,
-		, 1,
-		Offset(0x7C),	/* MiscEnable7C */
-		, 2,
-		BLNK, 2,
-		Offset(0x92),	/* GEVENTIN */
-		, 7,
-		E7IS, 1,
-		Offset(0x96),	/* GPM98IN */
-		G8IS, 1,
-		G9IS, 1,
-		Offset(0x9A),	/* EnhanceControl */
-		,7,
-		HPDE, 1,
-		Offset(0xA8),	/* PIO7654Enable */
-		IO4E, 1,
-		IO5E, 1,
-		IO6E, 1,
-		IO7E, 1,
-		Offset(0xA9),	/* PIO7654Status */
-		IO4S, 1,
-		IO5S, 1,
-		IO6S, 1,
-		IO7S, 1,
+	if (Lor(LEqual(Arg0, 0x03), LEqual(Arg0, 0x04)))	/* Resuming from power state S3 or S4 */
+	{
+		/* Disable PS/2 wake */
+		And(CRE0, 0x1D, CRE0)
+		And(CRE6, 0x7F, CRE6)
 	}
 
-	/* PM1 Event Block
-	 * First word is PM1_Status, Second word is PM1_Enable
-	 */
-	OperationRegion(P1EB, SystemIO, APEB, 0x04)
-		Field(P1EB, ByteAcc, NoLock, Preserve) {
-		TMST, 1,
-		,    3,
-		BMST,    1,
-		GBST,   1,
-		Offset(0x01),
-		PBST, 1,
-		, 1,
-		RTST, 1,
-		, 3,
-		PWST, 1,
-		SPWS, 1,
-		Offset(0x02),
-		TMEN, 1,
-		, 4,
-		GBEN, 1,
-		Offset(0x03),
-		PBEN, 1,
-		, 1,
-		RTEN, 1,
-		, 3,
-		PWDA, 1,
-	}
-
-	/* Wake status package */
-	Name(WKST,Package(){Zero, Zero})
-
-	/*
-	 *  \_WAK System Wake method
-	 *
-	 *	Entry:
-	 *		Arg0=The value of the sleeping state S1=1, S2=2
-	 *
-	 *	Exit:
-	 *		Return package of 2 DWords
-	 *		Dword 1 - Status
-	 *			0x00000000	wake succeeded
-	 *			0x00000001	Wake was signaled but failed due to lack of power
-	 *			0x00000002	Wake was signaled but failed due to thermal condition
-	 *		Dword 2 - Power Supply state
-	 *			if non-zero the effective S-state the power supply entered
-	 */
-	Method(\_WAK, 1) {
-		Store (0x20, DBG8)
-
-		/* Set up LEDs */
-		/* Set power LED to steady on */
-		Store(0x3, BLNK)
-
-		/* Configure SuperIO for wake */
-		/* Access SuperIO ACPI device */
-		Store(0x87, INDX)
-		Store(0x87, INDX)
-		Store(0x0A, CR07)
-
-		if (LEqual(Arg0, One))	/* Resuming from power state S1 */
-		{
-			/* Deactivate the ACPI device */
-			Store(Zero, CR30)
-
-			/* Disable PS/2 SMI/PME events */
-			And(CRF6, 0xCF, CRF6)
-		}
-		if (Lor(LEqual(Arg0, 0x03), LEqual(Arg0, 0x04)))	/* Resuming from power state S3 or S4 */
-		{
-			/* Disable PS/2 wake */
-			And(CRE0, 0x1D, CRE0)
-			And(CRE6, 0x7F, CRE6)
-		}
+	/* Restore default SuperIO access */
+	Store(0xAA, INDX)
 
-		/* Restore default SuperIO access */
-		Store(0xAA, INDX)
+	Store (0x21, DBG8)
 
-		Store (0x21, DBG8)
+	/* Re-enable HPET */
+	Store(1, HPDE)
 
-		/* Re-enable HPET */
-		Store(1, HPDE)
+	/* Restore PCIRST# so it resets USB */
+	if (LEqual(Arg0, 3)){
+		Store(1, URRE)
+	}
 
-		/* Restore PCIRST# so it resets USB */
-		if (LEqual(Arg0, 3)){
-			Store(1, URRE)
-		}
+	/* Configure southbridge for wake */
+	/* Arbitrarily clear PciExpWakeStatus */
+	Store(PWST, PWST)
 
-		/* Configure southbridge for wake */
-		/* Arbitrarily clear PciExpWakeStatus */
-		Store(PWST, PWST)
+	Store (0x22, DBG8)
 
-		Store (0x22, DBG8)
+	Notify(\_SB.PWRB, 0x02)			/* NOTIFY_DEVICE_WAKE */
 
-		Notify(\_SB.PWRB, 0x02)			/* NOTIFY_DEVICE_WAKE */
+	Return(WKST)
+}
 
-		Return(WKST)
+/*
+ * \_PTS - Prepare to Sleep method
+ *
+ *	Entry:
+ *		Arg0=The value of the sleeping state S1=1, S2=2, etc
+ *
+ * Exit:
+ *		-none-
+ *
+ * The _PTS control method is executed at the beginning of the sleep process
+ * for S1-S5. The sleeping value is passed to the _PTS control method.	This
+ * control method may be executed a relatively long time before entering the
+ * sleep state and the OS may abort the operation without notification to
+ * the ACPI driver.  This method cannot modify the configuration or power
+ * state of any device in the system.
+ */
+Method(\_PTS, 1) {
+	Store (Arg0, DBG8)
+
+	/* Set up LEDs */
+	if (LEqual(Arg0, One))	/* Power state S1 requested */
+	{
+		/* Set suspend LED to 0.25Hz toggle pulse with 50% duty cycle */
+		Store(0x2, BLNK)
+	}
+	if (LEqual(Arg0, 0x3))	/* Power state S3 requested */
+	{
+		/* Set suspend LED to 0.25Hz toggle pulse with 25% duty cycle */
+		Store(0x1, BLNK)
 	}
 
-	/*
-	 * \_PTS - Prepare to Sleep method
-	 *
-	 *	Entry:
-	 *		Arg0=The value of the sleeping state S1=1, S2=2, etc
-	 *
-	 * Exit:
-	 *		-none-
-	 *
-	 * The _PTS control method is executed at the beginning of the sleep process
-	 * for S1-S5. The sleeping value is passed to the _PTS control method.	This
-	 * control method may be executed a relatively long time before entering the
-	 * sleep state and the OS may abort the operation without notification to
-	 * the ACPI driver.  This method cannot modify the configuration or power
-	 * state of any device in the system.
-	 */
-	Method(\_PTS, 1) {
-		Store (Arg0, DBG8)
-
-		/* Set up LEDs */
-		if (LEqual(Arg0, One))	/* Power state S1 requested */
-		{
-			/* Set suspend LED to 0.25Hz toggle pulse with 50% duty cycle */
-			Store(0x2, BLNK)
-		}
-		if (LEqual(Arg0, 0x3))	/* Power state S3 requested */
-		{
-			/* Set suspend LED to 0.25Hz toggle pulse with 25% duty cycle */
-			Store(0x1, BLNK)
-		}
+	/* Configure SuperIO for sleep */
+	/* Access SuperIO ACPI device */
+	Store(0x87, INDX)
+	Store(0x87, INDX)
+	Store(0x0A, CR07)
 
-		/* Configure SuperIO for sleep */
-		/* Access SuperIO ACPI device */
-		Store(0x87, INDX)
-		Store(0x87, INDX)
-		Store(0x0A, CR07)
+	/* Disable PS/2 wakeup and connect PANSW_IN to PANSW_OUT */
+	And(CRE0, 0x1F, CRE0)
 
-		/* Disable PS/2 wakeup and connect PANSW_IN to PANSW_OUT */
-		And(CRE0, 0x1F, CRE0)
+	if (LEqual(Arg0, One))	/* Power state S1 requested */
+	{
+		/* Activate the ACPI device */
+		Store(One, CR30)
 
-		if (LEqual(Arg0, One))	/* Power state S1 requested */
-		{
-			/* Activate the ACPI device */
-			Store(One, CR30)
+		/* Disable SMI/PME events for:
+			* LPT
+			* FDC
+			* UART
+			*/
+		Store(0x00, CRF6)
 
-			/* Disable SMI/PME events for:
-			 * LPT
-			 * FDC
-			 * UART
-			Store(0x00, CRF6)
+		/* Enable PS/2 keyboard SMI/PME events */
+		Or(CRF6, 0x10, CRF6)
 
-			/* Enable PS/2 keyboard SMI/PME events */
-			Or(CRF6, 0x10, CRF6)
+		/* Enable PS/2 keyboard wake */
+		Or(CRE0, 0x40, CRE0)
 
-			/* Enable PS/2 keyboard wake */
-			Or(CRE0, 0x40, CRE0)
+		/* Enable PS/2 mouse SMI/PME events */
+		Or(CRF6, 0x20, CRF6)
 
-			/* Enable PS/2 mouse SMI/PME events */
-			Or(CRF6, 0x20, CRF6)
+		/* Enable PS/2 mouse wake  */
+		Or(CRE0, 0x20, CRE0)
+	} else {
+		/* Enable PS/2 keyboard wake on any keypress */
+		Or(CRE0, 0x41, CRE0)
 
-			/* Enable PS/2 mouse wake  */
-			Or(CRE0, 0x20, CRE0)
-		} else {
-			/* Enable PS/2 keyboard wake on any keypress */
-			Or(CRE0, 0x41, CRE0)
+		/* Enable PS/2 mouse wake on any click  */
+		Or(CRE0, 0x22, CRE0)
+		Or(CRE6, 0x80, CRE6)
 
-			/* Enable PS/2 mouse wake on any click  */
-			Or(CRE0, 0x22, CRE0)
-			Or(CRE6, 0x80, CRE6)
+		if (LEqual(Arg0, 0x03))	/* Power state S3 requested */
+		{
+			/* Set VSBGATE# to provide standby power during S3 */
+			Or(CRE4, 0x10, CRE4)
 		}
+	}
 
-		/* Restore default SuperIO access */
-		Store(0xAA, INDX)
+	/* Restore default SuperIO access */
+	Store(0xAA, INDX)
 
-		Store (0x10, DBG8)
+	Store (0x10, DBG8)
 
-		/* Don't allow PCIRST# to reset USB */
-		if (LEqual(Arg0, 3)){
-			Store(0, URRE)
-		}
+	/* Don't allow PCIRST# to reset USB */
+	if (LEqual(Arg0, 3)){
+		Store(0, URRE)
+	}
 
-		/* Configure southbridge for sleep */
-		/* Clear sleep SMI status flag and enable sleep SMI trap. */
-		// Store(One, CSSM)	/* Set ExtEvent0 as SMI# source */
-		// Store(One, SSEN)	/* Enable wake on external event 0 */
+	/* Configure southbridge for sleep */
+	/* Use bus clock for delay timebase */
+	Store(0, BCDL)
+	/* Defer APIC interrupts until first ACPI access */
+	Store(One, MAPC)
 
-		/* On older chips, clear PciExpWakeDisEn */
-		// if (LLessEqual(SBRI, 0x13)) {
-		//	Store(0, PWDE)
-		// }
+	/* On older chips, clear PciExpWakeDisEn */
+	// if (LLessEqual(SBRI, 0x13)) {
+	//	Store(0, PWDE)
+	// }
 
-		Store (0x11, DBG8)
+	Store (0x11, DBG8)
 
-		/* Clear wake status structure. */
-		Store(0, Index(WKST,0))
-		Store(0, Index(WKST,1))
-	}
\ No newline at end of file
+	/* Clear wake status structure. */
+	Store(0, Index(WKST,0))
+	Store(0, Index(WKST,1))
+}
diff --git a/src/mainboard/asus/kgpe-d16/dsdt.asl b/src/mainboard/asus/kgpe-d16/dsdt.asl
index bdd1d2d..b6f10d9 100644
--- a/src/mainboard/asus/kgpe-d16/dsdt.asl
+++ b/src/mainboard/asus/kgpe-d16/dsdt.asl
@@ -58,9 +58,8 @@ DefinitionBlock (
 	/* Define power states */
 	Name (\_S0, Package () { 0x00, 0x00, 0x00, 0x00 })	/* Normal operation */
 	Name (\_S1, Package () { 0x01, 0x01, 0x00, 0x00 })	/* Standby */
-	Name (\_S2, Package () { 0x02, 0x02, 0x00, 0x00 })	/* Standby w/ CPU shutdown */
-	Name (\_S3, Package () { 0x03, 0x00, 0x00, 0x00 })	/* Suspend */
-	/* Name (\_S4, Package () { 0x04, 0x04, 0x00, 0x00 }) */
+	Name (\_S3, Package () { 0x03, 0x03, 0x00, 0x00 })	/* Suspend to RAM */
+	Name (\_S4, Package () { 0x04, 0x04, 0x00, 0x00 })	/* Suspend to disk */
 	Name (\_S5, Package () { 0x05, 0x05, 0x00, 0x00 })	/* Hard power off */
 
 	/* The _PIC method is called by the OS to choose between interrupt
diff --git a/src/mainboard/asus/kgpe-d16/romstage.c b/src/mainboard/asus/kgpe-d16/romstage.c
index 616fdfb..3431bab 100644
--- a/src/mainboard/asus/kgpe-d16/romstage.c
+++ b/src/mainboard/asus/kgpe-d16/romstage.c
@@ -224,12 +224,15 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
 {
 	struct sys_info *sysinfo = &sysinfo_car;
 
-	u32 bsp_apicid = 0, val;
+	uint32_t bsp_apicid = 0, val;
+	uint8_t byte;
 	msr_t msr;
 
 	timestamp_init(timestamp_get());
 	timestamp_add_now(TS_START_ROMSTAGE);
 
+	int s3resume = acpi_is_wakeup_s3();
+
 	if (!cpu_init_detectedx && boot_cpu()) {
 		/* Nothing special needs to be done to find bus 0 */
 		/* Allow the HT devices to be found */
@@ -247,6 +250,11 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
 		/* Initialize early serial */
 		nuvoton_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE);
 		console_init();
+
+		/* Disable LPC legacy DMA support to prevent lockup */
+		byte = pci_read_config8(PCI_DEV(0, 0x14, 3), 0x78);
+		byte &= ~(1 << 0);
+		pci_write_config8(PCI_DEV(0, 0x14, 3), 0x78, byte);
 	}
 
 	post_code(0x30);
@@ -285,14 +293,6 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
 	amd_ht_fixup(sysinfo);
 	post_code(0x35);
 
-	/* Set DDR memory voltage
-	 * FIXME
-	 * This should be set based on the output of the DIMM SPDs
-	 * For now it is locked to 1.5V
-	 */
-	set_ddr3_voltage(0, 0);	/* Node 0 */
-	set_ddr3_voltage(1, 0);	/* Node 1 */
-
 	/* Setup nodes PCI space and start core 0 AP init. */
 	finalize_node_setup(sysinfo);
 
@@ -355,6 +355,17 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
 		die("After soft_reset_x - shouldn't see this message!!!\n");
 	}
 
+	/* Set DDR memory voltage
+	 * FIXME
+	 * This should be set based on the output of the DIMM SPDs
+	 * For now it is locked to 1.5V
+	 */
+	set_lpc_sticky_ctl(1);	/* Retain LPC/IMC GPIO configuration during S3 sleep */
+	if (!s3resume) {	/* Avoid supply voltage glitches while the DIMMs are retaining data */
+		set_ddr3_voltage(0, 0);	/* Node 0 */
+		set_ddr3_voltage(1, 0);	/* Node 1 */
+	}
+
 	/* Set up peripheral control lines */
 	set_peripheral_control_lines();
 
@@ -384,7 +395,10 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
 	timestamp_add_now(TS_AFTER_INITRAM);
 
 #if !IS_ENABLED(CONFIG_LATE_CBMEM_INIT)
-	cbmem_initialize_empty();
+	if (s3resume)
+		cbmem_initialize();
+	else
+		cbmem_initialize_empty();
 	post_code(0x41);
 
 	amdmct_cbmem_store_info(sysinfo);
diff --git a/src/mainboard/asus/kgpe-d16/spd_notes.txt b/src/mainboard/asus/kgpe-d16/spd_notes.txt
index 623a88f..ddd5cc8 100644
--- a/src/mainboard/asus/kgpe-d16/spd_notes.txt
+++ b/src/mainboard/asus/kgpe-d16/spd_notes.txt
@@ -28,3 +28,19 @@ Other hardware
 
 RECOVERY1 middle pin is connected to southbridge (AMD SP5100) GPIO 61
 Normal is HIGH, recovery is LOW.
+
++12VSB is generated using a charge pump attached to pin 7 of PU24 (APW7145).
+
+The +12VSB standby voltage to each bank of DIMMs is switched by a bank of small FETs located close to each RAM power regulator control chip.
+The +12V primary voltage (lower left pin of the FET placed on the upper left of the control chip of the second node) is also connected to the 232GE located near the PCI slot.
+
+The control line running to the gates of the +12VSB control FETs is connected to the +5VSB power for the USB ports.
+That line in turn is connected to +5VSB via the lone P06P03G PMOS transistor on the reverse side of the board, near the center on the lower half.
+The gate of that transistor is connected via a resistor to the source of the P06P03G PMOS transistor located adjacent to the unpopulated SMA clock header.
+The gate of that transistor is connected directly to the drain of the small FET directly below it.
+After that, there's a cascade of small FETs and resistors in that region, eventually leading to SuperIO pin 81.
+
+SuperIO pin 81 (VSBGATE#) enables the standby voltage rails when set LOW.
+VSBGATE# is reset on every assertion of PWRGOOD.
+
+Setting SuperIO LDN 9 CRF4 bits 1 or 0 (or both) to 0 disables NICB.
\ No newline at end of file
-- 
1.7.9.5

