blob: aef820ef22ac19a4c37f39a2aea6a3737942e7d6 [file] [log] [blame]
Aaron Durbin8f31ecf2014-01-09 10:41:30 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Aaron Durbin8f31ecf2014-01-09 10:41:30 -060015 */
16
17#include <arch/io.h>
18#include <arch/acpi.h>
19#include <stdint.h>
20#include <console/console.h>
21#include <cbmem.h>
22#include <device/device.h>
23#include <device/pci.h>
24#include <device/pci_ops.h>
25#include <elog.h>
Julius Werner18ea2d32014-10-07 16:42:17 -070026#include <soc/iomap.h>
27#include <soc/pmc.h>
Aaron Durbin8f31ecf2014-01-09 10:41:30 -060028
29static void log_power_and_resets(const struct chipset_power_state *ps)
30{
31 if (ps->gen_pmcon1 & PWR_FLR) {
32 elog_add_event(ELOG_TYPE_POWER_FAIL);
33 elog_add_event(ELOG_TYPE_PWROK_FAIL);
34 }
35
36 if (ps->gen_pmcon1 & SUS_PWR_FLR) {
37 elog_add_event(ELOG_TYPE_SUS_POWER_FAIL);
38 }
39
Shawn Nematbakhsh51d787a2014-01-16 17:52:21 -080040 if (ps->gen_pmcon1 & RPS) {
41 elog_add_event(ELOG_TYPE_RTC_RESET);
42 }
43
Aaron Durbin8f31ecf2014-01-09 10:41:30 -060044 if (ps->tco_sts & SECOND_TO_STS) {
45 elog_add_event(ELOG_TYPE_TCO_RESET);
46 }
47
48 if (ps->pm1_sts & PRBTNOR_STS) {
49 elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
50 }
51
52 if (ps->gen_pmcon1 & SRS) {
53 elog_add_event(ELOG_TYPE_RESET_BUTTON);
54 }
55
56 if (ps->gen_pmcon1 & GEN_RST_STS) {
57 elog_add_event(ELOG_TYPE_SYSTEM_RESET);
58 }
59}
60
61static void log_wake_events(const struct chipset_power_state *ps)
62{
63 const uint32_t pcie_wake_mask = PCI_EXP_STS | PCIE_WAKE3_STS |
64 PCIE_WAKE2_STS | PCIE_WAKE1_STS |
65 PCIE_WAKE0_STS;
66 uint32_t gpe0_sts;
67 uint32_t gpio_mask;
68 int i;
69
70 /* Mask off disabled events. */
71 gpe0_sts = ps->gpe0_sts & ps->gpe0_en;
72
73 if (ps->pm1_sts & WAK_STS) {
74 elog_add_event_byte(ELOG_TYPE_ACPI_WAKE,
Kyösti Mälkkic3ed8862014-06-19 19:50:51 +030075 acpi_is_wakeup_s3() ? 3 : 5);
Aaron Durbin8f31ecf2014-01-09 10:41:30 -060076 }
77
78 if (ps->pm1_sts & PWRBTN_STS) {
79 elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
80 }
81
82 if (ps->pm1_sts & RTC_STS) {
83 elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
84 }
85
86 if (gpe0_sts & PME_B0_EN) {
87 elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
88 }
89
90 if (gpe0_sts & pcie_wake_mask) {
91 elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
92 }
93
94 gpio_mask = SUS_GPIO_STS0;
95 i = 0;
96 while (gpio_mask) {
97 if (gpio_mask & gpe0_sts) {
98 elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i);
99 }
100 gpio_mask <<= 1;
101 i++;
102 }
103}
104
105void southcluster_log_state(void)
106{
107 struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
108
109 if (ps == NULL) {
110 printk(BIOS_DEBUG, "Not logging power state information. "
111 "Power state not found in cbmem.\n");
112 return;
113 }
114
115 log_power_and_resets(ps);
116 log_wake_events(ps);
117}