[coreboot] Patch set updated for coreboot: 8856afb S3 code in the mainboard.

Zheng Bao (zheng.bao@amd.com) gerrit at coreboot.org
Wed Feb 15 05:23:33 CET 2012


Zheng Bao (zheng.bao at amd.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/624

-gerrit

commit 8856afbe841195bff70cab07b49e0a4534e9f71f
Author: zbao <fishbaozi at gmail.com>
Date:   Wed Feb 15 13:18:20 2012 +0800

    S3 code in the mainboard.
    
    Persimmon is the demo board. Tested by Linux and Windows 7.
    
    Change-Id: I5ded942b51e63ebeb08ace0b202b4ed239b0c14c
    Signed-off-by: Zheng Bao <zheng.bao at amd.com>
    Signed-off-by: zbao <fishbaozi at gmail.com>
---
 src/mainboard/amd/persimmon/BiosCallOuts.c         |   75 +++++----
 src/mainboard/amd/persimmon/BiosCallOuts.h         |    4 +-
 src/mainboard/amd/persimmon/Kconfig                |    1 +
 src/mainboard/amd/persimmon/PlatformGnbPcie.c      |    2 +-
 .../amd/persimmon/PlatformGnbPcieComplex.h         |    1 +
 src/mainboard/amd/persimmon/agesawrapper.c         |  173 +++++++++++++++++++-
 src/mainboard/amd/persimmon/agesawrapper.h         |    5 +
 src/mainboard/amd/persimmon/buildOpts.c            |    6 +-
 src/mainboard/amd/persimmon/get_bus_conf.c         |   18 ++-
 src/mainboard/amd/persimmon/mainboard.c            |   16 ++-
 src/mainboard/amd/persimmon/romstage.c             |   90 ++++++++--
 11 files changed, 328 insertions(+), 63 deletions(-)

diff --git a/src/mainboard/amd/persimmon/BiosCallOuts.c b/src/mainboard/amd/persimmon/BiosCallOuts.c
index c8379ff..df00c7c 100644
--- a/src/mainboard/amd/persimmon/BiosCallOuts.c
+++ b/src/mainboard/amd/persimmon/BiosCallOuts.c
@@ -81,6 +81,10 @@ AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 	AGESA_STATUS CalloutStatus;
 	UINTN CallOutCount = sizeof (BiosCallouts) / sizeof (BiosCallouts [0]);
 
+	/*
+	 * printk(BIOS_SPEW,"%s function: %x\n", __func__, (u32) Func);
+	 */
+
 	CalloutStatus = AGESA_UNSUPPORTED;
 
 	for (i = 0; i < CallOutCount; i++) {
@@ -95,28 +99,30 @@ AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 
 AGESA_STATUS BiosAllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 {
-	UINT32				AvailableHeapSize;
-	UINT8				*BiosHeapBaseAddr;
-	UINT32				CurrNodeOffset;
-	UINT32				PrevNodeOffset;
-	UINT32				FreedNodeOffset;
-	UINT32				BestFitNodeOffset;
-	UINT32				BestFitPrevNodeOffset;
-	UINT32				NextFreeOffset;
-	BIOS_BUFFER_NODE	*CurrNodePtr;
-	BIOS_BUFFER_NODE	*FreedNodePtr;
-	BIOS_BUFFER_NODE	*BestFitNodePtr;
-	BIOS_BUFFER_NODE	*BestFitPrevNodePtr;
-	BIOS_BUFFER_NODE	*NextFreePtr;
-	BIOS_HEAP_MANAGER	*BiosHeapBasePtr;
+	UINT32              AvailableHeapSize;
+	UINT8               *BiosHeapBaseAddr;
+	UINT32              CurrNodeOffset;
+	UINT32              PrevNodeOffset;
+	UINT32              FreedNodeOffset;
+	UINT32              BestFitNodeOffset;
+	UINT32              BestFitPrevNodeOffset;
+	UINT32              NextFreeOffset;
+	BIOS_BUFFER_NODE   *CurrNodePtr;
+	BIOS_BUFFER_NODE   *FreedNodePtr;
+	BIOS_BUFFER_NODE   *BestFitNodePtr;
+	BIOS_BUFFER_NODE   *BestFitPrevNodePtr;
+	BIOS_BUFFER_NODE   *NextFreePtr;
+	BIOS_HEAP_MANAGER  *BiosHeapBasePtr;
 	AGESA_BUFFER_PARAMS *AllocParams;
 
 	AllocParams = ((AGESA_BUFFER_PARAMS *) ConfigPtr);
 	AllocParams->BufferPointer = NULL;
 
 	AvailableHeapSize = BIOS_HEAP_SIZE - sizeof (BIOS_HEAP_MANAGER);
-	BiosHeapBaseAddr = (UINT8 *) BIOS_HEAP_START_ADDRESS;
-	BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BIOS_HEAP_START_ADDRESS;
+	BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader));
+	BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr;
+
+	printk(BIOS_SPEW, "%s BiosHeapBaseAddr: %x\n", __func__, (u32) BiosHeapBaseAddr);
 
 	if (BiosHeapBasePtr->StartOfAllocatedNodes == 0) {
 		/* First allocation */
@@ -224,32 +230,33 @@ AGESA_STATUS BiosAllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 AGESA_STATUS BiosDeallocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 {
 
-	UINT8				 *BiosHeapBaseAddr;
-	UINT32				AllocNodeOffset;
-	UINT32				PrevNodeOffset;
-	UINT32				NextNodeOffset;
-	UINT32				FreedNodeOffset;
-	UINT32				EndNodeOffset;
-	BIOS_BUFFER_NODE	 *AllocNodePtr;
-	BIOS_BUFFER_NODE	 *PrevNodePtr;
-	BIOS_BUFFER_NODE	 *FreedNodePtr;
-	BIOS_BUFFER_NODE	 *NextNodePtr;
-	BIOS_HEAP_MANAGER	*BiosHeapBasePtr;
+	UINT8               *BiosHeapBaseAddr;
+	UINT32              AllocNodeOffset;
+	UINT32              PrevNodeOffset;
+	UINT32              NextNodeOffset;
+	UINT32              FreedNodeOffset;
+	UINT32              EndNodeOffset;
+	BIOS_BUFFER_NODE   *AllocNodePtr;
+	BIOS_BUFFER_NODE   *PrevNodePtr;
+	BIOS_BUFFER_NODE   *FreedNodePtr;
+	BIOS_BUFFER_NODE   *NextNodePtr;
+	BIOS_HEAP_MANAGER  *BiosHeapBasePtr;
 	AGESA_BUFFER_PARAMS *AllocParams;
 
-	BiosHeapBaseAddr = (UINT8 *) BIOS_HEAP_START_ADDRESS;
-	BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BIOS_HEAP_START_ADDRESS;
-
 	AllocParams = (AGESA_BUFFER_PARAMS *) ConfigPtr;
 
+	BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader));
+	BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr;
+
+
 	/* Find target node to deallocate in list of allocated nodes.
-	 Return AGESA_BOUNDS_CHK if the BufferHandle is not found
+	   Return AGESA_BOUNDS_CHK if the BufferHandle is not found
 	*/
 	AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
 	AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
 	PrevNodeOffset = AllocNodeOffset;
 
-	while (AllocNodePtr->BufferHandle !=	AllocParams->BufferHandle) {
+	while (AllocNodePtr->BufferHandle !=  AllocParams->BufferHandle) {
 		if (AllocNodePtr->NextNodeOffset == 0) {
 			return AGESA_BOUNDS_CHK;
 		}
@@ -348,8 +355,8 @@ AGESA_STATUS BiosLocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 
 	AllocParams = (AGESA_BUFFER_PARAMS *) ConfigPtr;
 
-	BiosHeapBaseAddr = (UINT8 *) BIOS_HEAP_START_ADDRESS;
-	BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BIOS_HEAP_START_ADDRESS;
+	BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader));
+	BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr;
 
 	AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
 	AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
diff --git a/src/mainboard/amd/persimmon/BiosCallOuts.h b/src/mainboard/amd/persimmon/BiosCallOuts.h
index d9e4497..071c73c 100644
--- a/src/mainboard/amd/persimmon/BiosCallOuts.h
+++ b/src/mainboard/amd/persimmon/BiosCallOuts.h
@@ -23,8 +23,8 @@
 #include "Porting.h"
 #include "AGESA.h"
 
-#define BIOS_HEAP_START_ADDRESS		0x00010000
-#define BIOS_HEAP_SIZE				0x20000		/* 64MB */
+#define BIOS_HEAP_SIZE				0x20000
+#define BSP_STACK_BASE_ADDR			0x30000
 
 typedef struct _BIOS_HEAP_MANAGER {
 	//UINT32 AvailableSize;
diff --git a/src/mainboard/amd/persimmon/Kconfig b/src/mainboard/amd/persimmon/Kconfig
index e01e101..01ea3a8 100644
--- a/src/mainboard/amd/persimmon/Kconfig
+++ b/src/mainboard/amd/persimmon/Kconfig
@@ -33,6 +33,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select HAVE_PIRQ_TABLE
 	select HAVE_MP_TABLE
 	select HAVE_MAINBOARD_RESOURCES
+	select HAVE_ACPI_RESUME
 	select HAVE_HARD_RESET
 	select SB_HT_CHAIN_UNITID_OFFSET_ONLY
 	select LIFT_BSP_APIC_ID
diff --git a/src/mainboard/amd/persimmon/PlatformGnbPcie.c b/src/mainboard/amd/persimmon/PlatformGnbPcie.c
index 5e37f51..bdfcb66 100644
--- a/src/mainboard/amd/persimmon/PlatformGnbPcie.c
+++ b/src/mainboard/amd/persimmon/PlatformGnbPcie.c
@@ -23,6 +23,7 @@
 #include "heapManager.h"
 #include "PlatformGnbPcieComplex.h"
 #include "Filecode.h"
+#include "BiosCallOuts.h"
 
 #define FILECODE PROC_RECOVERY_MEM_NB_ON_MRNON_FILECODE
 
@@ -165,4 +166,3 @@ PCIe_COMPLEX_DESCRIPTOR Brazos = {
 	InitEarly->GnbConfig.PcieComplexList = BrazosPcieComplexListPtr;
 	InitEarly->GnbConfig.PsppPolicy		= 0;
 }
-
diff --git a/src/mainboard/amd/persimmon/PlatformGnbPcieComplex.h b/src/mainboard/amd/persimmon/PlatformGnbPcieComplex.h
index b50cb1a..a49be62 100644
--- a/src/mainboard/amd/persimmon/PlatformGnbPcieComplex.h
+++ b/src/mainboard/amd/persimmon/PlatformGnbPcieComplex.h
@@ -23,6 +23,7 @@
 #include "Porting.h"
 #include "AGESA.h"
 #include "amdlib.h"
+#include <cpu/amd/agesa/s3_resume.h>
 
 //GNB GPP Port4
 #define GNB_GPP_PORT4_PORT_PRESENT		1	//0:Disable 1:Enable
diff --git a/src/mainboard/amd/persimmon/agesawrapper.c b/src/mainboard/amd/persimmon/agesawrapper.c
index 6e9997f..53ca04c 100644
--- a/src/mainboard/amd/persimmon/agesawrapper.c
+++ b/src/mainboard/amd/persimmon/agesawrapper.c
@@ -33,10 +33,12 @@
 #include "cpuLateInit.h"
 #include "Dispatcher.h"
 #include "cpuCacheInit.h"
+#include "heapManager.h"
 #include "amdlib.h"
 #include "PlatformGnbPcieComplex.h"
 #include "Filecode.h"
 #include <arch/io.h>
+#include <cpu/amd/agesa/s3_resume.h>
 
 #define FILECODE UNASSIGNED_FILE_FILECODE
 
@@ -243,6 +245,35 @@ agesawrapper_amdinitearly (
 	return (UINT32)status;
 }
 
+
+UINT32 GetHeapBase(
+	AMD_CONFIG_PARAMS *StdHeader
+	)
+{
+	UINT64			MsrReg;
+	UINT32			sys_mem, uma_base, uma_size;
+
+	/* TOP_MEM: the top of DRAM below 4G */
+	LibAmdMsrRead(TOP_MEM, &MsrReg, StdHeader);
+
+	/* refer to UMA Size Consideration in Family14h BKDG. */
+	sys_mem = (UINT32)(MsrReg & 0xFFFFFFFFUL) + 0x1000000; // Ignore 16MB allocated for C6 when finding UMA size, refer MemNGetUmaSizeON()
+	if ((MsrReg & 0x0000000F00000000) || (sys_mem >= 0x80000000)) {
+		uma_size = 0x18000000;	/* >= 2G memory, 384M recommended UMA */
+	}
+	else {
+	  if (sys_mem >= 0x40000000) {
+		  uma_size = 0x10000000;	/* >= 1G memory, 256M recommended UMA */
+	  }
+	  else {
+		  uma_size = 0x4000000;	/* <1G memory, 64M recommended UMA */
+	  }
+	}
+
+	uma_base =  (UINT32)(MsrReg & 0xFFFFFFFFUL) - uma_size ;	/* TOP_MEM1 */
+	return uma_base  - BIOS_HEAP_SIZE;
+}
+
 UINT32
 agesawrapper_amdinitpost (
 	VOID
@@ -272,7 +303,7 @@ agesawrapper_amdinitpost (
 	AmdReleaseStruct (&AmdParamStruct);
 
 	/* Initialize heap space */
-	BiosManagerPtr = (BIOS_HEAP_MANAGER *)BIOS_HEAP_START_ADDRESS;
+	BiosManagerPtr = (BIOS_HEAP_MANAGER *)GetHeapBase(&AmdParamStruct.StdHeader);
 
 	HeadPtr = (UINT32 *) ((UINT8 *) BiosManagerPtr + sizeof (BIOS_HEAP_MANAGER));
 	for (i = 0; i < ((BIOS_HEAP_SIZE/4) - (sizeof (BIOS_HEAP_MANAGER)/4)); i++) {
@@ -496,6 +527,146 @@ agesawrapper_amdinitlate (
 	return (UINT32)Status;
 }
 
+#if CONFIG_HAVE_ACPI_RESUME == 1
+UINT32
+agesawrapper_amdinitresume (
+  VOID
+  )
+{
+	AGESA_STATUS status;
+	AMD_INTERFACE_PARAMS AmdParamStruct;
+	AMD_RESUME_PARAMS     *AmdResumeParamsPtr;
+	S3_DATA_TYPE            S3DataType;
+
+	LibAmdMemFill (&AmdParamStruct,
+		       0,
+		       sizeof (AMD_INTERFACE_PARAMS),
+		       &(AmdParamStruct.StdHeader));
+
+	AmdParamStruct.AgesaFunctionName = AMD_INIT_RESUME;
+	AmdParamStruct.AllocationMethod = PreMemHeap;
+	AmdParamStruct.StdHeader.AltImageBasePtr = 0;
+	AmdParamStruct.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout;
+	AmdParamStruct.StdHeader.Func = 0;
+	AmdParamStruct.StdHeader.ImageBasePtr = 0;
+	AmdCreateStruct (&AmdParamStruct);
+
+	AmdResumeParamsPtr = (AMD_RESUME_PARAMS *)AmdParamStruct.NewStructPtr;
+
+	AmdResumeParamsPtr->S3DataBlock.NvStorageSize = 0;
+	AmdResumeParamsPtr->S3DataBlock.VolatileStorageSize = 0;
+	S3DataType = S3DataTypeNonVolatile;
+
+	OemAgesaGetS3Info (S3DataType,
+			   (u32 *) &AmdResumeParamsPtr->S3DataBlock.NvStorageSize,
+			   (void **) &AmdResumeParamsPtr->S3DataBlock.NvStorage);
+
+	status = AmdInitResume ((AMD_RESUME_PARAMS *)AmdParamStruct.NewStructPtr);
+
+	if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog();
+	AmdReleaseStruct (&AmdParamStruct);
+
+	return (UINT32)status;
+}
+
+UINT32
+agesawrapper_amds3laterestore (
+  VOID
+  )
+{
+	AGESA_STATUS Status;
+	AMD_INTERFACE_PARAMS    AmdInterfaceParams;
+	AMD_S3LATE_PARAMS       AmdS3LateParams;
+	AMD_S3LATE_PARAMS       *AmdS3LateParamsPtr;
+	S3_DATA_TYPE          S3DataType;
+
+	LibAmdMemFill (&AmdS3LateParams,
+		       0,
+		       sizeof (AMD_S3LATE_PARAMS),
+		       &(AmdS3LateParams.StdHeader));
+	AmdInterfaceParams.StdHeader.ImageBasePtr = 0;
+	AmdInterfaceParams.AllocationMethod = ByHost;
+	AmdInterfaceParams.AgesaFunctionName = AMD_S3LATE_RESTORE;
+	AmdInterfaceParams.NewStructPtr = &AmdS3LateParams;
+	AmdInterfaceParams.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout;
+	AmdS3LateParamsPtr = &AmdS3LateParams;
+	AmdInterfaceParams.NewStructSize = sizeof (AMD_S3LATE_PARAMS);
+
+	AmdCreateStruct (&AmdInterfaceParams);
+
+	AmdS3LateParamsPtr->S3DataBlock.VolatileStorageSize = 0;
+	S3DataType = S3DataTypeVolatile;
+
+	OemAgesaGetS3Info (S3DataType,
+			   (u32 *) &AmdS3LateParamsPtr->S3DataBlock.VolatileStorageSize,
+			   (void **) &AmdS3LateParamsPtr->S3DataBlock.VolatileStorage);
+
+	Status = AmdS3LateRestore (AmdS3LateParamsPtr);
+	if (Status != AGESA_SUCCESS) {
+		agesawrapper_amdreadeventlog();
+		ASSERT(Status == AGESA_SUCCESS);
+	}
+
+	return (UINT32)Status;
+}
+
+UINT32
+agesawrapper_amdS3Save (
+	VOID
+	)
+{
+	AGESA_STATUS Status;
+	AMD_S3SAVE_PARAMS *AmdS3SaveParamsPtr;
+	AMD_INTERFACE_PARAMS  AmdInterfaceParams;
+	S3_DATA_TYPE          S3DataType;
+
+	LibAmdMemFill (&AmdInterfaceParams,
+		       0,
+		       sizeof (AMD_INTERFACE_PARAMS),
+		       &(AmdInterfaceParams.StdHeader));
+
+	AmdInterfaceParams.StdHeader.ImageBasePtr = 0;
+	AmdInterfaceParams.StdHeader.HeapStatus = HEAP_SYSTEM_MEM;
+	AmdInterfaceParams.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout;
+	AmdInterfaceParams.AllocationMethod = PostMemDram;
+	AmdInterfaceParams.AgesaFunctionName = AMD_S3_SAVE;
+	AmdInterfaceParams.StdHeader.AltImageBasePtr = 0;
+	AmdInterfaceParams.StdHeader.Func = 0;
+	AmdCreateStruct(&AmdInterfaceParams);
+
+	AmdS3SaveParamsPtr = (AMD_S3SAVE_PARAMS *)AmdInterfaceParams.NewStructPtr;
+	AmdS3SaveParamsPtr->StdHeader = AmdInterfaceParams.StdHeader;
+
+	Status = AmdS3Save (AmdS3SaveParamsPtr);
+	if (Status != AGESA_SUCCESS) {
+		agesawrapper_amdreadeventlog();
+		ASSERT(Status == AGESA_SUCCESS);
+	}
+
+	S3DataType = S3DataTypeNonVolatile;
+
+	Status = OemAgesaSaveS3Info (
+		S3DataType,
+		AmdS3SaveParamsPtr->S3DataBlock.NvStorageSize,
+		AmdS3SaveParamsPtr->S3DataBlock.NvStorage);
+
+	if (AmdS3SaveParamsPtr->S3DataBlock.VolatileStorageSize != 0) {
+		S3DataType = S3DataTypeVolatile;
+
+		Status = OemAgesaSaveS3Info (
+			S3DataType,
+			AmdS3SaveParamsPtr->S3DataBlock.VolatileStorageSize,
+			AmdS3SaveParamsPtr->S3DataBlock.VolatileStorage
+			);
+	}
+
+	OemAgesaSaveMtrr();
+	AmdReleaseStruct (&AmdInterfaceParams);
+
+	return (UINT32)Status;
+}
+#endif
+
 UINT32
 agesawrapper_amdlaterunaptask (
 	UINT32 Func,
diff --git a/src/mainboard/amd/persimmon/agesawrapper.h b/src/mainboard/amd/persimmon/agesawrapper.h
index 7bed570..7babd58 100644
--- a/src/mainboard/amd/persimmon/agesawrapper.h
+++ b/src/mainboard/amd/persimmon/agesawrapper.h
@@ -84,7 +84,12 @@ UINT32 agesawrapper_amdreadeventlog (void);
 
 UINT32 agesawrapper_amdinitcpuio (void);
 UINT32 agesawrapper_amdinitmmio (void);
+UINT32 agesawrapper_amdinitresume (void);
+UINT32 agesawrapper_amdS3Save (void);
+UINT32 agesawrapper_amds3laterestore (void);
 UINT32 agesawrapper_amdlaterunaptask (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
 void *agesawrapper_getlateinitptr (int pick);
 
+UINT32 GetHeapBase(AMD_CONFIG_PARAMS *StdHeader);
+
 #endif
diff --git a/src/mainboard/amd/persimmon/buildOpts.c b/src/mainboard/amd/persimmon/buildOpts.c
index 3e5b14e..0b79e5f 100644
--- a/src/mainboard/amd/persimmon/buildOpts.c
+++ b/src/mainboard/amd/persimmon/buildOpts.c
@@ -120,8 +120,8 @@
 #define AGESA_ENTRY_INIT_LATE					TRUE
 #define AGESA_ENTRY_INIT_S3SAVE					TRUE
 #define AGESA_ENTRY_INIT_RESUME					TRUE
-#define AGESA_ENTRY_INIT_LATE_RESTORE			FALSE
-#define AGESA_ENTRY_INIT_GENERAL_SERVICES		FALSE
+#define AGESA_ENTRY_INIT_LATE_RESTORE				TRUE //FALSE
+#define AGESA_ENTRY_INIT_GENERAL_SERVICES			TRUE //FALSE
 
 #define BLDCFG_PCI_MMIO_BASE					CONFIG_MMCONF_BASE_ADDRESS
 #define BLDCFG_PCI_MMIO_SIZE					CONFIG_MMCONF_BUS_NUMBER
@@ -169,7 +169,7 @@
 //#define BLDCFG_USE_HT_ASSIST					TRUE
 //#define BLDCFG_USE_ATM_MODE					TRUE
 //#define BLDCFG_PLATFORM_CONTROL_FLOW_MODE		Nfcm
-#define BLDCFG_S3_LATE_RESTORE					FALSE
+#define BLDCFG_S3_LATE_RESTORE					TRUE
 //#define BLDCFG_USE_32_BYTE_REFRESH			FALSE
 //#define BLDCFG_USE_VARIABLE_MCT_ISOC_PRIORITY	FALSE
 //#define BLDCFG_PLATFORM_POWER_POLICY_MODE		Performance
diff --git a/src/mainboard/amd/persimmon/get_bus_conf.c b/src/mainboard/amd/persimmon/get_bus_conf.c
index 0142762..fef7d60 100644
--- a/src/mainboard/amd/persimmon/get_bus_conf.c
+++ b/src/mainboard/amd/persimmon/get_bus_conf.c
@@ -51,6 +51,9 @@ u32 sbdn_sb800;
 
 static u32 get_bus_conf_done = 0;
 
+#if CONFIG_HAVE_ACPI_RESUME == 1
+extern u8 acpi_slp_type;
+#endif
 
 void get_bus_conf(void)
 {
@@ -80,11 +83,20 @@ void get_bus_conf(void)
  * of each of the write functions called prior to the ACPI write functions, so this
  * becomes the best place for this call.
  */
+#if CONFIG_HAVE_ACPI_RESUME == 1
+	if (acpi_slp_type != 3) {
+		status = agesawrapper_amdinitlate();
+		if(status)
+			printk(BIOS_DEBUG, "agesawrapper_amdinitlate failed: %x \n", status);
+		status = agesawrapper_amdS3Save();
+		if(status)
+			printk(BIOS_DEBUG, "agesawrapper_amds3save failed: %x \n", status);
+	}
+#else
 	status = agesawrapper_amdinitlate();
-	if(status) {
+	if(status)
 		printk(BIOS_DEBUG, "agesawrapper_amdinitlate failed: %x \n", status);
-	}
-
+#endif
 	sbdn_sb800 = 0;
 
 	for (i = 0; i < 3; i++) {
diff --git a/src/mainboard/amd/persimmon/mainboard.c b/src/mainboard/amd/persimmon/mainboard.c
index 3b181a1..9a8428e 100644
--- a/src/mainboard/amd/persimmon/mainboard.c
+++ b/src/mainboard/amd/persimmon/mainboard.c
@@ -23,10 +23,13 @@
 #include <arch/io.h>
 #include <boot/tables.h>
 #include <cpu/x86/msr.h>
-#include <cpu/amd/mtrr.h>
 #include <device/pci_def.h>
-//#include <southbridge/amd/sb800/sb800.h>
+#include <southbridge/amd/sb800/sb800.h>
+#include <arch/acpi.h>
 #include "chip.h"
+#include "BiosCallOuts.h"
+#include <cpu/amd/agesa/s3_resume.h>
+#include <cpu/amd/mtrr.h>
 
 void set_pcie_reset(void);
 void set_pcie_dereset(void);
@@ -56,6 +59,14 @@ static void persimmon_enable(device_t dev)
 {
 	printk(BIOS_INFO, "Mainboard " CONFIG_MAINBOARD_PART_NUMBER " Enable.\n");
 
+/*
+ * The mainboard is the first place that we get control in ramstage. Check
+ * for S3 resume and call the approriate AGESA/CIMx resume functions.
+ */
+#if CONFIG_HAVE_ACPI_RESUME == 1
+	acpi_slp_type = acpi_get_sleep_type();
+#endif
+
 #if (CONFIG_GFXUMA == 1)
 	msr_t msr, msr2;
 	uint32_t sys_mem;
@@ -110,6 +121,7 @@ int add_mainboard_resources(struct lb_memory *mem)
 #endif
 	return 0;
 }
+
 struct chip_operations mainboard_ops = {
 	CHIP_NAME(CONFIG_MAINBOARD_VENDOR " " CONFIG_MAINBOARD_PART_NUMBER " Mainboard")
 	.enable_dev = persimmon_enable,
diff --git a/src/mainboard/amd/persimmon/romstage.c b/src/mainboard/amd/persimmon/romstage.c
index dfb1aca..52756ff 100644
--- a/src/mainboard/amd/persimmon/romstage.c
+++ b/src/mainboard/amd/persimmon/romstage.c
@@ -35,9 +35,14 @@
 #include "cpu/x86/lapic/boot_cpu.c"
 #include "pc80/i8254.c"
 #include "pc80/i8259.c"
+#include <cpu/x86/cache.h>
 #include "sb_cimx.h"
 #include "SBPLATFORM.h"
+#include "cbmem.h"
+#include "cpu/amd/mtrr.h"
+#include "cpu/amd/agesa/s3_resume.h"
 
+void disable_cache_as_ram(void); /* cache_as_ram.inc */
 void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx);
 
 #define SERIAL_DEV PNP_DEV(0x4e, F81865F_SP1)
@@ -46,6 +51,10 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
 {
 	u32 val;
 
+#if CONFIG_HAVE_ACPI_RESUME == 1
+	void *resume_backup_memory;
+#endif
+
 	/*
 	 * All cores: allow caching of flash chip code and data
 	 * (there are no cache-as-ram reliability concerns with family 14h)
@@ -98,28 +107,75 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
 	else
 		printk(BIOS_DEBUG, "passed.\n");
 
-	post_code(0x40);
-	printk(BIOS_DEBUG, "agesawrapper_amdinitpost ");
-	val = agesawrapper_amdinitpost ();
-	if (val)
-		printk(BIOS_DEBUG, "error level: %x \n", val);
-	else
-		printk(BIOS_DEBUG, "passed.\n");
-
-	post_code(0x41);
-	printk(BIOS_DEBUG, "agesawrapper_amdinitenv ");
-	val = agesawrapper_amdinitenv ();
-	if (val)
-		printk(BIOS_DEBUG, "error level: %x \n", val);
-	else
-		printk(BIOS_DEBUG, "passed.\n");
+#if CONFIG_HAVE_ACPI_RESUME == 1
+	if (!acpi_is_wakeup_early()) { /* Check for S3 resume */
+#endif
+		post_code(0x40);
+		printk(BIOS_DEBUG, "agesawrapper_amdinitpost ");
+		val = agesawrapper_amdinitpost ();
+		if (val)
+			printk(BIOS_DEBUG, "error level: %x \n", val);
+		else
+			printk(BIOS_DEBUG, "passed.\n");
+
+		post_code(0x42);
+		printk(BIOS_DEBUG, "agesawrapper_amdinitenv ");
+		val = agesawrapper_amdinitenv ();
+		if (val)
+			printk(BIOS_DEBUG, "error level: %x \n", val);
+		else
+			printk(BIOS_DEBUG, "passed.\n");
+
+#if CONFIG_HAVE_ACPI_RESUME == 1
+	} else { 			/* S3 detect */
+		printk(BIOS_INFO, "S3 detected\n");
+
+		post_code(0x60);
+		printk(BIOS_DEBUG, "agesawrapper_amdinitresume ");
+		val = agesawrapper_amdinitresume();
+		if (val)
+			printk(BIOS_DEBUG, "error level: %x \n", val);
+		else
+			printk(BIOS_DEBUG, "passed.\n");
+
+		post_code(0x61);
+		printk(BIOS_DEBUG, "Find resume memory location\n");
+		resume_backup_memory = backup_resume();
+
+		post_code(0x62);
+		printk(BIOS_DEBUG, "Move CAR stack.\n");
+		move_stack_high_mem(resume_backup_memory + HIGH_MEMORY_SAVE);
+		printk(BIOS_DEBUG, "stack moved to: 0x%x\n", (u32) (resume_backup_memory + HIGH_MEMORY_SAVE));
+
+		post_code(0x63);
+		disable_cache_as_ram();
+		printk(BIOS_DEBUG, "CAR disabled.\n");
+		set_resume_cache();
+
+		printk(BIOS_DEBUG, "agesawrapper_amds3laterestore ");
+		val = agesawrapper_amds3laterestore ();
+		if (val)
+			printk(BIOS_DEBUG, "error level: %x \n", val);
+		else
+			printk(BIOS_DEBUG, "passed.\n");
+
+		/*
+		 * Copy the system memory that is in the ramstage area to the
+		 * reserved area.
+		 */
+		if (resume_backup_memory)
+			memcopy_fast(resume_backup_memory, (void *)(CONFIG_RAMBASE), HIGH_MEMORY_SAVE);
+
+		printk(BIOS_DEBUG, "System memory saved. OK to load ramstage.\n");
+	}
+#endif
 
 	/* Initialize i8259 pic */
-	post_code(0x41);
+	post_code(0x43);
 	setup_i8259 ();
 
 	/* Initialize i8254 timers */
-	post_code(0x42);
+	post_code(0x44);
 	setup_i8254 ();
 
 	post_code(0x50);




More information about the coreboot mailing list