diff options
author | Aaron Durbin <adurbin@chromium.org> | 2014-01-09 10:33:23 -0600 |
---|---|---|
committer | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2014-05-13 16:11:04 +0200 |
commit | 00bf3dbf350b48e78aab413958ec83692d8fa263 (patch) | |
tree | 541da4fed8c8e33967a5fc389496dfb23b51e563 | |
parent | 1ea9bde5af87fa786147773fcf2ee3faa7861945 (diff) |
baytrail: snapshot power state in romstage
The memory reference code doesn't maintain some of
the registers which contain valuable information in order
to log correct reset and wake events in the eventlog. Therefore
snapshot the registers which matter in this area so that
they can be consumed by ramstage.
BUG=chrome-os-partner:24907
BRANCH=rambi,squawks
TEST=Did various resets/wakes with logging patch which
consumes this structure. Eventlog can pick up reset
events and power failures.
Change-Id: Id8d2d782dd4e1133113f5308c4ccfe79bc6d3e03
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/181982
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: http://review.coreboot.org/5032
Tested-by: build bot (Jenkins)
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
-rw-r--r-- | src/include/cbmem.h | 1 | ||||
-rw-r--r-- | src/lib/cbmem_info.c | 1 | ||||
-rw-r--r-- | src/soc/intel/baytrail/baytrail/pmc.h | 66 | ||||
-rw-r--r-- | src/soc/intel/baytrail/romstage/romstage.c | 76 |
4 files changed, 121 insertions, 23 deletions
diff --git a/src/include/cbmem.h b/src/include/cbmem.h index f103b30299..beb626b9dc 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -61,6 +61,7 @@ #define CBMEM_ID_EHCI_DEBUG 0xe4c1deb9 #define CBMEM_ID_REFCODE 0x04efc0de #define CBMEM_ID_REFCODE_CACHE 0x4efc0de5 +#define CBMEM_ID_POWER_STATE 0x50535454 #define CBMEM_ID_SMM_SAVE_SPACE 0x07e9acee #define CBMEM_ID_RAM_OOPS 0x05430095 #define CBMEM_ID_NONE 0x00000000 diff --git a/src/lib/cbmem_info.c b/src/lib/cbmem_info.c index 42348e4d21..49724d6e28 100644 --- a/src/lib/cbmem_info.c +++ b/src/lib/cbmem_info.c @@ -52,6 +52,7 @@ static struct cbmem_id_to_name { { CBMEM_ID_REFCODE, "REFCODE " }, { CBMEM_ID_SMM_SAVE_SPACE, "SMM BACKUP " }, { CBMEM_ID_REFCODE_CACHE, "REFCODE $ " }, + { CBMEM_ID_POWER_STATE, "POWER STATE" }, { CBMEM_ID_RAM_OOPS, "RAMOOPS " }, }; diff --git a/src/soc/intel/baytrail/baytrail/pmc.h b/src/soc/intel/baytrail/baytrail/pmc.h index ab2e169243..5013db8b08 100644 --- a/src/soc/intel/baytrail/baytrail/pmc.h +++ b/src/soc/intel/baytrail/baytrail/pmc.h @@ -24,11 +24,51 @@ #define IOCOM1 0x3f8 /* Memory mapped IO registers behind PMC_BASE_ADDRESS */ +#define PRSTS 0x00 +# define PMC_WDT_STS (1 << 15) +# define SEC_GBLRST_STS (1 << 7) +# define SEC_WDT_STS (1 << 6) +# define WOL_OVR_WK_STS (1 << 5) +# define PMC_WAKE_STS (1 << 4) +#define PMC_CFG 0x08 +# define SPS (1 << 5) +# define NO_REBOOT (1 << 4) +# define SX_ENT_TO_EN (1 << 3) +# define TIMING_T581_SHIFT (0) +# define TIMING_T581_MASK (3 << TIMING_T581_SHIFT) +# define TIMING_T581_10uS (0 << TIMING_T581_SHIFT) +# define TIMING_T581_100uS (1 << TIMING_T581_SHIFT) +# define TIMING_T581_1mS (2 << TIMING_T581_SHIFT) +# define TIMING_T581_10mS (3 << TIMING_T581_SHIFT) +#define VLV_PM_STS 0x0c +# define PMC_MSG_FULL_STS (1 << 24) +# define PMC_MSG_4_FULL_STS (1 << 23) +# define PMC_MSG_3_FULL_STS (1 << 22) +# define PMC_MSG_2_FULL_STS (1 << 21) +# define PMC_MSG_1_FULL_STS (1 << 20) +# define CODE_REQ (1 << 8) +# define HPR_ENT_TO (1 << 2) +# define SX_ENT_TO (1 << 1) #define GEN_PMCON1 0x20 -# define AFTERG3_EN (1 << 0) # define UART_EN (1 << 24) +# define DISB (1 << 23) +# define MEM_SR (1 << 21) +# define SRS (1 << 20) +# define CTS (1 << 19) +# define MS4V (1 << 18) # define PWR_FLR (1 << 16) +# define PME_B0_S5_DIS (1 << 15) # define SUS_PWR_FLR (1 << 14) +# define WOL_EN_OVRD (1 << 13) +# define DIS_SLP_X_STRCH_SUS_UP (1 << 12) +# define GEN_RST_STS (1 << 9) +# define RPS (1 << 2) +# define AFTERG3_EN (1 << 0) +#define GEN_PMCON2 0x24 +# define SLPSX_STR_POL_LOCK (1 << 18) +# define BIOS_PCI_EXP_EN (1 << 10) +# define PWRBTN_LVL (1 << 9) +# define SMI_LOCK (1 << 4) #define ETR 0x48 # define CF9LOCK (1 << 31) # define LTR_DEF (1 << 22) @@ -84,6 +124,14 @@ # define CLK_CTL_D3_LPE (0x0 << 0) # define CLK_CTL_ON (0x1 << 0) # define CLK_CTL_OFF (0x2 << 0) +#define PME_STS 0xc0 +#define GPE_LEVEL_EDGE 0xc4 +# define GPE_EDGE 0 +# define GPE_LEVEL 1 +#define GPE_POLARITY 0xc8 +# define GPE_ACTIVE_HIGH 1 +# define GPE_ACTIVE_LOW 0 +#define LOCK 0xcc /* IO Mapped registers behind ACPI_BASE_ADDRESS */ #define PM1_STS 0x00 @@ -202,6 +250,18 @@ # define RST_CPU (1 << 2) # define SYS_RST (1 << 1) +/* Track power state from reset to log events. */ +struct chipset_power_state { + uint16_t pm1_sts; + uint16_t pm1_en; + uint32_t pm1_cnt; + uint32_t gpe0_sts; + uint32_t gpe0_en; + uint32_t tco_sts; + uint32_t prsts; + uint32_t gen_pmcon1; + uint32_t gen_pmcon2; +} __attribute__((packed)); /* Power Management Utility Functions. */ uint16_t get_pmbase(void); @@ -219,6 +279,10 @@ void enable_gpe(uint32_t mask); void disable_gpe(uint32_t mask); void disable_all_gpe(void); +#if CONFIG_ELOG +void southcluster_log_state(void); +#else static inline void southcluster_log_state(void) {} +#endif #endif /* _BAYTRAIL_PMC_H_ */ diff --git a/src/soc/intel/baytrail/romstage/romstage.c b/src/soc/intel/baytrail/romstage/romstage.c index cb884bd0f1..baa62a595e 100644 --- a/src/soc/intel/baytrail/romstage/romstage.c +++ b/src/soc/intel/baytrail/romstage/romstage.c @@ -22,6 +22,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> @@ -151,20 +152,56 @@ void * asmlinkage romstage_main(unsigned long bist, return setup_stack_and_mttrs(); } +static struct chipset_power_state power_state CAR_GLOBAL; + +static void migrate_power_state(void) +{ + struct chipset_power_state *ps_cbmem; + struct chipset_power_state *ps_car; + + ps_car = car_get_var_ptr(&power_state); + ps_cbmem = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*ps_cbmem)); + + if (ps_cbmem == NULL) { + printk(BIOS_DEBUG, "Not adding power state to cbmem!\n"); + return; + } + memcpy(ps_cbmem, ps_car, sizeof(*ps_cbmem)); +} +CAR_MIGRATE(migrate_power_state); + +static struct chipset_power_state *fill_power_state(void) +{ + struct chipset_power_state *ps = car_get_var_ptr(&power_state); + + ps->pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS); + ps->pm1_en = inw(ACPI_BASE_ADDRESS + PM1_EN); + ps->pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT); + ps->gpe0_sts = inl(ACPI_BASE_ADDRESS + GPE0_STS); + ps->gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN); + ps->tco_sts = inl(ACPI_BASE_ADDRESS + TCO_STS); + ps->prsts = read32(PMC_BASE_ADDRESS + PRSTS); + ps->gen_pmcon1 = read32(PMC_BASE_ADDRESS + GEN_PMCON1); + ps->gen_pmcon2 = read32(PMC_BASE_ADDRESS + GEN_PMCON2); + + printk(BIOS_DEBUG, "pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n", + ps->pm1_sts, ps->pm1_en, ps->pm1_cnt); + printk(BIOS_DEBUG, "gpe0_sts: %08x gpe0_en: %08x tco_sts: %08x\n", + ps->gpe0_sts, ps->gpe0_en, ps->tco_sts); + printk(BIOS_DEBUG, "prsts: %08x gen_pmcon1: %08x gen_pmcon2: %08x\n", + ps->prsts, ps->gen_pmcon1, ps->gen_pmcon2); + + return ps; +} + /* Return 0, 3, or 5 to indicate the previous sleep state. */ -static int chipset_prev_sleep_state(void) +static int chipset_prev_sleep_state(struct chipset_power_state *ps) { - 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 (ps->pm1_sts & WAK_STS) { + switch ((ps->pm1_cnt & SLP_TYP) >> SLP_TYP_SHIFT) { #if CONFIG_HAVE_ACPI_RESUME case SLP_TYP_S3: prev_sleep_state = 3; @@ -172,38 +209,32 @@ static int chipset_prev_sleep_state(void) #endif case SLP_TYP_S5: prev_sleep_state = 5; + break; } /* Clear SLP_TYP. */ - outl(pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT); + outl(ps->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); + if (ps->gen_pmcon1 & (PWR_FLR | SUS_PWR_FLR)) { 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; } -#if CONFIG_CHROMEOS static inline void chromeos_init(int prev_sleep_state) { +#if CONFIG_CHROMEOS /* Normalize the sleep state to what init_chromeos() wants for S3: 2. */ init_chromeos(prev_sleep_state == 3 ? 2 : 0); -} -#else -static inline void chromeos_init(int prev_sleep_state) {} #endif +} /* Entry from the mainboard. */ void romstage_common(struct romstage_params *params) { struct romstage_handoff *handoff; + struct chipset_power_state *ps; int prev_sleep_state; mark_ts(params, timestamp_get()); @@ -212,7 +243,8 @@ void romstage_common(struct romstage_params *params) boot_count_increment(); #endif - prev_sleep_state = chipset_prev_sleep_state(); + ps = fill_power_state(); + prev_sleep_state = chipset_prev_sleep_state(ps); printk(BIOS_DEBUG, "prev_sleep_state = S%d\n", prev_sleep_state); |