soc: Remove copyright notices
[coreboot.git] / src / soc / intel / cannonlake / elog.c
blob6c26e6a08ddc2c52e956be885fe980ad3dcbd351
1 /*
2 * This file is part of the coreboot project.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <bootstate.h>
16 #include <cbmem.h>
17 #include <console/console.h>
18 #include <device/pci_ops.h>
19 #include <stdint.h>
20 #include <elog.h>
21 #include <intelblocks/pmclib.h>
22 #include <intelblocks/xhci.h>
23 #include <soc/pci_devs.h>
24 #include <soc/pm.h>
26 struct pme_status_info {
27 #ifdef __SIMPLE_DEVICE__
28 pci_devfn_t dev;
29 #else
30 struct device *dev;
31 #endif
32 uint8_t reg_offset;
33 uint32_t elog_event;
36 #define PME_STS_BIT (1 << 15)
38 static void pch_log_add_elog_event(const struct pme_status_info *info)
41 * If wake source is XHCI, check for detailed wake source events on
42 * USB2/3 ports.
44 if ((info->dev == PCH_DEV_XHCI) &&
45 pch_xhci_update_wake_event(soc_get_xhci_usb_info()))
46 return;
48 elog_add_event_wake(info->elog_event, 0);
51 static void pch_log_pme_internal_wake_source(void)
53 size_t i;
54 #ifdef __SIMPLE_DEVICE__
55 pci_devfn_t dev;
56 #else
57 struct device *dev;
58 #endif
59 uint16_t val;
60 bool dev_found = false;
62 struct pme_status_info pme_status_info[] = {
63 { PCH_DEV_HDA, 0x54, ELOG_WAKE_SOURCE_PME_HDA },
64 { PCH_DEV_GBE, 0xcc, ELOG_WAKE_SOURCE_PME_GBE },
65 { PCH_DEV_SATA, 0x74, ELOG_WAKE_SOURCE_PME_SATA },
66 { PCH_DEV_CSE, 0x54, ELOG_WAKE_SOURCE_PME_CSE },
67 { PCH_DEV_XHCI, 0x74, ELOG_WAKE_SOURCE_PME_XHCI },
68 { PCH_DEV_USBOTG, 0x84, ELOG_WAKE_SOURCE_PME_XDCI },
70 * The power management control/status register is not
71 * listed in the cannonlake PCH EDS. We have been told
72 * that the PMCS register is at offset 0xCC.
74 { PCH_DEV_CNViWIFI, 0xcc, ELOG_WAKE_SOURCE_PME_WIFI },
77 for (i = 0; i < ARRAY_SIZE(pme_status_info); i++) {
78 dev = pme_status_info[i].dev;
79 if (!dev)
80 continue;
82 val = pci_read_config16(dev, pme_status_info[i].reg_offset);
84 if ((val == 0xFFFF) || !(val & PME_STS_BIT))
85 continue;
87 pch_log_add_elog_event(&pme_status_info[i]);
88 dev_found = true;
92 * If device is still not found, but the wake source is internal PME,
93 * try probing XHCI ports to see if any of the USB2/3 ports indicate
94 * that it was the wake source. This path would be taken in case of GSMI
95 * logging with S0ix where the pci_pm_resume_noirq runs and clears the
96 * PME_STS_BIT in controller register.
98 if (!dev_found)
99 dev_found = pch_xhci_update_wake_event(soc_get_xhci_usb_info());
101 if (!dev_found)
102 elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
105 static void pch_log_gpio_gpe(u32 gpe0_sts, u32 gpe0_en, int start)
107 int i;
109 gpe0_sts &= gpe0_en;
111 for (i = 0; i <= 31; i++) {
112 if (gpe0_sts & (1 << i))
113 elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i + start);
117 static void pch_log_wake_source(struct chipset_power_state *ps)
119 /* Power Button */
120 if (ps->pm1_sts & PWRBTN_STS)
121 elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
123 /* RTC */
124 if (ps->pm1_sts & RTC_STS)
125 elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
127 /* PCI Express (TODO: determine wake device) */
128 if (ps->pm1_sts & PCIEXPWAK_STS)
129 elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
131 /* PME (TODO: determine wake device) */
132 if (ps->gpe0_sts[GPE_STD] & PME_STS)
133 elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0);
135 /* XHCI - "Power Management Event Bus 0" events include XHCI */
136 if (ps->gpe0_sts[GPE_STD] & PME_B0_STS)
137 pch_log_pme_internal_wake_source();
139 /* SMBUS Wake */
140 if (ps->gpe0_sts[GPE_STD] & SMB_WAK_STS)
141 elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0);
143 /* Log GPIO events in set 1-3 */
144 pch_log_gpio_gpe(ps->gpe0_sts[GPE_31_0], ps->gpe0_en[GPE_31_0], 0);
145 pch_log_gpio_gpe(ps->gpe0_sts[GPE_63_32], ps->gpe0_en[GPE_63_32], 32);
146 pch_log_gpio_gpe(ps->gpe0_sts[GPE_95_64], ps->gpe0_en[GPE_95_64], 64);
147 /* Treat the STD as an extension of GPIO to obtain visibility. */
148 pch_log_gpio_gpe(ps->gpe0_sts[GPE_STD], ps->gpe0_en[GPE_STD], 96);
151 static void pch_log_power_and_resets(struct chipset_power_state *ps)
153 /* Thermal Trip */
154 if (ps->gblrst_cause[0] & GBLRST_CAUSE0_THERMTRIP)
155 elog_add_event(ELOG_TYPE_THERM_TRIP);
157 /* PWR_FLR Power Failure */
158 if (ps->gen_pmcon_a & PWR_FLR)
159 elog_add_event(ELOG_TYPE_POWER_FAIL);
161 /* SUS Well Power Failure */
162 if (ps->gen_pmcon_a & SUS_PWR_FLR)
163 elog_add_event(ELOG_TYPE_SUS_POWER_FAIL);
165 /* TCO Timeout */
166 if (ps->prev_sleep_state != ACPI_S3 &&
167 ps->tco2_sts & TCO_STS_SECOND_TO)
168 elog_add_event(ELOG_TYPE_TCO_RESET);
170 /* Power Button Override */
171 if (ps->pm1_sts & PRBTNOR_STS)
172 elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
174 /* RTC reset */
175 if (ps->gen_pmcon_b & RTC_BATTERY_DEAD)
176 elog_add_event(ELOG_TYPE_RTC_RESET);
178 /* Host Reset Status */
179 if (ps->gen_pmcon_a & HOST_RST_STS)
180 elog_add_event(ELOG_TYPE_SYSTEM_RESET);
182 /* ACPI Wake Event */
183 if (ps->prev_sleep_state != ACPI_S0)
184 elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, ps->prev_sleep_state);
187 static void pch_log_state(void *unused)
189 struct chipset_power_state *ps = pmc_get_power_state();
191 if (!ps) {
192 printk(BIOS_ERR, "chipset_power_state not found!\n");
193 return;
196 /* Power and Reset */
197 pch_log_power_and_resets(ps);
199 /* Wake Sources */
200 if (ps->prev_sleep_state > ACPI_S0)
201 pch_log_wake_source(ps);
204 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, pch_log_state, NULL);
206 void elog_gsmi_cb_platform_log_wake_source(void)
208 struct chipset_power_state ps;
209 pmc_fill_pm_reg_info(&ps);
210 pch_log_wake_source(&ps);