summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/southbridge/intel/bd82x6x/Makefile.inc1
-rw-r--r--src/southbridge/intel/bd82x6x/elog.c114
-rw-r--r--src/southbridge/intel/bd82x6x/lpc.c4
-rw-r--r--src/southbridge/intel/bd82x6x/pch.h5
-rw-r--r--src/southbridge/intel/bd82x6x/smi.c5
5 files changed, 129 insertions, 0 deletions
diff --git a/src/southbridge/intel/bd82x6x/Makefile.inc b/src/southbridge/intel/bd82x6x/Makefile.inc
index 3de2bd0384..f9aade812c 100644
--- a/src/southbridge/intel/bd82x6x/Makefile.inc
+++ b/src/southbridge/intel/bd82x6x/Makefile.inc
@@ -32,6 +32,7 @@ ramstage-y += me_status.c
ramstage-y += reset.c
ramstage-y += watchdog.c
+ramstage-$(CONFIG_ELOG) += elog.c
ramstage-y += spi.c
smm-$(CONFIG_SPI_FLASH_SMM) += spi.c
diff --git a/src/southbridge/intel/bd82x6x/elog.c b/src/southbridge/intel/bd82x6x/elog.c
new file mode 100644
index 0000000000..09dfcdbc2c
--- /dev/null
+++ b/src/southbridge/intel/bd82x6x/elog.c
@@ -0,0 +1,114 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <arch/acpi.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <stdint.h>
+#include <string.h>
+#include <elog.h>
+#include "pch.h"
+
+void pch_log_state(void)
+{
+ u16 pm1_sts, gen_pmcon_3, tco2_sts;
+ u32 gpe0_sts, gpe0_en;
+ u8 gen_pmcon_2;
+ int i;
+ struct device *lpc = dev_find_slot(0, PCI_DEVFN(0x1f, 0));
+ if (!lpc)
+ return;
+
+ pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
+ gpe0_sts = inl(DEFAULT_PMBASE + GPE0_STS);
+ gpe0_en = inl(DEFAULT_PMBASE + GPE0_EN);
+ tco2_sts = inw(DEFAULT_PMBASE + TCO2_STS);
+ gen_pmcon_2 = pci_read_config8(lpc, GEN_PMCON_2);
+ gen_pmcon_3 = pci_read_config16(lpc, GEN_PMCON_3);
+
+ /* PWR_FLR Power Failure */
+ if (gen_pmcon_2 & (1 << 0))
+ elog_add_event(ELOG_TYPE_POWER_FAIL);
+
+ /* SUS Well Power Failure */
+ if (gen_pmcon_3 & (1 << 14))
+ elog_add_event(ELOG_TYPE_SUS_POWER_FAIL);
+
+ /* SYS_PWROK Failure */
+ if (gen_pmcon_2 & (1 << 1))
+ elog_add_event(ELOG_TYPE_SYS_PWROK_FAIL);
+
+ /* PWROK Failure */
+ if (gen_pmcon_2 & (1 << 0))
+ elog_add_event(ELOG_TYPE_PWROK_FAIL);
+
+ /* Second TCO Timeout */
+ if (tco2_sts & (1 << 1))
+ elog_add_event(ELOG_TYPE_TCO_RESET);
+
+ /* Power Button Override */
+ if (pm1_sts & (1 << 11))
+ elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
+
+ /* System Reset Status (reset button pushed) */
+ if (gen_pmcon_2 & (1 << 4))
+ elog_add_event(ELOG_TYPE_RESET_BUTTON);
+
+ /* General Reset Status */
+ if (gen_pmcon_3 & (1 << 9))
+ elog_add_event(ELOG_TYPE_SYSTEM_RESET);
+
+ /* ACPI Wake */
+ if (pm1_sts & (1 << 15))
+ elog_add_event_byte(ELOG_TYPE_ACPI_WAKE,
+ acpi_slp_type == 3 ? 3 : 5);
+
+ /*
+ * Wake sources
+ */
+
+ /* RTC */
+ if (pm1_sts & (1 << 10))
+ elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
+
+ /* PCI Express (TODO: determine wake device) */
+ if (pm1_sts & (1 << 14))
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
+
+ /* PME (TODO: determine wake device) */
+ if (gpe0_sts & (1 << 13))
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0);
+
+ /* Internal PME (TODO: determine wake device) */
+ if (gpe0_sts & (1 << 13))
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
+
+ /* GPIO 0-15 */
+ for (i = 0; i < 16; i++) {
+ if ((gpe0_sts & (1 << (16+i))) && (gpe0_en & (1 << (16+i))))
+ elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i);
+ }
+
+ /* SMBUS Wake */
+ if (gpe0_sts & (1 << 7))
+ elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0);
+}
diff --git a/src/southbridge/intel/bd82x6x/lpc.c b/src/southbridge/intel/bd82x6x/lpc.c
index 5f81edf394..ae71999238 100644
--- a/src/southbridge/intel/bd82x6x/lpc.c
+++ b/src/southbridge/intel/bd82x6x/lpc.c
@@ -29,6 +29,7 @@
#include <arch/ioapic.h>
#include <arch/acpi.h>
#include <cpu/cpu.h>
+#include <elog.h>
#include "pch.h"
#define NMI_OFF 0
@@ -296,6 +297,9 @@ static void pch_rtc_init(struct device *dev)
if (rtc_failed) {
reg8 &= ~RTC_BATTERY_DEAD;
pci_write_config8(dev, GEN_PMCON_3, reg8);
+#if CONFIG_ELOG
+ elog_add_event(ELOG_TYPE_RTC_RESET);
+#endif
}
printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
diff --git a/src/southbridge/intel/bd82x6x/pch.h b/src/southbridge/intel/bd82x6x/pch.h
index c9cc15edf9..0a16308f9b 100644
--- a/src/southbridge/intel/bd82x6x/pch.h
+++ b/src/southbridge/intel/bd82x6x/pch.h
@@ -65,6 +65,9 @@ int pch_silicon_type(void);
int pch_silicon_supported(int type, int rev);
void pch_enable(device_t dev);
void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue);
+#if CONFIG_ELOG
+void pch_log_state(void);
+#endif
#else
void enable_smbus(void);
void enable_usb_bar(void);
@@ -485,6 +488,8 @@ int smbus_read_byte(unsigned device, unsigned address);
#define DEVACT_STS 0x44
#define SS_CNT 0x50
#define C3_RES 0x54
+#define TCO1_STS 0x64
+#define TCO2_STS 0x66
/*
* SPI Opcode Menu setup for SPIBAR lockdown
diff --git a/src/southbridge/intel/bd82x6x/smi.c b/src/southbridge/intel/bd82x6x/smi.c
index da1084005f..bd4d32c135 100644
--- a/src/southbridge/intel/bd82x6x/smi.c
+++ b/src/southbridge/intel/bd82x6x/smi.c
@@ -370,6 +370,11 @@ static void smm_install(void)
void smm_init(void)
{
+#if CONFIG_ELOG
+ /* Log events from chipset before clearing */
+ pch_log_state();
+#endif
+
/* Put SMM code to 0xa0000 */
smm_install();