aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/apollolake/Makefile.inc1
-rw-r--r--src/soc/intel/apollolake/elog.c107
-rw-r--r--src/soc/intel/apollolake/include/soc/pm.h34
-rw-r--r--src/soc/intel/apollolake/pmc.c3
4 files changed, 140 insertions, 5 deletions
diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc
index cae90b5558..1f3c276c3a 100644
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -49,6 +49,7 @@ smm-y += uart_early.c
ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
ramstage-y += cpu.c
ramstage-y += chip.c
+ramstage-y += elog.c
ramstage-y += dsp.c
ramstage-y += gpio.c
ramstage-y += graphics.c
diff --git a/src/soc/intel/apollolake/elog.c b/src/soc/intel/apollolake/elog.c
new file mode 100644
index 0000000000..0dd44c2e7d
--- /dev/null
+++ b/src/soc/intel/apollolake/elog.c
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Google Inc.
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <bootstate.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <elog.h>
+#include <soc/pm.h>
+#include <soc/pci_devs.h>
+#include <stdint.h>
+
+static void pch_log_gpio_gpe(u32 gpe0_sts, u32 gpe0_en, int start)
+{
+ int i;
+
+ gpe0_sts &= gpe0_en;
+
+ for (i = 0; i <= 31; i++) {
+ if (gpe0_sts & (1 << i))
+ elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i + start);
+ }
+}
+
+static void pch_log_wake_source(struct chipset_power_state *ps)
+{
+ /* Power Button */
+ if (ps->pm1_sts & PWRBTN_STS)
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
+
+ /* RTC */
+ if (ps->pm1_sts & RTC_STS)
+ elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
+
+ /* PCI Express (TODO: determine wake device) */
+ if (ps->pm1_sts & PCIEXPWAK_STS)
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
+
+ /* PME */
+ if(ps->gpe0_sts[GPE0_A] & CSE_PME_STS)
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0);
+
+ /* SMBUS Wake */
+ if (ps->gpe0_sts[GPE0_A] & SMB_WAK_STS)
+ elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0);
+
+ /* ACPI Wake Event - Always Log prev_sleep_state*/
+ elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, ps->prev_sleep_state);
+
+ /* Log GPIO events in set A-D */
+ pch_log_gpio_gpe(ps->gpe0_sts[GPE0_A], ps->gpe0_en[GPE0_A], 0);
+ pch_log_gpio_gpe(ps->gpe0_sts[GPE0_B], ps->gpe0_en[GPE0_B], 32);
+ pch_log_gpio_gpe(ps->gpe0_sts[GPE0_C], ps->gpe0_en[GPE0_C], 64);
+ pch_log_gpio_gpe(ps->gpe0_sts[GPE0_D], ps->gpe0_en[GPE0_D], 96);
+}
+
+static void pch_log_power_and_resets(struct chipset_power_state *ps)
+{
+ /* RTC Reset */
+ if (ps->gen_pmcon1 & RPS)
+ elog_add_event(ELOG_TYPE_RTC_RESET);
+
+ /* System Reset */
+ if (ps->gen_pmcon1 & SRS)
+ elog_add_event(ELOG_TYPE_SYSTEM_RESET);
+
+ /* TCO Timeout */
+ if (ps->prev_sleep_state != ACPI_S3 &&
+ ps->tco_sts & TCO_TIMEOUT)
+ elog_add_event(ELOG_TYPE_TCO_RESET);
+
+ /* Power Button Override */
+ if (ps->pm1_sts & PRBTNOR_STS)
+ elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
+
+}
+
+void pch_log_state(void)
+{
+ struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
+
+ if (ps == NULL) {
+ printk(BIOS_ERR,
+ "Not logging power state information. "
+ "Power state not found in cbmem.\n");
+ return;
+ }
+
+ /* Power and Reset */
+ pch_log_power_and_resets(ps);
+
+ /* Wake Sources */
+ if (ps->prev_sleep_state > ACPI_S0)
+ pch_log_wake_source(ps);
+}
diff --git a/src/soc/intel/apollolake/include/soc/pm.h b/src/soc/intel/apollolake/include/soc/pm.h
index 7eb593002e..b3da3aa628 100644
--- a/src/soc/intel/apollolake/include/soc/pm.h
+++ b/src/soc/intel/apollolake/include/soc/pm.h
@@ -25,16 +25,17 @@
#define PM1_STS 0x00
#define WAK_STS (1 << 15)
+#define PCIEXPWAK_STS (1 << 14)
+#define PRBTNOR_STS (1 << 11)
#define RTC_STS (1 << 10)
#define PWRBTN_STS (1 << 8)
+#define GBL_STS (1 << 5)
#define PM1_EN 0x02
#define PCIEXPWAK_DIS (1 << 14)
-#define USB_WAKE_EN (1 << 13)
#define RTC_EN (1 << 10)
#define PWRBTN_EN (1 << 8)
#define GBL_EN (1 << 5)
-#define TMROF_EN (1 << 0)
#define PM1_CNT 0x04
#define SCI_EN (1 << 0)
@@ -113,8 +114,30 @@
#define GPE0_REG_MAX 4
#define GPE0_REG_SIZE 32
#define GPE0_STS(x) (0x20 + (x * 4))
+#define GPE0_A 0
+#define GPE0_B 1
+#define GPE0_C 2
+#define GPE0_D 3
+#define SATA_PME_STS (1 << 17)
+#define SMB_WAK_STS (1 << 16)
+#define AVS_PME_STS (1 << 14)
+#define XHCI_PME_STS (1 << 13)
+#define XDCI_PME_STS (1 << 12)
+#define CSE_PME_STS (1 << 11)
+#define BATLOW_STS (1 << 10)
+#define PCIE_GPE_STS (1 << 9)
+#define SWGPE_STS (1 << 2)
#define GPE0_EN(x) (0x30 + (x * 4))
+#define SATA_PME_EN (1 << 17)
+#define SMB_WAK_EN (1 << 16)
+#define AVS_PME_EN (1 << 14)
#define PME_B0_EN (1 << 13)
+#define XDCI_PME_EN (1 << 12)
+#define CSE_PME_EN (1 << 11)
+#define BATLOW_EN (1 << 10)
+#define PCIE_GPE_EN (1 << 9)
+#define SWGPE_EN (1 << 2)
+
/*
* Enables the setting of the GPIO_TIER1_SCI_STS bit to generate a wake event
* and/or an SCI or SMI#.
@@ -124,10 +147,9 @@
/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
#define PRSTS 0x1000
#define GEN_PMCON1 0x1020
-# define PWR_FLR (1 << 16)
-# define SUS_PWR_FLR (1 << 14)
+#define SRS (1 << 20)
+#define RPS (1 << 2)
#define GEN_PMCON2 0x1024
-# define RPS (1 << 2)
#define GEN_PMCON3 0x1028
#define ETR 0x1048
# define CF9_LOCK (1 << 31)
@@ -188,4 +210,6 @@ uintptr_t get_pmc_mmio_bar(void);
void global_reset_enable(bool enable);
void global_reset_lock(void);
+void pch_log_state(void);
+
#endif
diff --git a/src/soc/intel/apollolake/pmc.c b/src/soc/intel/apollolake/pmc.c
index 92a150ddf4..30b7677a92 100644
--- a/src/soc/intel/apollolake/pmc.c
+++ b/src/soc/intel/apollolake/pmc.c
@@ -137,6 +137,9 @@ static void pmc_init(struct device *dev)
/* Set up GPE configuration */
pmc_gpe_init();
pch_set_acpi_mode();
+
+ /* Log power state */
+ pch_log_state();
}
static const struct device_operations device_ops = {