soc/intel/pantherlake: Remove soc_info.[hc] interface
[coreboot2.git] / src / soc / intel / skylake / elog.c
blob325bacb0f3639c339fd9f7fe250ed960171866bc
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <acpi/acpi_pm.h>
4 #include <bootstate.h>
5 #include <commonlib/helpers.h>
6 #include <device/mmio.h>
7 #include <device/pci_ops.h>
8 #include <stdint.h>
9 #include <elog.h>
10 #include <intelblocks/pmclib.h>
11 #include <intelblocks/xhci.h>
12 #include <soc/pci_devs.h>
13 #include <soc/pm.h>
14 #include <soc/smbus.h>
16 static void pch_log_gpio_gpe(u32 gpe0_sts, u32 gpe0_en, int start)
18 int i;
20 gpe0_sts &= gpe0_en;
22 for (i = 0; i <= 31; i++) {
23 if (gpe0_sts & (1 << i))
24 elog_add_event_wake(ELOG_WAKE_SOURCE_GPE, i + start);
28 struct pme_status_info {
29 unsigned int devfn;
30 uint8_t reg_offset;
31 uint32_t elog_event;
34 #define PME_STS_BIT (1 << 15)
36 static void pch_log_pme_internal_wake_source(void)
38 size_t i;
39 uint16_t val;
40 bool dev_found = false;
42 const struct pme_status_info pme_status_info[] = {
43 { PCH_DEVFN_HDA, 0x54, ELOG_WAKE_SOURCE_PME_HDA },
44 { PCH_DEVFN_GBE, 0xcc, ELOG_WAKE_SOURCE_PME_GBE },
45 { PCH_DEVFN_SATA, 0x74, ELOG_WAKE_SOURCE_PME_SATA },
46 { PCH_DEVFN_CSE, 0x54, ELOG_WAKE_SOURCE_PME_CSE },
47 { PCH_DEVFN_USBOTG, 0x84, ELOG_WAKE_SOURCE_PME_XDCI },
49 const struct xhci_wake_info xhci_wake_info[] = {
50 { PCH_DEVFN_XHCI, ELOG_WAKE_SOURCE_PME_XHCI },
53 for (i = 0; i < ARRAY_SIZE(pme_status_info); i++) {
54 pci_devfn_t dev = PCI_DEV(0, PCI_SLOT(pme_status_info[i].devfn),
55 PCI_FUNC(pme_status_info[i].devfn));
57 val = pci_s_read_config16(dev, pme_status_info[i].reg_offset);
59 if ((val == 0xFFFF) || !(val & PME_STS_BIT))
60 continue;
62 elog_add_event_wake(pme_status_info[i].elog_event, 0);
63 dev_found = true;
67 * Check the XHCI controllers' USB2 & USB3 ports for wake events. There
68 * are cases (GSMI logging for S0ix clears PME_STS_BIT) where the XHCI
69 * controller's PME_STS_BIT may have already been cleared, so the host
70 * controller wake wouldn't get logged here; therefore, the host
71 * controller wake event is logged before its corresponding port wake
72 * event is logged.
74 dev_found |= xhci_update_wake_event(xhci_wake_info,
75 ARRAY_SIZE(xhci_wake_info));
77 if (!dev_found)
78 elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
81 #define RP_PME_STS_BIT (1 << 16)
82 static void pch_log_rp_wake_source(void)
84 size_t i, maxports;
85 uint32_t val;
87 struct pme_status_info pme_status_info[] = {
88 { PCH_DEVFN_PCIE1, 0x60, ELOG_WAKE_SOURCE_PME_PCIE1 },
89 { PCH_DEVFN_PCIE2, 0x60, ELOG_WAKE_SOURCE_PME_PCIE2 },
90 { PCH_DEVFN_PCIE3, 0x60, ELOG_WAKE_SOURCE_PME_PCIE3 },
91 { PCH_DEVFN_PCIE4, 0x60, ELOG_WAKE_SOURCE_PME_PCIE4 },
92 { PCH_DEVFN_PCIE5, 0x60, ELOG_WAKE_SOURCE_PME_PCIE5 },
93 { PCH_DEVFN_PCIE6, 0x60, ELOG_WAKE_SOURCE_PME_PCIE6 },
94 { PCH_DEVFN_PCIE7, 0x60, ELOG_WAKE_SOURCE_PME_PCIE7 },
95 { PCH_DEVFN_PCIE8, 0x60, ELOG_WAKE_SOURCE_PME_PCIE8 },
96 { PCH_DEVFN_PCIE9, 0x60, ELOG_WAKE_SOURCE_PME_PCIE9 },
97 { PCH_DEVFN_PCIE10, 0x60, ELOG_WAKE_SOURCE_PME_PCIE10 },
98 { PCH_DEVFN_PCIE11, 0x60, ELOG_WAKE_SOURCE_PME_PCIE11 },
99 { PCH_DEVFN_PCIE12, 0x60, ELOG_WAKE_SOURCE_PME_PCIE12 },
100 { PCH_DEVFN_PCIE13, 0x60, ELOG_WAKE_SOURCE_PME_PCIE13 },
101 { PCH_DEVFN_PCIE14, 0x60, ELOG_WAKE_SOURCE_PME_PCIE14 },
102 { PCH_DEVFN_PCIE15, 0x60, ELOG_WAKE_SOURCE_PME_PCIE15 },
103 { PCH_DEVFN_PCIE16, 0x60, ELOG_WAKE_SOURCE_PME_PCIE16 },
104 { PCH_DEVFN_PCIE17, 0x60, ELOG_WAKE_SOURCE_PME_PCIE17 },
105 { PCH_DEVFN_PCIE18, 0x60, ELOG_WAKE_SOURCE_PME_PCIE18 },
106 { PCH_DEVFN_PCIE19, 0x60, ELOG_WAKE_SOURCE_PME_PCIE19 },
107 { PCH_DEVFN_PCIE20, 0x60, ELOG_WAKE_SOURCE_PME_PCIE20 },
108 { PCH_DEVFN_PCIE21, 0x60, ELOG_WAKE_SOURCE_PME_PCIE21 },
109 { PCH_DEVFN_PCIE22, 0x60, ELOG_WAKE_SOURCE_PME_PCIE22 },
110 { PCH_DEVFN_PCIE23, 0x60, ELOG_WAKE_SOURCE_PME_PCIE23 },
111 { PCH_DEVFN_PCIE24, 0x60, ELOG_WAKE_SOURCE_PME_PCIE24 },
114 maxports = MIN(CONFIG_MAX_ROOT_PORTS, ARRAY_SIZE(pme_status_info));
116 for (i = 0; i < maxports; i++) {
117 pci_devfn_t dev = PCI_DEV(0, PCI_SLOT(pme_status_info[i].devfn),
118 PCI_FUNC(pme_status_info[i].devfn));
120 val = pci_s_read_config32(dev, pme_status_info[i].reg_offset);
122 if ((val == 0xFFFFFFFF) || !(val & RP_PME_STS_BIT))
123 continue;
126 * Linux kernel uses PME STS bit information. So do not clear
127 * this bit.
129 elog_add_event_wake(pme_status_info[i].elog_event, 0);
133 static void pch_log_wake_source(const struct chipset_power_state *ps)
135 /* Power Button */
136 if (ps->pm1_sts & PWRBTN_STS)
137 elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
139 /* RTC */
140 if (ps->pm1_sts & RTC_STS)
141 elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
143 /* PCI Express (TODO: determine wake device) */
144 if (ps->pm1_sts & PCIEXPWAK_STS)
145 elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
148 * PCIE Root Port .
149 * This should be done when PCIEXPWAK_STS bit is set.
150 * In SPT, this bit isn't getting set due to known bug.
151 * So scan all PCIe RP for PME status bit.
153 pch_log_rp_wake_source();
155 /* PME (TODO: determine wake device) */
156 if (ps->gpe0_sts[GPE_STD] & PME_STS)
157 elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0);
159 /* Internal PME (TODO: determine wake device) */
160 if (ps->gpe0_sts[GPE_STD] & PME_B0_STS)
161 pch_log_pme_internal_wake_source();
163 /* SMBUS Wake */
164 if (ps->gpe0_sts[GPE_STD] & SMB_WAK_STS)
165 elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0);
167 /* Log GPIO events in set 1-3 */
168 pch_log_gpio_gpe(ps->gpe0_sts[GPE_31_0], ps->gpe0_en[GPE_31_0], 0);
169 pch_log_gpio_gpe(ps->gpe0_sts[GPE_63_32], ps->gpe0_en[GPE_63_32], 32);
170 pch_log_gpio_gpe(ps->gpe0_sts[GPE_95_64], ps->gpe0_en[GPE_95_64], 64);
171 /* Treat the STD as an extension of GPIO to obtain visibility. */
172 pch_log_gpio_gpe(ps->gpe0_sts[GPE_STD], ps->gpe0_en[GPE_STD], 96);
175 static void pch_log_power_and_resets(const struct chipset_power_state *ps)
177 bool deep_sx;
180 * Platform entered deep Sx if:
181 * 1. Prev sleep state was Sx and deep_sx_enabled() is true
182 * 2. SUS well power was lost
184 deep_sx = ((((ps->prev_sleep_state == ACPI_S3) && deep_s3_enabled()) ||
185 ((ps->prev_sleep_state == ACPI_S5) && deep_s5_enabled())) &&
186 (ps->gen_pmcon_b & SUS_PWR_FLR));
188 /* Thermal Trip */
189 if (ps->gblrst_cause[0] & GBLRST_CAUSE0_THERMTRIP)
190 elog_add_event(ELOG_TYPE_THERM_TRIP);
192 /* PWR_FLR Power Failure */
193 if (ps->gen_pmcon_b & PWR_FLR)
194 elog_add_event(ELOG_TYPE_POWER_FAIL);
196 /* SUS Well Power Failure */
197 if (ps->gen_pmcon_b & SUS_PWR_FLR) {
198 /* Do not log SUS_PWR_FLR if waking from deep Sx */
199 if (!deep_sx)
200 elog_add_event(ELOG_TYPE_SUS_POWER_FAIL);
203 /* TCO Timeout */
204 if (ps->prev_sleep_state != ACPI_S3 &&
205 ps->tco2_sts & TCO2_STS_SECOND_TO)
206 elog_add_event(ELOG_TYPE_TCO_RESET);
208 /* Power Button Override */
209 if (ps->pm1_sts & PRBTNOR_STS)
210 elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
212 /* RTC reset */
213 if (ps->gen_pmcon_b & RTC_BATTERY_DEAD)
214 elog_add_event(ELOG_TYPE_RTC_RESET);
216 /* Host Reset Status */
217 if (ps->gen_pmcon_b & HOST_RST_STS)
218 elog_add_event(ELOG_TYPE_SYSTEM_RESET);
220 /* ACPI Wake Event */
221 if (ps->prev_sleep_state != ACPI_S0) {
222 if (deep_sx)
223 elog_add_event_byte(ELOG_TYPE_ACPI_DEEP_WAKE,
224 ps->prev_sleep_state);
225 else
226 elog_add_event_byte(ELOG_TYPE_ACPI_WAKE,
227 ps->prev_sleep_state);
231 static void pch_log_state(void *unused)
233 const struct chipset_power_state *ps;
235 if (acpi_fetch_pm_state(&ps, PS_CLAIMER_ELOG) < 0)
236 return;
238 /* Power and Reset */
239 pch_log_power_and_resets(ps);
241 /* Wake Sources */
242 if (ps->prev_sleep_state > 0)
243 pch_log_wake_source(ps);
246 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, pch_log_state, NULL);
248 void elog_gsmi_cb_platform_log_wake_source(void)
250 struct chipset_power_state ps;
251 pmc_fill_pm_reg_info(&ps);
252 pch_log_wake_source(&ps);