blob: cc494771dd6a6a4abc62292b599ae24ca5bbc410 [file] [log] [blame]
Duncan Laurie55cdf552013-03-08 16:01:44 -08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2013 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.
Duncan Laurie55cdf552013-03-08 16:01:44 -080015 */
16
17/*
18 * Helper functions for dealing with power management registers
19 * and the differences between LynxPoint-H and LynxPoint-LP.
20 */
21
22#include <arch/io.h>
Duncan Laurie55cdf552013-03-08 16:01:44 -080023#include <device/device.h>
24#include <device/pci.h>
Stefan Reinauer5605f1b2013-03-21 18:43:51 -070025#include <device/pci_def.h>
Duncan Laurie55cdf552013-03-08 16:01:44 -080026#include <console/console.h>
Arthur Heymans77d5e742019-01-03 21:11:45 +010027#include <security/vboot/vbnv.h>
28#include <security/vboot/vboot_common.h>
29#include <southbridge/intel/common/rtc.h>
Duncan Laurie55cdf552013-03-08 16:01:44 -080030#include "pch.h"
31
Julius Wernercd49cce2019-03-05 16:53:33 -080032#if CONFIG(INTEL_LYNXPOINT_LP)
Duncan Laurie55cdf552013-03-08 16:01:44 -080033#include "lp_gpio.h"
34#endif
35
36/* These defines are here to handle the LP variant code dynamically. If these
37 * values are defined in lp_gpio.h but when a non-LP board is being built, the
38 * build will fail. */
39#define GPIO_ALT_GPI_SMI_STS 0x50
40#define GPIO_ALT_GPI_SMI_EN 0x54
41
42/* Print status bits with descriptive names */
43static void print_status_bits(u32 status, const char *bit_names[])
44{
45 int i;
46
47 if (!status)
48 return;
49
50 for (i=31; i>=0; i--) {
Ryan Salsamendi0d9b3602017-06-30 17:15:57 -070051 if (status & (1UL << i)) {
Duncan Laurie55cdf552013-03-08 16:01:44 -080052 if (bit_names[i])
53 printk(BIOS_DEBUG, "%s ", bit_names[i]);
54 else
55 printk(BIOS_DEBUG, "BIT%d ", i);
56 }
57 }
58}
59
60/* Print status bits as GPIO numbers */
61static void print_gpio_status(u32 status, int start)
62{
63 int i;
64
65 if (!status)
66 return;
67
68 for (i=31; i>=0; i--) {
69 if (status & (1 << i))
70 printk(BIOS_DEBUG, "GPIO%d ", start + i);
71 }
72}
73
74
75/*
76 * PM1_CNT
77 */
78
79/* Enable events in PM1 control register */
80void enable_pm1_control(u32 mask)
81{
82 u32 pm1_cnt = inl(get_pmbase() + PM1_CNT);
83 pm1_cnt |= mask;
84 outl(pm1_cnt, get_pmbase() + PM1_CNT);
85}
86
87/* Disable events in PM1 control register */
88void disable_pm1_control(u32 mask)
89{
90 u32 pm1_cnt = inl(get_pmbase() + PM1_CNT);
91 pm1_cnt &= ~mask;
92 outl(pm1_cnt, get_pmbase() + PM1_CNT);
93}
94
95
96/*
97 * PM1
98 */
99
100/* Clear and return PM1 status register */
101static u16 reset_pm1_status(void)
102{
103 u16 pm1_sts = inw(get_pmbase() + PM1_STS);
104 outw(pm1_sts, get_pmbase() + PM1_STS);
105 return pm1_sts;
106}
107
108/* Print PM1 status bits */
109static u16 print_pm1_status(u16 pm1_sts)
110{
111 const char *pm1_sts_bits[] = {
112 [0] = "TMROF",
113 [4] = "BM",
114 [5] = "GBL",
115 [8] = "PWRBTN",
116 [10] = "RTC",
117 [11] = "PRBTNOR",
118 [14] = "PCIEXPWAK",
119 [15] = "WAK",
120 };
121
122 if (!pm1_sts)
123 return 0;
124
125 printk(BIOS_SPEW, "PM1_STS: ");
126 print_status_bits(pm1_sts, pm1_sts_bits);
127 printk(BIOS_SPEW, "\n");
128
129 return pm1_sts;
130}
131
132/* Print, clear, and return PM1 status */
133u16 clear_pm1_status(void)
134{
135 return print_pm1_status(reset_pm1_status());
136}
137
Aaron Durbind6d6db32013-03-27 21:13:02 -0500138/* Set the PM1 register to events */
139void enable_pm1(u16 events)
Duncan Laurie55cdf552013-03-08 16:01:44 -0800140{
Aaron Durbind6d6db32013-03-27 21:13:02 -0500141 outw(events, get_pmbase() + PM1_EN);
Duncan Laurie55cdf552013-03-08 16:01:44 -0800142}
143
144
145/*
146 * SMI
147 */
148
149/* Clear and return SMI status register */
150static u32 reset_smi_status(void)
151{
152 u32 smi_sts = inl(get_pmbase() + SMI_STS);
153 outl(smi_sts, get_pmbase() + SMI_STS);
154 return smi_sts;
155}
156
157/* Print SMI status bits */
158static u32 print_smi_status(u32 smi_sts)
159{
160 const char *smi_sts_bits[] = {
161 [2] = "BIOS",
162 [3] = "LEGACY_USB",
163 [4] = "SLP_SMI",
164 [5] = "APM",
165 [6] = "SWSMI_TMR",
166 [8] = "PM1",
167 [9] = "GPE0",
168 [10] = "GPI",
169 [11] = "MCSMI",
170 [12] = "DEVMON",
171 [13] = "TCO",
172 [14] = "PERIODIC",
173 [15] = "SERIRQ_SMI",
174 [16] = "SMBUS_SMI",
175 [17] = "LEGACY_USB2",
176 [18] = "INTEL_USB2",
177 [20] = "PCI_EXP_SMI",
178 [21] = "MONITOR",
179 [26] = "SPI",
180 [27] = "GPIO_UNLOCK"
181 };
182
183 if (!smi_sts)
184 return 0;
185
186 printk(BIOS_DEBUG, "SMI_STS: ");
187 print_status_bits(smi_sts, smi_sts_bits);
188 printk(BIOS_DEBUG, "\n");
189
190 return smi_sts;
191}
192
193/* Print, clear, and return SMI status */
194u32 clear_smi_status(void)
195{
196 return print_smi_status(reset_smi_status());
197}
198
199/* Enable SMI event */
200void enable_smi(u32 mask)
201{
202 u32 smi_en = inl(get_pmbase() + SMI_EN);
203 smi_en |= mask;
204 outl(smi_en, get_pmbase() + SMI_EN);
205}
206
207/* Disable SMI event */
208void disable_smi(u32 mask)
209{
210 u32 smi_en = inl(get_pmbase() + SMI_EN);
211 smi_en &= ~mask;
212 outl(smi_en, get_pmbase() + SMI_EN);
213}
214
215
216/*
217 * ALT_GP_SMI
218 */
219
220/* Clear GPIO SMI status and return events that are enabled and active */
221static u32 reset_alt_smi_status(void)
222{
223 u32 alt_sts, alt_en;
224
225 if (pch_is_lp()) {
226 /* LynxPoint-LP moves this to GPIO region as dword */
227 alt_sts = inl(get_gpiobase() + GPIO_ALT_GPI_SMI_STS);
228 outl(alt_sts, get_gpiobase() + GPIO_ALT_GPI_SMI_STS);
229
230 alt_en = inl(get_gpiobase() + GPIO_ALT_GPI_SMI_EN);
231 } else {
232 u16 pmbase = get_pmbase();
233
234 /* LynxPoint-H adds a second enable/status word */
235 alt_sts = inw(pmbase + ALT_GP_SMI_STS2);
236 outw(alt_sts & 0xffff, pmbase + ALT_GP_SMI_STS2);
237
238 alt_sts <<= 16;
239 alt_sts |= inw(pmbase + ALT_GP_SMI_STS);
240 outw(alt_sts & 0xffff, pmbase + ALT_GP_SMI_STS);
241
242 alt_en = inw(pmbase + ALT_GP_SMI_EN2);
243 alt_en <<= 16;
244 alt_en |= inw(pmbase + ALT_GP_SMI_EN);
245 }
246
247 /* Only report enabled events */
248 return alt_sts & alt_en;
249}
250
251/* Print GPIO SMI status bits */
252static u32 print_alt_smi_status(u32 alt_sts)
253{
254 if (!alt_sts)
255 return 0;
256
257 printk(BIOS_DEBUG, "ALT_STS: ");
258
259 if (pch_is_lp()) {
260 /* First 16 events are GPIO 32-47 */
261 print_gpio_status(alt_sts & 0xffff, 32);
262 } else {
263 const char *alt_sts_bits_high[] = {
264 [0] = "GPIO17",
265 [1] = "GPIO19",
266 [2] = "GPIO21",
267 [3] = "GPIO22",
268 [4] = "GPIO43",
269 [5] = "GPIO56",
270 [6] = "GPIO57",
271 [7] = "GPIO60",
272 };
273
274 /* First 16 events are GPIO 0-15 */
275 print_gpio_status(alt_sts & 0xffff, 0);
276 print_status_bits(alt_sts >> 16, alt_sts_bits_high);
277 }
278
279 printk(BIOS_DEBUG, "\n");
280
281 return alt_sts;
282}
283
284/* Print, clear, and return GPIO SMI status */
285u32 clear_alt_smi_status(void)
286{
287 return print_alt_smi_status(reset_alt_smi_status());
288}
289
290/* Enable GPIO SMI events */
291void enable_alt_smi(u32 mask)
292{
293 if (pch_is_lp()) {
294 u32 alt_en;
295
296 alt_en = inl(get_gpiobase() + GPIO_ALT_GPI_SMI_EN);
297 alt_en |= mask;
298 outl(alt_en, get_gpiobase() + GPIO_ALT_GPI_SMI_EN);
299 } else {
300 u16 pmbase = get_pmbase();
301 u16 alt_en;
302
303 /* Lower enable register */
304 alt_en = inw(pmbase + ALT_GP_SMI_EN);
305 alt_en |= mask & 0xffff;
306 outw(alt_en, pmbase + ALT_GP_SMI_EN);
307
308 /* Upper enable register */
309 alt_en = inw(pmbase + ALT_GP_SMI_EN2);
310 alt_en |= (mask >> 16) & 0xffff;
311 outw(alt_en, pmbase + ALT_GP_SMI_EN2);
312 }
313}
314
315
316/*
317 * TCO
318 */
319
320/* Clear TCO status and return events that are enabled and active */
321static u32 reset_tco_status(void)
322{
323 u32 tcobase = get_pmbase() + 0x60;
324 u32 tco_sts = inl(tcobase + 0x04);
325 u32 tco_en = inl(get_pmbase() + 0x68);
326
327 /* Don't clear BOOT_STS before SECOND_TO_STS */
328 outl(tco_sts & ~(1 << 18), tcobase + 0x04);
329
330 /* Clear BOOT_STS */
331 if (tco_sts & (1 << 18))
332 outl(tco_sts & (1 << 18), tcobase + 0x04);
333
334 return tco_sts & tco_en;
335}
336
337/* Print TCO status bits */
338static u32 print_tco_status(u32 tco_sts)
339{
340 const char *tco_sts_bits[] = {
341 [0] = "NMI2SMI",
342 [1] = "SW_TCO",
343 [2] = "TCO_INT",
344 [3] = "TIMEOUT",
345 [7] = "NEWCENTURY",
346 [8] = "BIOSWR",
347 [9] = "DMISCI",
348 [10] = "DMISMI",
349 [12] = "DMISERR",
350 [13] = "SLVSEL",
351 [16] = "INTRD_DET",
352 [17] = "SECOND_TO",
353 [18] = "BOOT",
354 [20] = "SMLINK_SLV"
355 };
356
357 if (!tco_sts)
358 return 0;
359
360 printk(BIOS_DEBUG, "TCO_STS: ");
361 print_status_bits(tco_sts, tco_sts_bits);
362 printk(BIOS_DEBUG, "\n");
363
364 return tco_sts;
365}
366
367/* Print, clear, and return TCO status */
368u32 clear_tco_status(void)
369{
370 return print_tco_status(reset_tco_status());
371}
372
373/* Enable TCO SCI */
374void enable_tco_sci(void)
375{
376 u16 gpe0_sts = pch_is_lp() ? LP_GPE0_STS_4 : GPE0_STS;
377
378 /* Clear pending events */
379 outl(get_pmbase() + gpe0_sts, TCOSCI_STS);
380
381 /* Enable TCO SCI events */
382 enable_gpe(TCOSCI_EN);
383}
384
385
386/*
387 * GPE0
388 */
389
390/* Clear a GPE0 status and return events that are enabled and active */
391static u32 reset_gpe_status(u16 sts_reg, u16 en_reg)
392{
393 u32 gpe0_sts = inl(get_pmbase() + sts_reg);
394 u32 gpe0_en = inl(get_pmbase() + en_reg);
395
396 outl(gpe0_sts, get_pmbase() + sts_reg);
397
398 /* Only report enabled events */
399 return gpe0_sts & gpe0_en;
400}
401
402/* Print GPE0 status bits */
403static u32 print_gpe_status(u32 gpe0_sts, const char *bit_names[])
404{
405 if (!gpe0_sts)
406 return 0;
407
408 printk(BIOS_DEBUG, "GPE0_STS: ");
409 print_status_bits(gpe0_sts, bit_names);
410 printk(BIOS_DEBUG, "\n");
411
412 return gpe0_sts;
413}
414
415/* Print GPE0 GPIO status bits */
416static u32 print_gpe_gpio(u32 gpe0_sts, int start)
417{
418 if (!gpe0_sts)
419 return 0;
420
421 printk(BIOS_DEBUG, "GPE0_STS: ");
422 print_gpio_status(gpe0_sts, start);
423 printk(BIOS_DEBUG, "\n");
424
425 return gpe0_sts;
426}
427
428/* Print, clear, and return LynxPoint-H GPE0 status */
429static u32 clear_lpt_gpe_status(void)
430{
431 const char *gpe0_sts_bits_low[] = {
432 [1] = "HOTPLUG",
433 [2] = "SWGPE",
434 [6] = "TCO_SCI",
435 [7] = "SMB_WAK",
436 [8] = "RI",
437 [9] = "PCI_EXP",
438 [10] = "BATLOW",
439 [11] = "PME",
440 [13] = "PME_B0",
441 [16] = "GPIO0",
442 [17] = "GPIO1",
443 [18] = "GPIO2",
444 [19] = "GPIO3",
445 [20] = "GPIO4",
446 [21] = "GPIO5",
447 [22] = "GPIO6",
448 [23] = "GPIO7",
449 [24] = "GPIO8",
450 [25] = "GPIO9",
451 [26] = "GPIO10",
452 [27] = "GPIO11",
453 [28] = "GPIO12",
454 [29] = "GPIO13",
455 [30] = "GPIO14",
456 [31] = "GPIO15",
457 };
458 const char *gpe0_sts_bits_high[] = {
459 [3] = "GPIO27",
460 [6] = "WADT",
461 [24] = "GPIO17",
462 [25] = "GPIO19",
463 [26] = "GPIO21",
464 [27] = "GPIO22",
465 [28] = "GPIO43",
466 [29] = "GPIO56",
467 [30] = "GPIO57",
468 [31] = "GPIO60",
469 };
470
471 /* High bits */
472 print_gpe_status(reset_gpe_status(GPE0_STS_2, GPE0_EN_2),
473 gpe0_sts_bits_high);
474
475 /* Standard GPE and GPIO 0-31 */
476 return print_gpe_status(reset_gpe_status(GPE0_STS, GPE0_EN),
477 gpe0_sts_bits_low);
478}
479
480/* Print, clear, and return LynxPoint-LP GPE0 status */
481static u32 clear_lpt_lp_gpe_status(void)
482{
483 const char *gpe0_sts_4_bits[] = {
484 [1] = "HOTPLUG",
485 [2] = "SWGPE",
486 [6] = "TCO_SCI",
487 [7] = "SMB_WAK",
488 [9] = "PCI_EXP",
489 [10] = "BATLOW",
490 [11] = "PME",
491 [12] = "ME",
492 [13] = "PME_B0",
493 [16] = "GPIO27",
494 [18] = "WADT"
495 };
496
497 /* GPIO 0-31 */
498 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_1, LP_GPE0_EN_1), 0);
499
500 /* GPIO 32-63 */
501 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_2, LP_GPE0_EN_2), 32);
502
503 /* GPIO 64-94 */
504 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_3, LP_GPE0_EN_3), 64);
505
506 /* Standard GPE */
507 return print_gpe_status(reset_gpe_status(LP_GPE0_STS_4, LP_GPE0_EN_4),
508 gpe0_sts_4_bits);
509}
510
511/* Clear all GPE status and return "standard" GPE event status */
512u32 clear_gpe_status(void)
513{
514 if (pch_is_lp())
515 return clear_lpt_lp_gpe_status();
516 else
517 return clear_lpt_gpe_status();
518}
519
520/* Enable all requested GPE */
521void enable_all_gpe(u32 set1, u32 set2, u32 set3, u32 set4)
522{
523 u16 pmbase = get_pmbase();
524
525 if (pch_is_lp()) {
526 outl(set1, pmbase + LP_GPE0_EN_1);
527 outl(set2, pmbase + LP_GPE0_EN_2);
528 outl(set3, pmbase + LP_GPE0_EN_3);
529 outl(set4, pmbase + LP_GPE0_EN_4);
530 } else {
531 outl(set1, pmbase + GPE0_EN);
532 outl(set2, pmbase + GPE0_EN_2);
533 }
534}
535
536/* Disable all GPE */
537void disable_all_gpe(void)
538{
539 enable_all_gpe(0, 0, 0, 0);
540}
541
542/* Enable a standard GPE */
543void enable_gpe(u32 mask)
544{
545 u32 gpe0_reg = pch_is_lp() ? LP_GPE0_EN_4 : GPE0_EN;
546 u32 gpe0_en = inl(get_pmbase() + gpe0_reg);
547 gpe0_en |= mask;
548 outl(gpe0_en, get_pmbase() + gpe0_reg);
549}
550
551/* Disable a standard GPE */
552void disable_gpe(u32 mask)
553{
554 u32 gpe0_reg = pch_is_lp() ? LP_GPE0_EN_4 : GPE0_EN;
555 u32 gpe0_en = inl(get_pmbase() + gpe0_reg);
556 gpe0_en &= ~mask;
557 outl(gpe0_en, get_pmbase() + gpe0_reg);
558}