1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * Helper functions for dealing with power management registers
5 * and the differences between LynxPoint-H and LynxPoint-LP.
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>
17 #if CONFIG(INTEL_LYNXPOINT_LP)
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
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
[])
35 for (i
= 31; i
>= 0; i
--) {
36 if (status
& (1 << i
)) {
38 printk(BIOS_DEBUG
, "%s ", bit_names
[i
]);
40 printk(BIOS_DEBUG
, "BIT%d ", i
);
45 /* Print status bits as GPIO numbers */
46 static void print_gpio_status(u32 status
, int start
)
53 for (i
= 31; i
>= 0; i
--) {
54 if (status
& (1 << i
))
55 printk(BIOS_DEBUG
, "GPIO%d ", start
+ i
);
63 /* Enable events in PM1 control register */
64 void enable_pm1_control(u32 mask
)
66 u32 pm1_cnt
= inl(get_pmbase() + PM1_CNT
);
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
);
76 outl(pm1_cnt
, get_pmbase() + PM1_CNT
);
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
);
91 /* Print PM1 status bits */
92 static u16
print_pm1_status(u16 pm1_sts
)
94 const char *pm1_sts_bits
[] = {
108 printk(BIOS_SPEW
, "PM1_STS: ");
109 print_status_bits(pm1_sts
, pm1_sts_bits
);
110 printk(BIOS_SPEW
, "\n");
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
);
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
);
139 /* Print SMI status bits */
140 static u32
print_smi_status(u32 smi_sts
)
142 const char *smi_sts_bits
[] = {
157 [17] = "LEGACY_USB2",
159 [20] = "PCI_EXP_SMI",
168 printk(BIOS_DEBUG
, "SMI_STS: ");
169 print_status_bits(smi_sts
, smi_sts_bits
);
170 printk(BIOS_DEBUG
, "\n");
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
);
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
);
194 outl(smi_en
, get_pmbase() + SMI_EN
);
201 /* Clear GPIO SMI status and return events that are enabled and active */
202 static u32
reset_alt_smi_status(void)
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
);
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
);
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
);
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
)
238 printk(BIOS_DEBUG
, "ALT_STS: ");
241 /* First 16 events are GPIO 32-47 */
242 print_gpio_status(alt_sts
& 0xffff, 32);
244 const char *alt_sts_bits_high
[] = {
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");
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
)
277 alt_en
= inl(get_gpiobase() + GPIO_ALT_GPI_SMI_EN
);
279 outl(alt_en
, get_gpiobase() + GPIO_ALT_GPI_SMI_EN
);
281 u16 pmbase
= get_pmbase();
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
);
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);
310 if (tco_sts
& (1 << 18))
311 outl(tco_sts
& (1 << 18), tcobase
+ 0x04);
316 /* Print TCO status bits */
317 static u32
print_tco_status(u32 tco_sts
)
319 const char *tco_sts_bits
[] = {
339 printk(BIOS_DEBUG
, "TCO_STS: ");
340 print_status_bits(tco_sts
, tco_sts_bits
);
341 printk(BIOS_DEBUG
, "\n");
346 /* Print, clear, and return TCO status */
347 u32
clear_tco_status(void)
349 return print_tco_status(reset_tco_status());
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
);
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
[])
386 printk(BIOS_DEBUG
, "GPE0_STS: ");
387 print_status_bits(gpe0_sts
, bit_names
);
388 printk(BIOS_DEBUG
, "\n");
393 /* Print GPE0 GPIO status bits */
394 static u32
print_gpe_gpio(u32 gpe0_sts
, int start
)
399 printk(BIOS_DEBUG
, "GPE0_STS: ");
400 print_gpio_status(gpe0_sts
, start
);
401 printk(BIOS_DEBUG
, "\n");
406 /* Print, clear, and return LynxPoint-H GPE0 status */
407 static u32
clear_lpt_gpe_status(void)
409 const char *gpe0_sts_bits_low
[] = {
436 const char *gpe0_sts_bits_high
[] = {
450 print_gpe_status(reset_gpe_status(GPE0_STS_2
, GPE0_EN_2
),
453 /* Standard GPE and GPIO 0-31 */
454 return print_gpe_status(reset_gpe_status(GPE0_STS
, GPE0_EN
),
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
[] = {
476 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_1
, LP_GPE0_EN_1
), 0);
479 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_2
, LP_GPE0_EN_2
), 32);
482 print_gpe_gpio(reset_gpe_status(LP_GPE0_STS_3
, LP_GPE0_EN_3
), 64);
485 return print_gpe_status(reset_gpe_status(LP_GPE0_STS_4
, LP_GPE0_EN_4
),
489 /* Clear all GPE status and return "standard" GPE event status */
490 u32
clear_gpe_status(void)
493 return clear_lpt_lp_gpe_status();
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();
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
);
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
);
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
);
535 outl(gpe0_en
, get_pmbase() + gpe0_reg
);