065857ee7f
Change-Id: I91158452680586ac676ea11c8589062880a31f91 Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: https://review.coreboot.org/c/31692 Reviewed-by: Patrick Georgi <pgeorgi@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
234 lines
6.6 KiB
C
234 lines
6.6 KiB
C
/*
|
|
* This file is part of the coreboot project.
|
|
*
|
|
* Copyright 2013 Google Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; version 2 of
|
|
* the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <types.h>
|
|
#include <console/console.h>
|
|
#include <cpu/x86/cache.h>
|
|
#include <device/pci_def.h>
|
|
#include <cpu/x86/smm.h>
|
|
#include <elog.h>
|
|
#include <southbridge/intel/common/pmbase.h>
|
|
#include <southbridge/intel/common/gpio.h>
|
|
|
|
#include "pmutil.h"
|
|
|
|
void alt_gpi_mask(u16 clr, u16 set)
|
|
{
|
|
u16 alt_gp = read_pmbase16(ALT_GP_SMI_EN);
|
|
alt_gp &= ~clr;
|
|
alt_gp |= set;
|
|
write_pmbase16(ALT_GP_SMI_EN, alt_gp);
|
|
}
|
|
|
|
void gpe0_mask(u32 clr, u32 set)
|
|
{
|
|
u32 gpe0 = read_pmbase32(GPE0_EN);
|
|
gpe0 &= ~clr;
|
|
gpe0 |= set;
|
|
write_pmbase32(GPE0_EN, gpe0);
|
|
}
|
|
|
|
/**
|
|
* @brief read and clear PM1_STS
|
|
* @return PM1_STS register
|
|
*/
|
|
u16 reset_pm1_status(void)
|
|
{
|
|
u16 reg16 = read_pmbase16(PM1_STS);
|
|
/* set status bits are cleared by writing 1 to them */
|
|
write_pmbase16(PM1_STS, reg16);
|
|
|
|
return reg16;
|
|
}
|
|
|
|
void dump_pm1_status(u16 pm1_sts)
|
|
{
|
|
printk(BIOS_SPEW, "PM1_STS: ");
|
|
if (pm1_sts & (1 << 15)) printk(BIOS_SPEW, "WAK ");
|
|
if (pm1_sts & (1 << 14)) printk(BIOS_SPEW, "PCIEXPWAK ");
|
|
if (pm1_sts & (1 << 11)) printk(BIOS_SPEW, "PRBTNOR ");
|
|
if (pm1_sts & (1 << 10)) printk(BIOS_SPEW, "RTC ");
|
|
if (pm1_sts & (1 << 8)) printk(BIOS_SPEW, "PWRBTN ");
|
|
if (pm1_sts & (1 << 5)) printk(BIOS_SPEW, "GBL ");
|
|
if (pm1_sts & (1 << 4)) printk(BIOS_SPEW, "BM ");
|
|
if (pm1_sts & (1 << 0)) printk(BIOS_SPEW, "TMROF ");
|
|
printk(BIOS_SPEW, "\n");
|
|
|
|
int reg16 = read_pmbase16(PM1_EN);
|
|
printk(BIOS_SPEW, "PM1_EN: %x\n", reg16);
|
|
}
|
|
|
|
/**
|
|
* @brief read and clear SMI_STS
|
|
* @return SMI_STS register
|
|
*/
|
|
u32 reset_smi_status(void)
|
|
{
|
|
u32 reg32;
|
|
|
|
reg32 = read_pmbase32(SMI_STS);
|
|
/* set status bits are cleared by writing 1 to them */
|
|
write_pmbase32(SMI_STS, reg32);
|
|
|
|
return reg32;
|
|
}
|
|
|
|
void dump_smi_status(u32 smi_sts)
|
|
{
|
|
printk(BIOS_DEBUG, "SMI_STS: ");
|
|
if (smi_sts & (1 << 26)) printk(BIOS_DEBUG, "SPI ");
|
|
if (smi_sts & (1 << 21)) printk(BIOS_DEBUG, "MONITOR ");
|
|
if (smi_sts & (1 << 20)) printk(BIOS_DEBUG, "PCI_EXP_SMI ");
|
|
if (smi_sts & (1 << 18)) printk(BIOS_DEBUG, "INTEL_USB2 ");
|
|
if (smi_sts & (1 << 17)) printk(BIOS_DEBUG, "LEGACY_USB2 ");
|
|
if (smi_sts & (1 << 16)) printk(BIOS_DEBUG, "SMBUS_SMI ");
|
|
if (smi_sts & (1 << 15)) printk(BIOS_DEBUG, "SERIRQ_SMI ");
|
|
if (smi_sts & (1 << 14)) printk(BIOS_DEBUG, "PERIODIC ");
|
|
if (smi_sts & (1 << 13)) printk(BIOS_DEBUG, "TCO ");
|
|
if (smi_sts & (1 << 12)) printk(BIOS_DEBUG, "DEVMON ");
|
|
if (smi_sts & (1 << 11)) printk(BIOS_DEBUG, "MCSMI ");
|
|
if (smi_sts & (1 << 10)) printk(BIOS_DEBUG, "GPI ");
|
|
if (smi_sts & (1 << 9)) printk(BIOS_DEBUG, "GPE0 ");
|
|
if (smi_sts & (1 << 8)) printk(BIOS_DEBUG, "PM1 ");
|
|
if (smi_sts & (1 << 6)) printk(BIOS_DEBUG, "SWSMI_TMR ");
|
|
if (smi_sts & (1 << 5)) printk(BIOS_DEBUG, "APM ");
|
|
if (smi_sts & (1 << 4)) printk(BIOS_DEBUG, "SLP_SMI ");
|
|
if (smi_sts & (1 << 3)) printk(BIOS_DEBUG, "LEGACY_USB ");
|
|
if (smi_sts & (1 << 2)) printk(BIOS_DEBUG, "BIOS ");
|
|
printk(BIOS_DEBUG, "\n");
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief read and clear GPE0_STS
|
|
* @return GPE0_STS register
|
|
*/
|
|
u64 reset_gpe0_status(void)
|
|
{
|
|
u32 reg_h, reg_l;
|
|
|
|
reg_l = read_pmbase32(GPE0_STS);
|
|
reg_h = read_pmbase32(GPE0_STS + 4);
|
|
/* set status bits are cleared by writing 1 to them */
|
|
write_pmbase32(GPE0_STS, reg_l);
|
|
write_pmbase32(GPE0_STS + 4, reg_h);
|
|
|
|
return (((u64)reg_h) << 32) | reg_l;
|
|
}
|
|
|
|
void dump_gpe0_status(u64 gpe0_sts)
|
|
{
|
|
int i;
|
|
printk(BIOS_DEBUG, "GPE0_STS: ");
|
|
if (gpe0_sts & (1LL << 32)) printk(BIOS_DEBUG, "USB6 ");
|
|
for (i=31; i>= 16; i--) {
|
|
if (gpe0_sts & (1 << i)) printk(BIOS_DEBUG, "GPIO%d ", (i-16));
|
|
}
|
|
if (gpe0_sts & (1 << 14)) printk(BIOS_DEBUG, "USB4 ");
|
|
if (gpe0_sts & (1 << 13)) printk(BIOS_DEBUG, "PME_B0 ");
|
|
if (gpe0_sts & (1 << 12)) printk(BIOS_DEBUG, "USB3 ");
|
|
if (gpe0_sts & (1 << 11)) printk(BIOS_DEBUG, "PME ");
|
|
if (gpe0_sts & (1 << 10)) printk(BIOS_DEBUG, "EL_SCI/BATLOW ");
|
|
if (gpe0_sts & (1 << 9)) printk(BIOS_DEBUG, "PCI_EXP ");
|
|
if (gpe0_sts & (1 << 8)) printk(BIOS_DEBUG, "RI ");
|
|
if (gpe0_sts & (1 << 7)) printk(BIOS_DEBUG, "SMB_WAK ");
|
|
if (gpe0_sts & (1 << 6)) printk(BIOS_DEBUG, "TCO_SCI ");
|
|
if (gpe0_sts & (1 << 5)) printk(BIOS_DEBUG, "USB5 ");
|
|
if (gpe0_sts & (1 << 4)) printk(BIOS_DEBUG, "USB2 ");
|
|
if (gpe0_sts & (1 << 3)) printk(BIOS_DEBUG, "USB1 ");
|
|
if (gpe0_sts & (1 << 2)) printk(BIOS_DEBUG, "SWGPE ");
|
|
if (gpe0_sts & (1 << 1)) printk(BIOS_DEBUG, "HOT_PLUG ");
|
|
if (gpe0_sts & (1 << 0)) printk(BIOS_DEBUG, "THRM ");
|
|
printk(BIOS_DEBUG, "\n");
|
|
}
|
|
|
|
/**
|
|
* @brief read and clear TCOx_STS
|
|
* @return TCOx_STS registers
|
|
*/
|
|
u32 reset_tco_status(void)
|
|
{
|
|
u32 reg32;
|
|
|
|
reg32 = read_pmbase32(TCO1_STS);
|
|
/*
|
|
* set status bits are cleared by writing 1 to them, but don't
|
|
* clear BOOT_STS before SECOND_TO_STS.
|
|
*/
|
|
write_pmbase32(TCO1_STS, reg32 & ~BOOT_STS);
|
|
if (reg32 & BOOT_STS)
|
|
write_pmbase32(TCO1_STS, BOOT_STS);
|
|
|
|
return reg32;
|
|
}
|
|
|
|
|
|
void dump_tco_status(u32 tco_sts)
|
|
{
|
|
printk(BIOS_DEBUG, "TCO_STS: ");
|
|
if (tco_sts & (1 << 20)) printk(BIOS_DEBUG, "SMLINK_SLV ");
|
|
if (tco_sts & (1 << 18)) printk(BIOS_DEBUG, "BOOT ");
|
|
if (tco_sts & (1 << 17)) printk(BIOS_DEBUG, "SECOND_TO ");
|
|
if (tco_sts & (1 << 16)) printk(BIOS_DEBUG, "INTRD_DET ");
|
|
if (tco_sts & (1 << 12)) printk(BIOS_DEBUG, "DMISERR ");
|
|
if (tco_sts & (1 << 10)) printk(BIOS_DEBUG, "DMISMI ");
|
|
if (tco_sts & (1 << 9)) printk(BIOS_DEBUG, "DMISCI ");
|
|
if (tco_sts & (1 << 8)) printk(BIOS_DEBUG, "BIOSWR ");
|
|
if (tco_sts & (1 << 7)) printk(BIOS_DEBUG, "NEWCENTURY ");
|
|
if (tco_sts & (1 << 3)) printk(BIOS_DEBUG, "TIMEOUT ");
|
|
if (tco_sts & (1 << 2)) printk(BIOS_DEBUG, "TCO_INT ");
|
|
if (tco_sts & (1 << 1)) printk(BIOS_DEBUG, "SW_TCO ");
|
|
if (tco_sts & (1 << 0)) printk(BIOS_DEBUG, "NMI2SMI ");
|
|
printk(BIOS_DEBUG, "\n");
|
|
}
|
|
|
|
/**
|
|
* @brief Set the EOS bit
|
|
*/
|
|
void smi_set_eos(void)
|
|
{
|
|
u8 reg8;
|
|
|
|
reg8 = read_pmbase8(SMI_EN);
|
|
reg8 |= EOS;
|
|
write_pmbase8(SMI_EN, reg8);
|
|
}
|
|
|
|
|
|
void dump_alt_gp_smi_status(u16 alt_gp_smi_sts)
|
|
{
|
|
int i;
|
|
printk(BIOS_DEBUG, "ALT_GP_SMI_STS: ");
|
|
for (i=15; i>= 0; i--) {
|
|
if (alt_gp_smi_sts & (1 << i)) printk(BIOS_DEBUG, "GPI%d ", i);
|
|
}
|
|
printk(BIOS_DEBUG, "\n");
|
|
}
|
|
|
|
/**
|
|
* @brief read and clear ALT_GP_SMI_STS
|
|
* @return ALT_GP_SMI_STS register
|
|
*/
|
|
u16 reset_alt_gp_smi_status(void)
|
|
{
|
|
u16 reg16;
|
|
|
|
reg16 = read_pmbase16(ALT_GP_SMI_STS);
|
|
/* set status bits are cleared by writing 1 to them */
|
|
write_pmbase16(ALT_GP_SMI_STS, reg16);
|
|
|
|
return reg16;
|
|
}
|