util/sconfig: Remove unused ioapic and irq keywords
[coreboot.git] / src / southbridge / intel / lynxpoint / pmutil.c
blobd67fb6cd846cd85b9fa4e7d0928b89ea92054f1f
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 /*
4 * Helper functions for dealing with power management registers
5 * and the differences between LynxPoint-H and LynxPoint-LP.
6 */
8 #include <arch/io.h>
9 #include <device/device.h>
10 #include <device/pci.h>
11 #include <console/console.h>
12 #include <security/vboot/vbnv.h>
13 #include <security/vboot/vboot_common.h>
14 #include <southbridge/intel/common/rtc.h>
15 #include "pch.h"
17 #if CONFIG(INTEL_LYNXPOINT_LP)
18 #include "lp_gpio.h"
19 #endif
21 /* These defines are here to handle the LP variant code dynamically. If these
22 * values are defined in lp_gpio.h but when a non-LP board is being built, the
23 * build will fail. */
24 #define GPIO_ALT_GPI_SMI_STS 0x50
25 #define GPIO_ALT_GPI_SMI_EN 0x54
27 /* Print status bits with descriptive names */
28 static void print_status_bits(u32 status, const char *bit_names[])
30 int i;
32 if (!status)
33 return;
35 for (i = 31; i >= 0; i--) {
36 if (status & (1 << i)) {
37 if (bit_names[i])
38 printk(BIOS_DEBUG, "%s ", bit_names[i]);
39 else
40 printk(BIOS_DEBUG, "BIT%d ", i);
45 /* Print status bits as GPIO numbers */
46 static void print_gpio_status(u32 status, int start)
48 int i;
50 if (!status)
51 return;
53 for (i = 31; i >= 0; i--) {
54 if (status & (1 << i))
55 printk(BIOS_DEBUG, "GPIO%d ", start + i);
60 * PM1_CNT
63 /* Enable events in PM1 control register */
64 void enable_pm1_control(u32 mask)
66 u32 pm1_cnt = inl(get_pmbase() + PM1_CNT);
67 pm1_cnt |= mask;
68 outl(pm1_cnt, get_pmbase() + PM1_CNT);
71 /* Disable events in PM1 control register */
72 void disable_pm1_control(u32 mask)
74 u32 pm1_cnt = inl(get_pmbase() + PM1_CNT);
75 pm1_cnt &= ~mask;
76 outl(pm1_cnt, get_pmbase() + PM1_CNT);
80 * PM1
83 /* Clear and return PM1 status register */
84 static u16 reset_pm1_status(void)
86 u16 pm1_sts = inw(get_pmbase() + PM1_STS);
87 outw(pm1_sts, get_pmbase() + PM1_STS);
88 return pm1_sts;
91 /* Print PM1 status bits */
92 static u16 print_pm1_status(u16 pm1_sts)
94 const char *pm1_sts_bits[] = {
95 [0] = "TMROF",
96 [4] = "BM",
97 [5] = "GBL",
98 [8] = "PWRBTN",
99 [10] = "RTC",
100 [11] = "PRBTNOR",
101 [14] = "PCIEXPWAK",
102 [15] = "WAK",
105 if (!pm1_sts)
106 return 0;
108 printk(BIOS_SPEW, "PM1_STS: ");
109 print_status_bits(pm1_sts, pm1_sts_bits);
110 printk(BIOS_SPEW, "\n");
112 return pm1_sts;
115 /* Print, clear, and return PM1 status */
116 u16 clear_pm1_status(void)
118 return print_pm1_status(reset_pm1_status());
121 /* Set the PM1 register to events */
122 void enable_pm1(u16 events)
124 outw(events, get_pmbase() + PM1_EN);
128 * SMI
131 /* Clear and return SMI status register */
132 static u32 reset_smi_status(void)
134 u32 smi_sts = inl(get_pmbase() + SMI_STS);
135 outl(smi_sts, get_pmbase() + SMI_STS);
136 return smi_sts;
139 /* Print SMI status bits */
140 static u32 print_smi_status(u32 smi_sts)
142 const char *smi_sts_bits[] = {
143 [2] = "BIOS",
144 [3] = "LEGACY_USB",
145 [4] = "SLP_SMI",
146 [5] = "APM",
147 [6] = "SWSMI_TMR",
148 [8] = "PM1",
149 [9] = "GPE0",
150 [10] = "GPI",
151 [11] = "MCSMI",
152 [12] = "DEVMON",
153 [13] = "TCO",
154 [14] = "PERIODIC",
155 [15] = "SERIRQ_SMI",
156 [16] = "SMBUS_SMI",
157 [17] = "LEGACY_USB2",
158 [18] = "INTEL_USB2",
159 [20] = "PCI_EXP_SMI",
160 [21] = "MONITOR",
161 [26] = "SPI",
162 [27] = "GPIO_UNLOCK"
165 if (!smi_sts)
166 return 0;
168 printk(BIOS_DEBUG, "SMI_STS: ");
169 print_status_bits(smi_sts, smi_sts_bits);
170 printk(BIOS_DEBUG, "\n");
172 return smi_sts;
175 /* Print, clear, and return SMI status */
176 u32 clear_smi_status(void)
178 return print_smi_status(reset_smi_status());
181 /* Enable SMI event */
182 void enable_smi(u32 mask)
184 u32 smi_en = inl(get_pmbase() + SMI_EN);
185 smi_en |= mask;
186 outl(smi_en, get_pmbase() + SMI_EN);
189 /* Disable SMI event */
190 void disable_smi(u32 mask)
192 u32 smi_en = inl(get_pmbase() + SMI_EN);
193 smi_en &= ~mask;
194 outl(smi_en, get_pmbase() + SMI_EN);
198 * ALT_GP_SMI
201 /* Clear GPIO SMI status and return events that are enabled and active */
202 static u32 reset_alt_smi_status(void)
204 u32 alt_sts, alt_en;
206 if (pch_is_lp()) {
207 /* LynxPoint-LP moves this to GPIO region as dword */
208 alt_sts = inl(get_gpiobase() + GPIO_ALT_GPI_SMI_STS);
209 outl(alt_sts, get_gpiobase() + GPIO_ALT_GPI_SMI_STS);
211 alt_en = inl(get_gpiobase() + GPIO_ALT_GPI_SMI_EN);
212 } else {
213 u16 pmbase = get_pmbase();
215 /* LynxPoint-H adds a second enable/status word */
216 alt_sts = inw(pmbase + ALT_GP_SMI_STS2);
217 outw(alt_sts & 0xffff, pmbase + ALT_GP_SMI_STS2);
219 alt_sts <<= 16;
220 alt_sts |= inw(pmbase + ALT_GP_SMI_STS);
221 outw(alt_sts & 0xffff, pmbase + ALT_GP_SMI_STS);
223 alt_en = inw(pmbase + ALT_GP_SMI_EN2);
224 alt_en <<= 16;
225 alt_en |= inw(pmbase + ALT_GP_SMI_EN);
228 /* Only report enabled events */
229 return alt_sts & alt_en;
232 /* Print GPIO SMI status bits */
233 static u32 print_alt_smi_status(u32 alt_sts)
235 if (!alt_sts)
236 return 0;
238 printk(BIOS_DEBUG, "ALT_STS: ");
240 if (pch_is_lp()) {
241 /* First 16 events are GPIO 32-47 */
242 print_gpio_status(alt_sts & 0xffff, 32);
243 } else {
244 const char *alt_sts_bits_high[] = {
245 [0] = "GPIO17",
246 [1] = "GPIO19",
247 [2] = "GPIO21",
248 [3] = "GPIO22",
249 [4] = "GPIO43",
250 [5] = "GPIO56",
251 [6] = "GPIO57",
252 [7] = "GPIO60",
255 /* First 16 events are GPIO 0-15 */
256 print_gpio_status(alt_sts & 0xffff, 0);
257 print_status_bits(alt_sts >> 16, alt_sts_bits_high);
260 printk(BIOS_DEBUG, "\n");
262 return alt_sts;
265 /* Print, clear, and return GPIO SMI status */
266 u32 clear_alt_smi_status(void)
268 return print_alt_smi_status(reset_alt_smi_status());
271 /* Enable GPIO SMI events */
272 void enable_alt_smi(u32 mask)
274 if (pch_is_lp()) {
275 u32 alt_en;
277 alt_en = inl(get_gpiobase() + GPIO_ALT_GPI_SMI_EN);
278 alt_en |= mask;
279 outl(alt_en, get_gpiobase() + GPIO_ALT_GPI_SMI_EN);
280 } else {
281 u16 pmbase = get_pmbase();
282 u16 alt_en;
284 /* Lower enable register */
285 alt_en = inw(pmbase + ALT_GP_SMI_EN);
286 alt_en |= mask & 0xffff;
287 outw(alt_en, pmbase + ALT_GP_SMI_EN);
289 /* Upper enable register */
290 alt_en = inw(pmbase + ALT_GP_SMI_EN2);
291 alt_en |= (mask >> 16) & 0xffff;
292 outw(alt_en, pmbase + ALT_GP_SMI_EN2);
297 * TCO
300 /* Clear TCO status and return events that are active */
301 static u32 reset_tco_status(void)
303 u32 tcobase = get_pmbase() + 0x60;
304 u32 tco_sts = inl(tcobase + 0x04);
306 /* Don't clear BOOT_STS before SECOND_TO_STS */
307 outl(tco_sts & ~(1 << 18), tcobase + 0x04);
309 /* Clear BOOT_STS */
310 if (tco_sts & (1 << 18))
311 outl(tco_sts & (1 << 18), tcobase + 0x04);
313 return tco_sts;
316 /* Print TCO status bits */
317 static u32 print_tco_status(u32 tco_sts)
319 const char *tco_sts_bits[] = {
320 [0] = "NMI2SMI",
321 [1] = "SW_TCO",
322 [2] = "TCO_INT",
323 [3] = "TIMEOUT",
324 [7] = "NEWCENTURY",
325 [8] = "BIOSWR",
326 [9] = "DMISCI",
327 [10] = "DMISMI",
328 [12] = "DMISERR",
329 [13] = "SLVSEL",
330 [16] = "INTRD_DET",
331 [17] = "SECOND_TO",
332 [18] = "BOOT",
333 [20] = "SMLINK_SLV"
336 if (!tco_sts)
337 return 0;
339 printk(BIOS_DEBUG, "TCO_STS: ");
340 print_status_bits(tco_sts, tco_sts_bits);
341 printk(BIOS_DEBUG, "\n");
343 return tco_sts;
346 /* Print, clear, and return TCO status */
347 u32 clear_tco_status(void)
349 return print_tco_status(reset_tco_status());
352 /* Enable TCO SCI */
353 void enable_tco_sci(void)
355 u16 gpe0_sts = pch_is_lp() ? LP_GPE0_STS_4 : GPE0_STS;
357 /* Clear pending events */
358 outl(TCOSCI_STS, get_pmbase() + gpe0_sts);
360 /* Enable TCO SCI events */
361 enable_gpe(TCOSCI_EN);
365 * GPE0
368 /* Clear a GPE0 status and return events that are enabled and active */
369 static u32 reset_gpe_status(u16 sts_reg, u16 en_reg)
371 u32 gpe0_sts = inl(get_pmbase() + sts_reg);
372 u32 gpe0_en = inl(get_pmbase() + en_reg);
374 outl(gpe0_sts, get_pmbase() + sts_reg);
376 /* Only report enabled events */
377 return gpe0_sts & gpe0_en;
380 /* Print GPE0 status bits */
381 static u32 print_gpe_status(u32 gpe0_sts, const char *bit_names[])
383 if (!gpe0_sts)
384 return 0;
386 printk(BIOS_DEBUG, "GPE0_STS: ");
387 print_status_bits(gpe0_sts, bit_names);
388 printk(BIOS_DEBUG, "\n");
390 return gpe0_sts;
393 /* Print GPE0 GPIO status bits */
394 static u32 print_gpe_gpio(u32 gpe0_sts, int start)
396 if (!gpe0_sts)
397 return 0;
399 printk(BIOS_DEBUG, "GPE0_STS: ");
400 print_gpio_status(gpe0_sts, start);
401 printk(BIOS_DEBUG, "\n");
403 return gpe0_sts;
406 /* Print, clear, and return LynxPoint-H GPE0 status */
407 static u32 clear_lpt_gpe_status(void)
409 const char *gpe0_sts_bits_low[] = {
410 [1] = "HOTPLUG",
411 [2] = "SWGPE",
412 [6] = "TCO_SCI",
413 [7] = "SMB_WAK",
414 [8] = "RI",
415 [9] = "PCI_EXP",
416 [10] = "BATLOW",
417 [11] = "PME",
418 [13] = "PME_B0",
419 [16] = "GPIO0",
420 [17] = "GPIO1",
421 [18] = "GPIO2",
422 [19] = "GPIO3",
423 [20] = "GPIO4",
424 [21] = "GPIO5",
425 [22] = "GPIO6",
426 [23] = "GPIO7",
427 [24] = "GPIO8",
428 [25] = "GPIO9",
429 [26] = "GPIO10",
430 [27] = "GPIO11",
431 [28] = "GPIO12",
432 [29] = "GPIO13",
433 [30] = "GPIO14",
434 [31] = "GPIO15",
436 const char *gpe0_sts_bits_high[] = {
437 [3] = "GPIO27",
438 [6] = "WADT",
439 [24] = "GPIO17",
440 [25] = "GPIO19",
441 [26] = "GPIO21",
442 [27] = "GPIO22",
443 [28] = "GPIO43",
444 [29] = "GPIO56",
445 [30] = "GPIO57",
446 [31] = "GPIO60",
449 /* High bits */
450 print_gpe_status(reset_gpe_status(GPE0_STS_2, GPE0_EN_2),
451 gpe0_sts_bits_high);
453 /* Standard GPE and GPIO 0-31 */
454 return print_gpe_status(reset_gpe_status(GPE0_STS, GPE0_EN),
455 gpe0_sts_bits_low);
458 /* Print, clear, and return LynxPoint-LP GPE0 status */
459 static u32 clear_lpt_lp_gpe_status(void)
461 const char *gpe0_sts_4_bits[] = {
462 [1] = "HOTPLUG",
463 [2] = "SWGPE",
464 [6] = "TCO_SCI",
465 [7] = "SMB_WAK",
466 [9] = "PCI_EXP",
467 [10] = "BATLOW",
468 [11] = "PME",
469 [12] = "ME",
470 [13] = "PME_B0",
471 [16] = "GPIO27",
472 [18] = "WADT"
475 /* GPIO 0-31 */
476 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_1, LP_GPE0_EN_1), 0);
478 /* GPIO 32-63 */
479 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_2, LP_GPE0_EN_2), 32);
481 /* GPIO 64-94 */
482 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_3, LP_GPE0_EN_3), 64);
484 /* Standard GPE */
485 return print_gpe_status(reset_gpe_status(LP_GPE0_STS_4, LP_GPE0_EN_4),
486 gpe0_sts_4_bits);
489 /* Clear all GPE status and return "standard" GPE event status */
490 u32 clear_gpe_status(void)
492 if (pch_is_lp())
493 return clear_lpt_lp_gpe_status();
494 else
495 return clear_lpt_gpe_status();
498 /* Enable all requested GPE */
499 void enable_all_gpe(u32 set1, u32 set2, u32 set3, u32 set4)
501 u16 pmbase = get_pmbase();
503 if (pch_is_lp()) {
504 outl(set1, pmbase + LP_GPE0_EN_1);
505 outl(set2, pmbase + LP_GPE0_EN_2);
506 outl(set3, pmbase + LP_GPE0_EN_3);
507 outl(set4, pmbase + LP_GPE0_EN_4);
508 } else {
509 outl(set1, pmbase + GPE0_EN);
510 outl(set2, pmbase + GPE0_EN_2);
514 /* Disable all GPE */
515 void disable_all_gpe(void)
517 enable_all_gpe(0, 0, 0, 0);
520 /* Enable a standard GPE */
521 void enable_gpe(u32 mask)
523 u32 gpe0_reg = pch_is_lp() ? LP_GPE0_EN_4 : GPE0_EN;
524 u32 gpe0_en = inl(get_pmbase() + gpe0_reg);
525 gpe0_en |= mask;
526 outl(gpe0_en, get_pmbase() + gpe0_reg);
529 /* Disable a standard GPE */
530 void disable_gpe(u32 mask)
532 u32 gpe0_reg = pch_is_lp() ? LP_GPE0_EN_4 : GPE0_EN;
533 u32 gpe0_en = inl(get_pmbase() + gpe0_reg);
534 gpe0_en &= ~mask;
535 outl(gpe0_en, get_pmbase() + gpe0_reg);