diff options
-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); |