summaryrefslogtreecommitdiff
path: root/src/soc/intel/icelake/elog.c
diff options
context:
space:
mode:
authorSubrata Banik <subrata.banik@intel.com>2019-04-29 13:28:11 +0530
committerSubrata Banik <subrata.banik@intel.com>2019-05-02 06:02:52 +0000
commit5489341e6380cb8c7d1249a495486ae9cfcd4fa2 (patch)
treea33e36b2b46d4a0d6addf9503a607d1e3cafad59 /src/soc/intel/icelake/elog.c
parentff9104eae3512e554b4790b40b0bdd3fca2036b3 (diff)
soc/intel/icelake: Add chipset event logging
This patch ports CB:30718 and CB:31908 changes from CNL to ICL. Add logging of chipset events on boot into the flash event log. This was tested on a google/dragonegg board to ensure that events like "System Reset" are added to the log as expected. Also fix GEN_PMCON bit checks as below: ICL PCH has PWR_FLR, SUS_PWR_FLR and HOST_RST_STS bits in GEN_PMCON_A and so this change updates the check for these bits to use GEN_PMCON_A instead of GEN_PMCON_B. Change-Id: I25ec32e81f8801f8d5e69c6095ffed73d75dded6 Signed-off-by: Subrata Banik <subrata.banik@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/32504 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Furquan Shaikh <furquan@google.com> Reviewed-by: Rizwan Qureshi <rizwan.qureshi@intel.com>
Diffstat (limited to 'src/soc/intel/icelake/elog.c')
-rw-r--r--src/soc/intel/icelake/elog.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/soc/intel/icelake/elog.c b/src/soc/intel/icelake/elog.c
new file mode 100644
index 0000000000..2ec6b410df
--- /dev/null
+++ b/src/soc/intel/icelake/elog.c
@@ -0,0 +1,132 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Intel Corporation.
+ * Copyright 2019 Google LLC
+ *
+ * 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 <stdint.h>
+#include <elog.h>
+#include <intelblocks/pmclib.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.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 (TODO: determine wake device) */
+ if (ps->gpe0_sts[GPE_STD] & PME_STS)
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0);
+
+ /* Internal PME (TODO: determine wake device) */
+ if (ps->gpe0_sts[GPE_STD] & PME_B0_STS)
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
+
+ /* SMBUS Wake */
+ if (ps->gpe0_sts[GPE_STD] & SMB_WAK_STS)
+ elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0);
+
+ /* Log GPIO events in set 1-3 */
+ pch_log_gpio_gpe(ps->gpe0_sts[GPE_31_0], ps->gpe0_en[GPE_31_0], 0);
+ pch_log_gpio_gpe(ps->gpe0_sts[GPE_63_32], ps->gpe0_en[GPE_63_32], 32);
+ pch_log_gpio_gpe(ps->gpe0_sts[GPE_95_64], ps->gpe0_en[GPE_95_64], 64);
+ /* Treat the STD as an extension of GPIO to obtain visibility. */
+ pch_log_gpio_gpe(ps->gpe0_sts[GPE_STD], ps->gpe0_en[GPE_STD], 96);
+}
+
+static void pch_log_power_and_resets(struct chipset_power_state *ps)
+{
+ /* Thermal Trip */
+ if (ps->gblrst_cause[0] & GBLRST_CAUSE0_THERMTRIP)
+ elog_add_event(ELOG_TYPE_THERM_TRIP);
+
+ /* PWR_FLR Power Failure */
+ if (ps->gen_pmcon_a & PWR_FLR)
+ elog_add_event(ELOG_TYPE_POWER_FAIL);
+
+ /* SUS Well Power Failure */
+ if (ps->gen_pmcon_a & SUS_PWR_FLR)
+ elog_add_event(ELOG_TYPE_SUS_POWER_FAIL);
+
+ /* TCO Timeout */
+ if (ps->prev_sleep_state != ACPI_S3 &&
+ ps->tco2_sts & TCO_STS_SECOND_TO)
+ elog_add_event(ELOG_TYPE_TCO_RESET);
+
+ /* Power Button Override */
+ if (ps->pm1_sts & PRBTNOR_STS)
+ elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
+
+ /* RTC reset */
+ if (ps->gen_pmcon_b & RTC_BATTERY_DEAD)
+ elog_add_event(ELOG_TYPE_RTC_RESET);
+
+ /* Host Reset Status */
+ if (ps->gen_pmcon_a & HOST_RST_STS)
+ elog_add_event(ELOG_TYPE_SYSTEM_RESET);
+
+ /* ACPI Wake Event */
+ if (ps->prev_sleep_state != ACPI_S0)
+ elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, ps->prev_sleep_state);
+}
+
+static void pch_log_state(void *unused)
+{
+ struct chipset_power_state *ps = pmc_get_power_state();
+
+ if (!ps) {
+ printk(BIOS_ERR, "chipset_power_state not found!\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);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, pch_log_state, NULL);
+
+void elog_gsmi_cb_platform_log_wake_source(void)
+{
+ struct chipset_power_state ps;
+ pmc_fill_pm_reg_info(&ps);
+ pch_log_wake_source(&ps);
+}