baytrail: add support for S3 resume
Previously the only path through memory init and coreboot was hardcoding S5. Therefore all S3 paths would not be taken. Allow for S3 resume to work by enabling the proper control paths in romstage. BUG=chrome-os-partner:22867 BRANCH=None TEST=While in kernel 'echo mem > /sys/power/state'. Board went into S3. Power button press resumed back into kernel. Change-Id: I3cbae73223f0d71c74eb3d6b7c25d1b32318ab3e Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/175940 Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: http://review.coreboot.org/4943 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
This commit is contained in:
parent
2237324e77
commit
6e3289372c
|
@ -24,9 +24,11 @@
|
||||||
#define IOCOM1 0x3f8
|
#define IOCOM1 0x3f8
|
||||||
|
|
||||||
/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
|
/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
|
||||||
#define GEN_PMCONF1 0x20
|
#define GEN_PMCON1 0x20
|
||||||
# define AFTERG3_EN (1 << 0)
|
# define AFTERG3_EN (1 << 0)
|
||||||
# define UART_EN (1 << 24)
|
# define UART_EN (1 << 24)
|
||||||
|
# define PWR_FLR (1 << 16)
|
||||||
|
# define SUS_PWR_FLR (1 << 14)
|
||||||
#define ETR 0x48
|
#define ETR 0x48
|
||||||
# define CF9LOCK (1 << 31)
|
# define CF9LOCK (1 << 31)
|
||||||
# define LTR_DEF (1 << 22)
|
# define LTR_DEF (1 << 22)
|
||||||
|
@ -86,7 +88,8 @@
|
||||||
#define TMROF_EN (1 << 0)
|
#define TMROF_EN (1 << 0)
|
||||||
#define PM1_CNT 0x04
|
#define PM1_CNT 0x04
|
||||||
#define SLP_EN (1 << 13)
|
#define SLP_EN (1 << 13)
|
||||||
#define SLP_TYP (7 << 10)
|
#define SLP_TYP_SHIFT 10
|
||||||
|
#define SLP_TYP (7 << SLP_TYP_SHIFT)
|
||||||
#define SLP_TYP_S0 0
|
#define SLP_TYP_S0 0
|
||||||
#define SLP_TYP_S1 1
|
#define SLP_TYP_S1 1
|
||||||
#define SLP_TYP_S3 5
|
#define SLP_TYP_S3 5
|
||||||
|
|
|
@ -18,7 +18,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <arch/hlt.h>
|
||||||
#include <arch/io.h>
|
#include <arch/io.h>
|
||||||
|
#include <bootmode.h>
|
||||||
#include <cbfs.h>
|
#include <cbfs.h>
|
||||||
#include <cbmem.h>
|
#include <cbmem.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
|
@ -28,8 +30,14 @@
|
||||||
#include <baytrail/iomap.h>
|
#include <baytrail/iomap.h>
|
||||||
#include <baytrail/iosf.h>
|
#include <baytrail/iosf.h>
|
||||||
#include <baytrail/pci_devs.h>
|
#include <baytrail/pci_devs.h>
|
||||||
|
#include <baytrail/reset.h>
|
||||||
#include <baytrail/romstage.h>
|
#include <baytrail/romstage.h>
|
||||||
|
|
||||||
|
static void reset_system(void)
|
||||||
|
{
|
||||||
|
warm_reset();
|
||||||
|
while(1) { hlt(); }
|
||||||
|
}
|
||||||
|
|
||||||
static void enable_smbus(void)
|
static void enable_smbus(void)
|
||||||
{
|
{
|
||||||
|
@ -111,9 +119,16 @@ void raminit(struct mrc_params *mp, int prev_sleep_state)
|
||||||
mp->console_out = &send_to_console;
|
mp->console_out = &send_to_console;
|
||||||
mp->prev_sleep_state = prev_sleep_state;
|
mp->prev_sleep_state = prev_sleep_state;
|
||||||
|
|
||||||
if (!mrc_cache_get_current(&cache)) {
|
if (recovery_mode_enabled()) {
|
||||||
|
printk(BIOS_DEBUG, "Recovery mode: not using MRC cache.\n");
|
||||||
|
} else if (!mrc_cache_get_current(&cache)) {
|
||||||
mp->saved_data_size = cache->size;
|
mp->saved_data_size = cache->size;
|
||||||
mp->saved_data = &cache->data[0];
|
mp->saved_data = &cache->data[0];
|
||||||
|
} else if (prev_sleep_state == 3) {
|
||||||
|
/* If waking from S3 and no cache then. */
|
||||||
|
printk(BIOS_DEBUG, "No MRC cache found in S3 resume path.\n");
|
||||||
|
post_code(POST_RESUME_FAILURE);
|
||||||
|
reset_system();
|
||||||
} else {
|
} else {
|
||||||
printk(BIOS_DEBUG, "No MRC cache found.\n");
|
printk(BIOS_DEBUG, "No MRC cache found.\n");
|
||||||
}
|
}
|
||||||
|
@ -132,7 +147,15 @@ void raminit(struct mrc_params *mp, int prev_sleep_state)
|
||||||
|
|
||||||
print_dram_info();
|
print_dram_info();
|
||||||
|
|
||||||
cbmem_initialize_empty();
|
if (prev_sleep_state != 3) {
|
||||||
|
cbmem_initialize_empty();
|
||||||
|
} else if (cbmem_initialize()) {
|
||||||
|
#if CONFIG_HAVE_ACPI_RESUME
|
||||||
|
printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n");
|
||||||
|
/* Failed S3 resume, reset to come up cleanly */
|
||||||
|
reset_system();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "MRC Wrapper returned %d\n", ret);
|
printk(BIOS_DEBUG, "MRC Wrapper returned %d\n", ret);
|
||||||
printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", mp->data_to_save,
|
printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", mp->data_to_save,
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <baytrail/iomap.h>
|
#include <baytrail/iomap.h>
|
||||||
#include <baytrail/lpc.h>
|
#include <baytrail/lpc.h>
|
||||||
#include <baytrail/pci_devs.h>
|
#include <baytrail/pci_devs.h>
|
||||||
|
#include <baytrail/pmc.h>
|
||||||
#include <baytrail/reset.h>
|
#include <baytrail/reset.h>
|
||||||
#include <baytrail/romstage.h>
|
#include <baytrail/romstage.h>
|
||||||
#include <baytrail/smm.h>
|
#include <baytrail/smm.h>
|
||||||
|
@ -139,10 +140,50 @@ void * asmlinkage romstage_main(unsigned long bist,
|
||||||
return setup_stack_and_mttrs();
|
return setup_stack_and_mttrs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 0, 3, or 5 to indicate the previous sleep state. */
|
||||||
|
static int chipset_prev_sleep_state(void)
|
||||||
|
{
|
||||||
|
uint16_t pm1_sts;
|
||||||
|
uint32_t pm1_cnt;
|
||||||
|
uint32_t gen_pmcon1;
|
||||||
|
/* Default to S0. */
|
||||||
|
int prev_sleep_state = 0;
|
||||||
|
|
||||||
|
pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
|
||||||
|
pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
|
||||||
|
|
||||||
|
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_S5:
|
||||||
|
prev_sleep_state = 5;
|
||||||
|
}
|
||||||
|
/* Clear SLP_TYP. */
|
||||||
|
outl(pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_pmcon1 = read32(PMC_BASE_ADDRESS + GEN_PMCON1);
|
||||||
|
if (gen_pmcon1 & (PWR_FLR | SUS_PWR_FLR)) {
|
||||||
|
/* Clear power failure bits. */
|
||||||
|
write32(PMC_BASE_ADDRESS + GEN_PMCON1, gen_pmcon1);
|
||||||
|
prev_sleep_state = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk(BIOS_DEBUG, "pm1_sts = %04x pm1_cnt = %08x gen_pmcon1 = %08x\n",
|
||||||
|
pm1_sts, pm1_cnt, gen_pmcon1);
|
||||||
|
|
||||||
|
return prev_sleep_state;
|
||||||
|
}
|
||||||
|
|
||||||
/* Entry from the mainboard. */
|
/* Entry from the mainboard. */
|
||||||
void romstage_common(struct romstage_params *params)
|
void romstage_common(struct romstage_params *params)
|
||||||
{
|
{
|
||||||
struct romstage_handoff *handoff;
|
struct romstage_handoff *handoff;
|
||||||
|
int prev_sleep_state;
|
||||||
|
|
||||||
mark_ts(params, timestamp_get());
|
mark_ts(params, timestamp_get());
|
||||||
|
|
||||||
|
@ -150,14 +191,18 @@ void romstage_common(struct romstage_params *params)
|
||||||
boot_count_increment();
|
boot_count_increment();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
prev_sleep_state = chipset_prev_sleep_state();
|
||||||
|
|
||||||
|
printk(BIOS_DEBUG, "prev_sleep_state = S%d\n", prev_sleep_state);
|
||||||
|
|
||||||
/* Initialize RAM */
|
/* Initialize RAM */
|
||||||
raminit(params->mrc_params, 5);
|
raminit(params->mrc_params, prev_sleep_state);
|
||||||
|
|
||||||
mark_ts(params, timestamp_get());
|
mark_ts(params, timestamp_get());
|
||||||
|
|
||||||
handoff = romstage_handoff_find_or_add();
|
handoff = romstage_handoff_find_or_add();
|
||||||
if (handoff != NULL)
|
if (handoff != NULL)
|
||||||
handoff->s3_resume = 0;
|
handoff->s3_resume = (prev_sleep_state == 3);
|
||||||
else
|
else
|
||||||
printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
|
printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue