summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/cbmem.h1
-rw-r--r--src/lib/cbmem_info.c1
-rw-r--r--src/soc/intel/baytrail/baytrail/pmc.h66
-rw-r--r--src/soc/intel/baytrail/romstage/romstage.c76
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);