blob: 322e96f4a04e16d2e4aaac85c27acb210cc58f5e [file] [log] [blame]
Duncan Lauriec88c54c2014-04-30 16:36:13 -07001/*
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 modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Duncan Lauriec88c54c2014-04-30 16:36:13 -070014 */
15
16/*
17 * Helper functions for dealing with power management registers
18 * and the differences between PCH variants.
19 */
20
Joel Kitching1d93b882018-09-26 17:58:14 +080021#include <arch/acpi.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070022#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020023#include <device/pci_ops.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070024#include <device/device.h>
25#include <device/pci.h>
26#include <device/pci_def.h>
27#include <console/console.h>
Julius Werner4ee4bd52014-10-20 13:46:39 -070028#include <soc/iomap.h>
29#include <soc/lpc.h>
30#include <soc/pci_devs.h>
31#include <soc/pm.h>
32#include <soc/gpio.h>
Philipp Deppenwiesefea24292017-10-17 17:02:29 +020033#include <security/vboot/vbnv.h>
Joel Kitching1d93b882018-09-26 17:58:14 +080034#include <security/vboot/vboot_common.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070035
36/* Print status bits with descriptive names */
37static void print_status_bits(u32 status, const char *bit_names[])
38{
39 int i;
40
41 if (!status)
42 return;
43
Lee Leahy26b7cd02017-03-16 18:47:55 -070044 for (i = 31; i >= 0; i--) {
Duncan Lauriec88c54c2014-04-30 16:36:13 -070045 if (status & (1 << i)) {
46 if (bit_names[i])
47 printk(BIOS_DEBUG, "%s ", bit_names[i]);
48 else
49 printk(BIOS_DEBUG, "BIT%d ", i);
50 }
51 }
52}
53
54/* Print status bits as GPIO numbers */
55static void print_gpio_status(u32 status, int start)
56{
57 int i;
58
59 if (!status)
60 return;
61
Lee Leahy26b7cd02017-03-16 18:47:55 -070062 for (i = 31; i >= 0; i--) {
Duncan Lauriec88c54c2014-04-30 16:36:13 -070063 if (status & (1 << i))
64 printk(BIOS_DEBUG, "GPIO%d ", start + i);
65 }
66}
67
68
69/*
70 * PM1_CNT
71 */
72
73/* Enable events in PM1 control register */
74void enable_pm1_control(u32 mask)
75{
76 u32 pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
77 pm1_cnt |= mask;
78 outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT);
79}
80
81/* Disable events in PM1 control register */
82void disable_pm1_control(u32 mask)
83{
84 u32 pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
85 pm1_cnt &= ~mask;
86 outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT);
87}
88
89
90/*
91 * PM1
92 */
93
94/* Clear and return PM1 status register */
95static u16 reset_pm1_status(void)
96{
97 u16 pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
98 outw(pm1_sts, ACPI_BASE_ADDRESS + PM1_STS);
99 return pm1_sts;
100}
101
102/* Print PM1 status bits */
103static u16 print_pm1_status(u16 pm1_sts)
104{
105 const char *pm1_sts_bits[] = {
106 [0] = "TMROF",
107 [4] = "BM",
108 [5] = "GBL",
109 [8] = "PWRBTN",
110 [10] = "RTC",
111 [11] = "PRBTNOR",
112 [14] = "PCIEXPWAK",
113 [15] = "WAK",
114 };
115
116 if (!pm1_sts)
117 return 0;
118
119 printk(BIOS_SPEW, "PM1_STS: ");
120 print_status_bits(pm1_sts, pm1_sts_bits);
121 printk(BIOS_SPEW, "\n");
122
123 return pm1_sts;
124}
125
126/* Print, clear, and return PM1 status */
127u16 clear_pm1_status(void)
128{
129 return print_pm1_status(reset_pm1_status());
130}
131
132/* Set the PM1 register to events */
133void enable_pm1(u16 events)
134{
135 outw(events, ACPI_BASE_ADDRESS + PM1_EN);
136}
137
138
139/*
140 * SMI
141 */
142
143/* Clear and return SMI status register */
144static u32 reset_smi_status(void)
145{
146 u32 smi_sts = inl(ACPI_BASE_ADDRESS + SMI_STS);
147 outl(smi_sts, ACPI_BASE_ADDRESS + SMI_STS);
148 return smi_sts;
149}
150
151/* Print SMI status bits */
152static u32 print_smi_status(u32 smi_sts)
153{
154 const char *smi_sts_bits[] = {
155 [2] = "BIOS",
156 [3] = "LEGACY_USB",
157 [4] = "SLP_SMI",
158 [5] = "APM",
159 [6] = "SWSMI_TMR",
160 [8] = "PM1",
161 [9] = "GPE0",
162 [10] = "GPI",
163 [11] = "MCSMI",
164 [12] = "DEVMON",
165 [13] = "TCO",
166 [14] = "PERIODIC",
167 [15] = "SERIRQ_SMI",
168 [16] = "SMBUS_SMI",
169 [17] = "LEGACY_USB2",
170 [18] = "INTEL_USB2",
171 [20] = "PCI_EXP_SMI",
172 [21] = "MONITOR",
173 [26] = "SPI",
174 [27] = "GPIO_UNLOCK"
175 };
176
177 if (!smi_sts)
178 return 0;
179
180 printk(BIOS_DEBUG, "SMI_STS: ");
181 print_status_bits(smi_sts, smi_sts_bits);
182 printk(BIOS_DEBUG, "\n");
183
184 return smi_sts;
185}
186
187/* Print, clear, and return SMI status */
188u32 clear_smi_status(void)
189{
190 return print_smi_status(reset_smi_status());
191}
192
193/* Enable SMI event */
194void enable_smi(u32 mask)
195{
196 u32 smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN);
197 smi_en |= mask;
198 outl(smi_en, ACPI_BASE_ADDRESS + SMI_EN);
199}
200
201/* Disable SMI event */
202void disable_smi(u32 mask)
203{
204 u32 smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN);
205 smi_en &= ~mask;
206 outl(smi_en, ACPI_BASE_ADDRESS + SMI_EN);
207}
208
209
210/*
211 * ALT_GP_SMI
212 */
213
214/* Clear GPIO SMI status and return events that are enabled and active */
215static u32 reset_alt_smi_status(void)
216{
217 u32 alt_sts, alt_en;
218
219 /* Low Power variant moves this to GPIO region as dword */
220 alt_sts = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_STS);
221 outl(alt_sts, GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_STS);
222 alt_en = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN);
223
224 /* Only report enabled events */
225 return alt_sts & alt_en;
226}
227
228/* Print GPIO SMI status bits */
229static u32 print_alt_smi_status(u32 alt_sts)
230{
231 if (!alt_sts)
232 return 0;
233
234 printk(BIOS_DEBUG, "ALT_STS: ");
235
236 /* First 16 events are GPIO 32-47 */
237 print_gpio_status(alt_sts & 0xffff, 32);
238
239 printk(BIOS_DEBUG, "\n");
240
241 return alt_sts;
242}
243
244/* Print, clear, and return GPIO SMI status */
245u32 clear_alt_smi_status(void)
246{
247 return print_alt_smi_status(reset_alt_smi_status());
248}
249
250/* Enable GPIO SMI events */
251void enable_alt_smi(u32 mask)
252{
253 u32 alt_en;
254
255 alt_en = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN);
256 alt_en |= mask;
257 outl(alt_en, GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN);
258}
259
260
261/*
262 * TCO
263 */
264
265/* Clear TCO status and return events that are enabled and active */
266static u32 reset_tco_status(void)
267{
268 u32 tcobase = ACPI_BASE_ADDRESS + 0x60;
269 u32 tco_sts = inl(tcobase + 0x04);
270 u32 tco_en = inl(ACPI_BASE_ADDRESS + 0x68);
271
272 /* Don't clear BOOT_STS before SECOND_TO_STS */
273 outl(tco_sts & ~(1 << 18), tcobase + 0x04);
274
275 /* Clear BOOT_STS */
276 if (tco_sts & (1 << 18))
277 outl(tco_sts & (1 << 18), tcobase + 0x04);
278
279 return tco_sts & tco_en;
280}
281
282/* Print TCO status bits */
283static u32 print_tco_status(u32 tco_sts)
284{
285 const char *tco_sts_bits[] = {
286 [0] = "NMI2SMI",
287 [1] = "SW_TCO",
288 [2] = "TCO_INT",
289 [3] = "TIMEOUT",
290 [7] = "NEWCENTURY",
291 [8] = "BIOSWR",
292 [9] = "DMISCI",
293 [10] = "DMISMI",
294 [12] = "DMISERR",
295 [13] = "SLVSEL",
296 [16] = "INTRD_DET",
297 [17] = "SECOND_TO",
298 [18] = "BOOT",
299 [20] = "SMLINK_SLV"
300 };
301
302 if (!tco_sts)
303 return 0;
304
305 printk(BIOS_DEBUG, "TCO_STS: ");
306 print_status_bits(tco_sts, tco_sts_bits);
307 printk(BIOS_DEBUG, "\n");
308
309 return tco_sts;
310}
311
312/* Print, clear, and return TCO status */
313u32 clear_tco_status(void)
314{
315 return print_tco_status(reset_tco_status());
316}
317
318/* Enable TCO SCI */
319void enable_tco_sci(void)
320{
321 /* Clear pending events */
322 outl(ACPI_BASE_ADDRESS + GPE0_STS(3), TCOSCI_STS);
323
324 /* Enable TCO SCI events */
325 enable_gpe(TCOSCI_EN);
326}
327
328
329/*
330 * GPE0
331 */
332
333/* Clear a GPE0 status and return events that are enabled and active */
334static u32 reset_gpe(u16 sts_reg, u16 en_reg)
335{
336 u32 gpe0_sts = inl(ACPI_BASE_ADDRESS + sts_reg);
337 u32 gpe0_en = inl(ACPI_BASE_ADDRESS + en_reg);
338
339 outl(gpe0_sts, ACPI_BASE_ADDRESS + sts_reg);
340
341 /* Only report enabled events */
342 return gpe0_sts & gpe0_en;
343}
344
345/* Print GPE0 status bits */
346static u32 print_gpe_status(u32 gpe0_sts, const char *bit_names[])
347{
348 if (!gpe0_sts)
349 return 0;
350
351 printk(BIOS_DEBUG, "GPE0_STS: ");
352 print_status_bits(gpe0_sts, bit_names);
353 printk(BIOS_DEBUG, "\n");
354
355 return gpe0_sts;
356}
357
358/* Print GPE0 GPIO status bits */
359static u32 print_gpe_gpio(u32 gpe0_sts, int start)
360{
361 if (!gpe0_sts)
362 return 0;
363
364 printk(BIOS_DEBUG, "GPE0_STS: ");
365 print_gpio_status(gpe0_sts, start);
366 printk(BIOS_DEBUG, "\n");
367
368 return gpe0_sts;
369}
370
371/* Clear all GPE status and return "standard" GPE event status */
372u32 clear_gpe_status(void)
373{
374 const char *gpe0_sts_3_bits[] = {
375 [1] = "HOTPLUG",
376 [2] = "SWGPE",
377 [6] = "TCO_SCI",
378 [7] = "SMB_WAK",
379 [9] = "PCI_EXP",
380 [10] = "BATLOW",
381 [11] = "PME",
382 [12] = "ME",
383 [13] = "PME_B0",
384 [16] = "GPIO27",
385 [18] = "WADT"
386 };
387
388 print_gpe_gpio(reset_gpe(GPE0_STS(GPE_31_0), GPE0_EN(GPE_31_0)), 0);
389 print_gpe_gpio(reset_gpe(GPE0_STS(GPE_63_32), GPE0_EN(GPE_63_32)), 32);
390 print_gpe_gpio(reset_gpe(GPE0_STS(GPE_94_64), GPE0_EN(GPE_94_64)), 64);
391 return print_gpe_status(reset_gpe(GPE0_STS(GPE_STD), GPE0_EN(GPE_STD)),
392 gpe0_sts_3_bits);
393}
394
395/* Enable all requested GPE */
396void enable_all_gpe(u32 set1, u32 set2, u32 set3, u32 set4)
397{
398 outl(set1, ACPI_BASE_ADDRESS + GPE0_EN(GPE_31_0));
399 outl(set2, ACPI_BASE_ADDRESS + GPE0_EN(GPE_63_32));
400 outl(set3, ACPI_BASE_ADDRESS + GPE0_EN(GPE_94_64));
401 outl(set4, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
402}
403
404/* Disable all GPE */
405void disable_all_gpe(void)
406{
407 enable_all_gpe(0, 0, 0, 0);
408}
409
410/* Enable a standard GPE */
411void enable_gpe(u32 mask)
412{
413 u32 gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
414 gpe0_en |= mask;
415 outl(gpe0_en, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
416}
417
418/* Disable a standard GPE */
419void disable_gpe(u32 mask)
420{
421 u32 gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
422 gpe0_en &= ~mask;
423 outl(gpe0_en, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD));
424}
425
426int acpi_sci_irq(void)
427{
428 int scis = pci_read_config32(PCH_DEV_LPC, ACPI_CNTL) & SCI_IRQ_SEL;
429 int sci_irq = 9;
430
431 /* Determine how SCI is routed. */
432 switch (scis) {
433 case SCIS_IRQ9:
434 case SCIS_IRQ10:
435 case SCIS_IRQ11:
436 sci_irq = scis - SCIS_IRQ9 + 9;
437 break;
438 case SCIS_IRQ20:
439 case SCIS_IRQ21:
440 case SCIS_IRQ22:
441 case SCIS_IRQ23:
442 sci_irq = scis - SCIS_IRQ20 + 20;
443 break;
444 default:
445 printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n");
446 sci_irq = 9;
447 break;
448 }
449
450 printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq);
451 return sci_irq;
452}
Aaron Durbinb9d9b792017-09-15 11:51:58 -0600453
454int rtc_failure(void)
455{
456 u8 reg8;
457 int rtc_failed;
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200458#if defined(__SIMPLE_DEVICE__)
459 pci_devfn_t dev = PCH_DEV_LPC;
460#else
461 struct device *dev = PCH_DEV_LPC;
462#endif
Aaron Durbinb9d9b792017-09-15 11:51:58 -0600463
464 reg8 = pci_read_config8(dev, GEN_PMCON_3);
465 rtc_failed = reg8 & RTC_BATTERY_DEAD;
466 if (rtc_failed) {
467 reg8 &= ~RTC_BATTERY_DEAD;
468 pci_write_config8(dev, GEN_PMCON_3, reg8);
469 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
470 }
471
472 return !!rtc_failed;
473}
Aaron Durbin0990fbf2017-09-15 15:23:04 -0600474
475int vbnv_cmos_failed(void)
476{
477 return rtc_failure();
478}
Joel Kitching1d93b882018-09-26 17:58:14 +0800479
480int vboot_platform_is_resuming(void)
481{
482 if (!(inw(ACPI_BASE_ADDRESS + PM1_STS) & WAK_STS))
483 return 0;
484
485 return acpi_sleep_from_pm1(inl(ACPI_BASE_ADDRESS + PM1_CNT)) == ACPI_S3;
486}