[coreboot-gerrit] New patch to review for coreboot: 81d6346 minnowmax: Add S3 suspend/resume Support

Mohan D'Costa (mohan@ndr.co.jp) gerrit at coreboot.org
Thu Sep 18 08:56:29 CEST 2014


Mohan D'Costa (mohan at ndr.co.jp) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/6937

-gerrit

commit 81d634610439e913114bd6cc85cbf23776d04cd4
Author: Mohan D'Costa <mohan at ndr.co.jp>
Date:   Thu Sep 18 15:57:06 2014 +0900

    minnowmax: Add S3 suspend/resume Support
    
    This adds S3 Suspend / Resume support to MinnowMax board
    using Intel's Bay Trail FSP
    It is based on the "src/soc/intel/baytrail/romstage/romstage.c"
    implementation.
    Tested resume from Power Button and Magic Packet.
    
    Notes:
    Fast boot needs to be enabled.
    
    Change-Id: If0011068eb7290d1b764c5c4b12c17375fb69008
    Signed-off-by: Mohan D'Costa <mohan at ndr.co.jp>
---
 src/drivers/intel/fsp/fsp_util.c                  |  4 +-
 src/drivers/intel/fsp/fsp_util.h                  |  5 +-
 src/mainboard/intel/minnowmax/Kconfig             |  1 +
 src/soc/intel/fsp_baytrail/acpi/sleepstates.asl   |  1 +
 src/soc/intel/fsp_baytrail/fsp/chipset_fsp_util.c | 28 ++++++++-
 src/soc/intel/fsp_baytrail/ramstage.c             | 32 ++++++++++
 src/soc/intel/fsp_baytrail/romstage/romstage.c    | 77 +++++++++++++++++++++--
 7 files changed, 137 insertions(+), 11 deletions(-)

diff --git a/src/drivers/intel/fsp/fsp_util.c b/src/drivers/intel/fsp/fsp_util.c
index a9b5624..a2833a4 100644
--- a/src/drivers/intel/fsp/fsp_util.c
+++ b/src/drivers/intel/fsp/fsp_util.c
@@ -71,7 +71,7 @@ void FspNotify (u32 Phase)
  * Call the FSP to do memory init. The FSP doesn't return to this function.
  * The FSP returns to the romstage_main_continue().
  */
-void __attribute__ ((noreturn)) fsp_early_init (FSP_INFO_HEADER *fsp_ptr)
+void __attribute__ ((noreturn)) fsp_early_init (FSP_INFO_HEADER *fsp_ptr, unsigned int prev_sleep_state)
 {
 	FSP_FSP_INIT FspInitApi;
 	FSP_INIT_PARAMS FspInitParams;
@@ -92,7 +92,7 @@ void __attribute__ ((noreturn)) fsp_early_init (FSP_INFO_HEADER *fsp_ptr)
 	FspInitApi = (FSP_FSP_INIT)(fsp_ptr->ImageBase + fsp_ptr->FspInitEntry);
 
 	/* Call the chipset code to fill in the chipset specific structures */
-	chipset_fsp_early_init(&FspInitParams, fsp_ptr);
+	chipset_fsp_early_init(&FspInitParams, fsp_ptr, prev_sleep_state);
 
 	/* Call back to romstage for board specific changes */
 	romstage_fsp_rt_buffer_callback(&FspRtBuffer);
diff --git a/src/drivers/intel/fsp/fsp_util.h b/src/drivers/intel/fsp/fsp_util.h
index db8b6de..aeecfab 100644
--- a/src/drivers/intel/fsp/fsp_util.h
+++ b/src/drivers/intel/fsp/fsp_util.h
@@ -28,7 +28,8 @@ void * find_and_set_fastboot_cache(void);
 #endif
 
 volatile u8 * find_fsp (void);
-void fsp_early_init(FSP_INFO_HEADER *fsp_info);
+void fsp_early_init(FSP_INFO_HEADER *fsp_info, 
+	unsigned int prev_sleep_state);
 void FspNotify(u32 Phase);
 void FspNotifyReturnPoint(EFI_STATUS Status, VOID *HobListPtr);
 void print_hob_type_structure(u16 Hobtype, void *Hoblistptr);
@@ -36,7 +37,7 @@ void romstage_fsp_rt_buffer_callback(FSP_INIT_RT_BUFFER *FspRtBuffer);
 void print_fsp_info(void);
 
 void chipset_fsp_early_init(FSP_INIT_PARAMS *FspInitParams,
-	FSP_INFO_HEADER *fsp_ptr);
+	FSP_INFO_HEADER *fsp_ptr, unsigned int prev_sleep_state);
 void ChipsetFspReturnPoint(EFI_STATUS Status, VOID *HobListPtr);
 
 /* Additional HOB types not included in the FSP:
diff --git a/src/mainboard/intel/minnowmax/Kconfig b/src/mainboard/intel/minnowmax/Kconfig
index 0e83d5a..229172c 100644
--- a/src/mainboard/intel/minnowmax/Kconfig
+++ b/src/mainboard/intel/minnowmax/Kconfig
@@ -27,6 +27,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select HAVE_OPTION_TABLE
 	select OVERRIDE_MRC_CACHE_LOC
 	select TSC_MONOTONIC_TIMER
+	select HAVE_ACPI_RESUME
 
 config MAINBOARD_DIR
 	string
diff --git a/src/soc/intel/fsp_baytrail/acpi/sleepstates.asl b/src/soc/intel/fsp_baytrail/acpi/sleepstates.asl
index 65339cc..8abeb2d 100644
--- a/src/soc/intel/fsp_baytrail/acpi/sleepstates.asl
+++ b/src/soc/intel/fsp_baytrail/acpi/sleepstates.asl
@@ -21,5 +21,6 @@
 
 Name(\_S0, Package(){0x0,0x0,0x0,0x0})
 // Name(\_S1, Package(){0x1,0x1,0x0,0x0})
+Name(\_S3, Package(){0x5,0x5,0x0,0x0})
 Name(\_S4, Package(){0x6,0x6,0x0,0x0})
 Name(\_S5, Package(){0x7,0x7,0x0,0x0})
diff --git a/src/soc/intel/fsp_baytrail/fsp/chipset_fsp_util.c b/src/soc/intel/fsp_baytrail/fsp/chipset_fsp_util.c
index 60a1f7a..e9db7a9 100644
--- a/src/soc/intel/fsp_baytrail/fsp/chipset_fsp_util.c
+++ b/src/soc/intel/fsp_baytrail/fsp/chipset_fsp_util.c
@@ -28,7 +28,11 @@
 #include <baytrail/pci_devs.h>
 #include <drivers/intel/fsp/fsp_util.h>
 #include "../chip.h"
+#include <arch/io.h>
 #include <baytrail/reset.h>
+#include <baytrail/pmc.h>
+#include <baytrail/acpi.h>
+#include <baytrail/iomap.h>
 
 #ifdef __PRE_RAM__
 #include <baytrail/romstage.h>
@@ -304,7 +308,7 @@ static void ConfigureDefaultUpdData(UPD_DATA_REGION *UpdData)
 
 /* Set up the Baytrail specific structures for the call into the FSP */
 void chipset_fsp_early_init(FSP_INIT_PARAMS *pFspInitParams,
-		FSP_INFO_HEADER *fsp_ptr)
+		FSP_INFO_HEADER *fsp_ptr, unsigned int prev_sleep_state)
 {
 	FSP_INIT_RT_BUFFER *pFspRtBuffer = pFspInitParams->RtBufferPtr;
 
@@ -312,13 +316,33 @@ void chipset_fsp_early_init(FSP_INIT_PARAMS *pFspInitParams,
 	GetUpdDefaultFromFsp (fsp_ptr, pFspRtBuffer->Common.UpdDataRgnPtr);
 	ConfigureDefaultUpdData(pFspRtBuffer->Common.UpdDataRgnPtr);
 	pFspInitParams->NvsBufferPtr = NULL;
-	pFspRtBuffer->Common.BootMode = BOOT_WITH_FULL_CONFIGURATION;
 
 #if IS_ENABLED(CONFIG_ENABLE_FSP_FAST_BOOT)
 	/* Find the fastboot cache that was saved in the ROM */
 	pFspInitParams->NvsBufferPtr = find_and_set_fastboot_cache();
 #endif
 
+	if (prev_sleep_state == 3) {
+		/* S3 resume */
+		if ( pFspInitParams->NvsBufferPtr == NULL) {
+			/* If waking from S3 and no cache then. */
+			printk(BIOS_WARNING, "No MRC cache found in S3 resume path.\n");
+			post_code(POST_RESUME_FAILURE);
+			/* Clear Sleep Type */
+			outl(inl(ACPI_BASE_ADDRESS + PM1_CNT) & 
+				~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
+			/* Reboot */
+			printk(BIOS_WARNING,"Rebooting..\n" );
+			warm_reset();
+			/* Should not reach here.. */
+			die("Reboot System\n");
+		}
+		pFspRtBuffer->Common.BootMode = BOOT_ON_S3_RESUME;
+	} else {
+		/* Not S3 resume */
+		pFspRtBuffer->Common.BootMode = BOOT_WITH_FULL_CONFIGURATION;
+	}
+
 	return;
 }
 
diff --git a/src/soc/intel/fsp_baytrail/ramstage.c b/src/soc/intel/fsp_baytrail/ramstage.c
index e231701..58010f4 100644
--- a/src/soc/intel/fsp_baytrail/ramstage.c
+++ b/src/soc/intel/fsp_baytrail/ramstage.c
@@ -18,6 +18,7 @@
  */
 
 #include <arch/cpu.h>
+#include <arch/acpi.h>
 #include <console/console.h>
 #include <cpu/intel/microcode.h>
 #include <cpu/x86/cr.h>
@@ -25,10 +26,12 @@
 #include <device/device.h>
 #include <device/pci_def.h>
 #include <device/pci_ops.h>
+#include <romstage_handoff.h>
 #include <stdlib.h>
 
 #include <baytrail/gpio.h>
 #include <baytrail/lpc.h>
+#include <baytrail/nvs.h>
 #include <baytrail/msr.h>
 #include <baytrail/pattrs.h>
 #include <baytrail/pci_devs.h>
@@ -123,6 +126,32 @@ static void fill_in_pattrs(void)
 }
 
 
+static inline void set_acpi_sleep_type(int val)
+{
+#if CONFIG_HAVE_ACPI_RESUME
+        acpi_slp_type = val;
+#endif
+}
+
+static void s3_resume_prepare(void)
+{
+        global_nvs_t *gnvs;
+        struct romstage_handoff *romstage_handoff;
+
+        gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t));
+
+        romstage_handoff = cbmem_find(CBMEM_ID_ROMSTAGE_INFO);
+        if (romstage_handoff == NULL || romstage_handoff->s3_resume == 0) {
+                if (gnvs != NULL) {
+                        memset(gnvs, 0, sizeof(global_nvs_t));
+                }
+                set_acpi_sleep_type(0);
+                return;
+        }
+
+        set_acpi_sleep_type(3);
+}
+
 void baytrail_init_pre_device(void)
 {
 	struct soc_gpio_config *config;
@@ -132,6 +161,9 @@ void baytrail_init_pre_device(void)
 	/* Allow for SSE instructions to be executed. */
 	write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT);
 
+        /* Indicate S3 resume to rest of ramstage. */
+        s3_resume_prepare();
+
 	/* Get GPIO initial states from mainboard */
 	config = mainboard_get_gpios();
 	setup_soc_gpios(config);
diff --git a/src/soc/intel/fsp_baytrail/romstage/romstage.c b/src/soc/intel/fsp_baytrail/romstage/romstage.c
index a63156f..3cc73b9 100644
--- a/src/soc/intel/fsp_baytrail/romstage/romstage.c
+++ b/src/soc/intel/fsp_baytrail/romstage/romstage.c
@@ -24,6 +24,7 @@
 #include <arch/io.h>
 #include <arch/cbfs.h>
 #include <arch/stages.h>
+#include <arch/early_variables.h> 
 #include <console/console.h>
 #include <cbmem.h>
 #include <cpu/x86/mtrr.h>
@@ -44,6 +45,51 @@
 #include <device/pci_def.h>
 #include <console/cbmem_console.h>
 
+/* Return 0, 3, 4 or 5 to indicate the previous sleep state. */
+static int chipset_prev_sleep_state(unsigned int clear)
+{
+        /* Default to S0. */
+        unsigned int prev_sleep_state = 0;
+	unsigned int pm1_sts;
+	unsigned int pm1_cnt;
+	unsigned int gen_pmcon1;
+
+	/* Read Power State */
+	pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
+	pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
+	gen_pmcon1 = read32(PMC_BASE_ADDRESS + GEN_PMCON1);
+	
+	printk(BIOS_DEBUG, "PM1_STS = 0x%x PM1_CNT = 0x%x GEN_PMCON1 = 0x%x\n", 
+		pm1_sts, pm1_cnt, gen_pmcon1);
+
+        if (pm1_sts & WAK_STS) {
+                switch ((pm1_cnt & SLP_TYP) >> SLP_TYP_SHIFT) {
+        #if CONFIG_HAVE_ACPI_RESUME
+                case SLP_TYP_S3:
+                        prev_sleep_state = 3;
+                        break;
+        #endif
+                case SLP_TYP_S4:
+                        prev_sleep_state = 4;
+                        break;
+
+                case SLP_TYP_S5:
+                        prev_sleep_state = 5;
+                        break;
+                }
+                /* If set Clear SLP_TYP. */
+                if (clear == 1) {
+			outl(pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
+		}
+        }
+
+        if (gen_pmcon1 & (PWR_FLR | SUS_PWR_FLR)) {
+                prev_sleep_state = 5;
+        }
+
+        return prev_sleep_state;
+}
+
 static void program_base_addresses(void)
 {
 	uint32_t reg;
@@ -115,6 +161,7 @@ void * asmlinkage main(FSP_INFO_HEADER *fsp_info_header)
 	const unsigned long func_dis2 = PMC_BASE_ADDRESS + FUNC_DIS2;
 	uint32_t fd_mask = 0;
 	uint32_t fd2_mask = 0;
+        unsigned int prev_sleep_state;
 
 	post_code(0x40);
 
@@ -156,6 +203,10 @@ void * asmlinkage main(FSP_INFO_HEADER *fsp_info_header)
 
 	post_code(0x47);
 
+	/* Get previous sleep state but don't clear */
+	prev_sleep_state = chipset_prev_sleep_state(0);
+	printk(BIOS_INFO, "prev_sleep_state = S%d\n", prev_sleep_state);
+
   /*
    * Call early init to initialize memory and chipset. This function returns
    * to the romstage_main_continue function with a pointer to the HOB
@@ -163,7 +214,7 @@ void * asmlinkage main(FSP_INFO_HEADER *fsp_info_header)
    */
 	post_code(0x48);
 	printk(BIOS_DEBUG, "Starting the Intel FSP (early_init)\n");
-	fsp_early_init(fsp_info_header);
+	fsp_early_init(fsp_info_header, prev_sleep_state);
 	die("Uh Oh! fsp_early_init should not return here.\n");
 }
 
@@ -174,6 +225,8 @@ void * asmlinkage main(FSP_INFO_HEADER *fsp_info_header)
 void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr) {
 	int cbmem_was_initted;
 	void *cbmem_hob_ptr;
+	unsigned int prev_sleep_state;
+	struct romstage_handoff *handoff;
 
 #if IS_ENABLED(CONFIG_COLLECT_TIMESTAMPS)
 	tsc_t after_initram_time = rdtsc();
@@ -193,6 +246,10 @@ void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr) {
 
 	printk(BIOS_DEBUG, "FSP Status: 0x%0x\n", (u32)status);
 
+	/* Get previous sleep state again and clear */
+	prev_sleep_state = chipset_prev_sleep_state(1);
+	printk(BIOS_DEBUG, "%s: prev_sleep_state = S%d\n", __func__, prev_sleep_state);
+
 	report_platform_info();
 
 #if IS_ENABLED(CONFIG_COLLECT_TIMESTAMPS)
@@ -203,16 +260,26 @@ void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr) {
 	late_mainboard_romstage_entry();
 	post_code(0x4c);
 
-	quick_ram_check();
-	post_code(0x4d);
-
-	cbmem_was_initted = !cbmem_recovery(0);
+	/* if S3 resume skip ram check */
+	if (prev_sleep_state != 3) {
+		quick_ram_check();
+	 	post_code(0x4d);
+	}
+	
+	cbmem_was_initted = !cbmem_recovery((prev_sleep_state == 3));
 
 	/* Save the HOB pointer in CBMEM to be used in ramstage*/
 	cbmem_hob_ptr = cbmem_add (CBMEM_ID_HOB_POINTER, sizeof(*hob_list_ptr));
 	*(u32*)cbmem_hob_ptr = (u32)hob_list_ptr;
 	post_code(0x4e);
 
+        handoff = romstage_handoff_find_or_add();
+        if (handoff != NULL)
+                handoff->s3_resume = (prev_sleep_state == 3);
+        else
+                printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
+
+
 #if IS_ENABLED(CONFIG_COLLECT_TIMESTAMPS)
 	timestamp_init(base_time);
 	timestamp_reinit();



More information about the coreboot-gerrit mailing list