intel/fsp_baytrail: Add S3 suspend/resume Support
This adds S3 Suspend / Resume support to Intel's Bay Trail FSP It is based on the "src/soc/intel/baytrail/romstage/romstage.c" implementation. Change-Id: If0011068eb7290d1b764c5c4b12c17375fb69008 Signed-off-by: Mohan D'Costa <mohan@ndr.co.jp> Reviewed-on: http://review.coreboot.org/6937 Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: Martin Roth <gaumless@gmail.com> Tested-by: build bot (Jenkins)
This commit is contained in:
parent
bdae9bedcd
commit
ed0c83877f
|
@ -63,6 +63,7 @@ config ENABLE_FSP_FAST_BOOT
|
||||||
|
|
||||||
config ENABLE_MRC_CACHE
|
config ENABLE_MRC_CACHE
|
||||||
bool
|
bool
|
||||||
|
default y if HAVE_ACPI_RESUME
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
Enabling this feature will cause MRC data to be cached in NV storage.
|
Enabling this feature will cause MRC data to be cached in NV storage.
|
||||||
|
|
|
@ -21,5 +21,8 @@
|
||||||
|
|
||||||
Name(\_S0, Package(){0x0,0x0,0x0,0x0})
|
Name(\_S0, Package(){0x0,0x0,0x0,0x0})
|
||||||
// Name(\_S1, Package(){0x1,0x1,0x0,0x0})
|
// Name(\_S1, Package(){0x1,0x1,0x0,0x0})
|
||||||
|
#if CONFIG_HAVE_ACPI_RESUME
|
||||||
|
Name(\_S3, Package(){0x5,0x5,0x0,0x0})
|
||||||
|
#endif
|
||||||
Name(\_S4, Package(){0x6,0x6,0x0,0x0})
|
Name(\_S4, Package(){0x6,0x6,0x0,0x0})
|
||||||
Name(\_S5, Package(){0x7,0x7,0x0,0x0})
|
Name(\_S5, Package(){0x7,0x7,0x0,0x0})
|
||||||
|
|
|
@ -33,6 +33,7 @@ void report_platform_info(void);
|
||||||
#include <fsptypes.h>
|
#include <fsptypes.h>
|
||||||
|
|
||||||
void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr);
|
void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr);
|
||||||
|
uint32_t chipset_prev_sleep_state(uint32_t clear);
|
||||||
|
|
||||||
#define NUM_ROMSTAGE_TS 4
|
#define NUM_ROMSTAGE_TS 4
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,11 @@
|
||||||
#include <baytrail/pci_devs.h>
|
#include <baytrail/pci_devs.h>
|
||||||
#include <drivers/intel/fsp/fsp_util.h>
|
#include <drivers/intel/fsp/fsp_util.h>
|
||||||
#include "../chip.h"
|
#include "../chip.h"
|
||||||
|
#include <arch/io.h>
|
||||||
#include <baytrail/reset.h>
|
#include <baytrail/reset.h>
|
||||||
|
#include <baytrail/pmc.h>
|
||||||
|
#include <baytrail/acpi.h>
|
||||||
|
#include <baytrail/iomap.h>
|
||||||
|
|
||||||
#ifdef __PRE_RAM__
|
#ifdef __PRE_RAM__
|
||||||
#include <baytrail/romstage.h>
|
#include <baytrail/romstage.h>
|
||||||
|
@ -307,18 +311,43 @@ void chipset_fsp_early_init(FSP_INIT_PARAMS *pFspInitParams,
|
||||||
FSP_INFO_HEADER *fsp_ptr)
|
FSP_INFO_HEADER *fsp_ptr)
|
||||||
{
|
{
|
||||||
FSP_INIT_RT_BUFFER *pFspRtBuffer = pFspInitParams->RtBufferPtr;
|
FSP_INIT_RT_BUFFER *pFspRtBuffer = pFspInitParams->RtBufferPtr;
|
||||||
|
uint32_t prev_sleep_state;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
/* Initialize the UPD Data */
|
/* Initialize the UPD Data */
|
||||||
GetUpdDefaultFromFsp (fsp_ptr, pFspRtBuffer->Common.UpdDataRgnPtr);
|
GetUpdDefaultFromFsp (fsp_ptr, pFspRtBuffer->Common.UpdDataRgnPtr);
|
||||||
ConfigureDefaultUpdData(pFspRtBuffer->Common.UpdDataRgnPtr);
|
ConfigureDefaultUpdData(pFspRtBuffer->Common.UpdDataRgnPtr);
|
||||||
pFspInitParams->NvsBufferPtr = NULL;
|
pFspInitParams->NvsBufferPtr = NULL;
|
||||||
pFspRtBuffer->Common.BootMode = BOOT_WITH_FULL_CONFIGURATION;
|
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ENABLE_FSP_FAST_BOOT)
|
#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
|
||||||
/* Find the fastboot cache that was saved in the ROM */
|
/* Find the fastboot cache that was saved in the ROM */
|
||||||
pFspInitParams->NvsBufferPtr = find_and_set_fastboot_cache();
|
pFspInitParams->NvsBufferPtr = find_and_set_fastboot_cache();
|
||||||
#endif
|
#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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
#include <arch/acpi.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <cpu/intel/microcode.h>
|
#include <cpu/intel/microcode.h>
|
||||||
#include <cpu/x86/cr.h>
|
#include <cpu/x86/cr.h>
|
||||||
|
@ -25,10 +26,12 @@
|
||||||
#include <device/device.h>
|
#include <device/device.h>
|
||||||
#include <device/pci_def.h>
|
#include <device/pci_def.h>
|
||||||
#include <device/pci_ops.h>
|
#include <device/pci_ops.h>
|
||||||
|
#include <romstage_handoff.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <baytrail/gpio.h>
|
#include <baytrail/gpio.h>
|
||||||
#include <baytrail/lpc.h>
|
#include <baytrail/lpc.h>
|
||||||
|
#include <baytrail/nvs.h>
|
||||||
#include <baytrail/msr.h>
|
#include <baytrail/msr.h>
|
||||||
#include <baytrail/pattrs.h>
|
#include <baytrail/pattrs.h>
|
||||||
#include <baytrail/pci_devs.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)
|
void baytrail_init_pre_device(void)
|
||||||
{
|
{
|
||||||
struct soc_gpio_config *config;
|
struct soc_gpio_config *config;
|
||||||
|
@ -132,6 +161,9 @@ void baytrail_init_pre_device(void)
|
||||||
/* Allow for SSE instructions to be executed. */
|
/* Allow for SSE instructions to be executed. */
|
||||||
write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT);
|
write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT);
|
||||||
|
|
||||||
|
/* Indicate S3 resume to rest of ramstage. */
|
||||||
|
s3_resume_prepare();
|
||||||
|
|
||||||
/* Get GPIO initial states from mainboard */
|
/* Get GPIO initial states from mainboard */
|
||||||
config = mainboard_get_gpios();
|
config = mainboard_get_gpios();
|
||||||
setup_soc_gpios(config);
|
setup_soc_gpios(config);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <arch/io.h>
|
#include <arch/io.h>
|
||||||
#include <arch/cbfs.h>
|
#include <arch/cbfs.h>
|
||||||
#include <arch/stages.h>
|
#include <arch/stages.h>
|
||||||
|
#include <arch/early_variables.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <cbmem.h>
|
#include <cbmem.h>
|
||||||
#include <cpu/x86/mtrr.h>
|
#include <cpu/x86/mtrr.h>
|
||||||
|
@ -44,6 +45,51 @@
|
||||||
#include <device/pci_def.h>
|
#include <device/pci_def.h>
|
||||||
#include <console/cbmem_console.h>
|
#include <console/cbmem_console.h>
|
||||||
|
|
||||||
|
/* Return 0, 3, 4 or 5 to indicate the previous sleep state. */
|
||||||
|
uint32_t chipset_prev_sleep_state(uint32_t clear)
|
||||||
|
{
|
||||||
|
/* Default to S0. */
|
||||||
|
uint32_t prev_sleep_state = 0;
|
||||||
|
uint32_t pm1_sts;
|
||||||
|
uint32_t pm1_cnt;
|
||||||
|
uint32_t 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)
|
static void program_base_addresses(void)
|
||||||
{
|
{
|
||||||
uint32_t reg;
|
uint32_t reg;
|
||||||
|
@ -174,6 +220,8 @@ void * asmlinkage main(FSP_INFO_HEADER *fsp_info_header)
|
||||||
void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr) {
|
void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr) {
|
||||||
int cbmem_was_initted;
|
int cbmem_was_initted;
|
||||||
void *cbmem_hob_ptr;
|
void *cbmem_hob_ptr;
|
||||||
|
uint32_t prev_sleep_state;
|
||||||
|
struct romstage_handoff *handoff;
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_COLLECT_TIMESTAMPS)
|
#if IS_ENABLED(CONFIG_COLLECT_TIMESTAMPS)
|
||||||
tsc_t after_initram_time = rdtsc();
|
tsc_t after_initram_time = rdtsc();
|
||||||
|
@ -193,6 +241,10 @@ void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr) {
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "FSP Status: 0x%0x\n", (u32)status);
|
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();
|
report_platform_info();
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_COLLECT_TIMESTAMPS)
|
#if IS_ENABLED(CONFIG_COLLECT_TIMESTAMPS)
|
||||||
|
@ -203,16 +255,26 @@ void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr) {
|
||||||
late_mainboard_romstage_entry();
|
late_mainboard_romstage_entry();
|
||||||
post_code(0x4c);
|
post_code(0x4c);
|
||||||
|
|
||||||
|
/* if S3 resume skip ram check */
|
||||||
|
if (prev_sleep_state != 3) {
|
||||||
quick_ram_check();
|
quick_ram_check();
|
||||||
post_code(0x4d);
|
post_code(0x4d);
|
||||||
|
}
|
||||||
|
|
||||||
cbmem_was_initted = !cbmem_recovery(0);
|
cbmem_was_initted = !cbmem_recovery(prev_sleep_state == 3);
|
||||||
|
|
||||||
/* Save the HOB pointer in CBMEM to be used in ramstage*/
|
/* Save the HOB pointer in CBMEM to be used in ramstage*/
|
||||||
cbmem_hob_ptr = cbmem_add (CBMEM_ID_HOB_POINTER, sizeof(*hob_list_ptr));
|
cbmem_hob_ptr = cbmem_add (CBMEM_ID_HOB_POINTER, sizeof(*hob_list_ptr));
|
||||||
*(u32*)cbmem_hob_ptr = (u32)hob_list_ptr;
|
*(u32*)cbmem_hob_ptr = (u32)hob_list_ptr;
|
||||||
post_code(0x4e);
|
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)
|
#if IS_ENABLED(CONFIG_COLLECT_TIMESTAMPS)
|
||||||
timestamp_init(base_time);
|
timestamp_init(base_time);
|
||||||
timestamp_reinit();
|
timestamp_reinit();
|
||||||
|
|
Loading…
Reference in New Issue