/** @file
Source code file for Platform Init PEI module
Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/**
Clear any SMI status or wake status left from boot.
@retval EFI_SUCCESS The function completed successfully.
**/
EFI_STATUS
ClearIchSmiAndWake (
VOID
)
{
EFI_STATUS Status;
EFI_BOOT_MODE BootMode;
UINT16 ABase;
UINT16 Pm1Sts;
UINT32 Pm1Cnt;
UINT32 Data32;
UINT32 Gpe0Sts;
UINT32 SmiSts;
UINT16 DevActSts;
UINT16 TcoBase;
UINT16 Tco1Sts;
UINT16 LpcDeviceId;
UINTN LanBaseAddress;
UINT16 LanPmcs;
Status = PeiServicesGetBootMode (&BootMode);
ASSERT_EFI_ERROR (Status);
if (BootMode == BOOT_ON_S3_RESUME) {
return EFI_SUCCESS;
}
PchAcpiBaseGet (&ABase);
PchTcoBaseGet (&TcoBase);
//
// Read the ACPI registers
//
Pm1Sts = IoRead16 (ABase + R_PCH_ACPI_PM1_STS);
Pm1Cnt = IoRead32 (ABase + R_PCH_ACPI_PM1_CNT);
Gpe0Sts = IoRead32 (ABase + R_PCH_ACPI_GPE0_STS_127_96);
SmiSts = IoRead32 (ABase + R_PCH_SMI_STS);
Data32 = 0;
//
// Before clear B_PCH_ACPI_GPE0_STS_127_96_PME_B0, PMES bit of internal device must be cleared at first.
//
Data32 = (Gpe0Sts & B_PCH_ACPI_GPE0_STS_127_96_PME_B0);
if (Data32 != 0) {
//
// Check if Internal LAN waked up system
//
LanBaseAddress = MmPciBase (
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_LAN,
PCI_FUNCTION_NUMBER_PCH_LAN
);
LanPmcs = MmioRead16 (LanBaseAddress + R_PCH_LAN_PMCS);
if ((LanPmcs & B_PCH_LAN_PMCS_PMES) != 0) {
//
// Clear PMES bit
//
MmioOr16 (LanBaseAddress + R_PCH_LAN_PMCS, B_PCH_LAN_PMCS_PMES);
DEBUG ((DEBUG_INFO, "Clear LAN PMES bit!\n"));
}
}
LpcDeviceId = GetLpcDid ();
//
// Clear any SMI or wake state from the boot
//
Pm1Sts |=
(
B_PCH_ACPI_PM1_STS_WAK |
B_PCH_ACPI_PM1_STS_PRBTNOR |
B_PCH_ACPI_PM1_STS_RTC |
B_PCH_ACPI_PM1_STS_PWRBTN |
B_PCH_ACPI_PM1_STS_GBL |
B_PCH_ACPI_PM1_STS_TMROF
);
Gpe0Sts |=
(
B_PCH_ACPI_GPE0_STS_127_96_PME_B0 |
B_PCH_ACPI_GPE0_STS_127_96_PME |
B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP |
B_PCH_ACPI_GPE0_STS_127_96_RI |
B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK |
B_PCH_ACPI_GPE0_STS_127_96_TC0SCI |
B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG |
B_PCH_ACPI_GPE0_STS_127_96_LAN_WAKE
);
//
// PCH Desktop
//
if (IS_PCH_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) {
Gpe0Sts |= B_PCH_ACPI_GPE0_STS_127_96_BATLOW;
}
SmiSts |=
(
B_PCH_SMI_STS_SMBUS |
B_PCH_SMI_STS_PERIODIC |
B_PCH_SMI_STS_TCO |
B_PCH_SMI_STS_MCSMI |
B_PCH_SMI_STS_SWSMI_TMR |
B_PCH_SMI_STS_APM |
B_PCH_SMI_STS_ON_SLP_EN |
B_PCH_SMI_STS_BIOS
);
//
// Write them back
//
IoWrite16 (ABase + R_PCH_ACPI_PM1_STS, Pm1Sts);
IoWrite32 (ABase + R_PCH_ACPI_GPE0_STS_127_96, Gpe0Sts);
IoWrite32 (ABase + R_PCH_SMI_STS, SmiSts);
DevActSts = IoRead16 (ABase + R_PCH_DEVACT_STS);
Tco1Sts = IoRead16 (TcoBase + R_PCH_TCO1_STS);
DevActSts |=
(
B_PCH_DEVACT_STS_KBC |
B_PCH_DEVACT_STS_PIRQDH |
B_PCH_DEVACT_STS_PIRQCG |
B_PCH_DEVACT_STS_PIRQBF |
B_PCH_DEVACT_STS_PIRQAE
);
Tco1Sts |=
(
B_PCH_TCO1_STS_DMISERR |
B_PCH_TCO1_STS_DMISMI |
B_PCH_TCO1_STS_DMISCI |
B_PCH_TCO1_STS_BIOSWR |
B_PCH_TCO1_STS_NEWCENTURY |
B_PCH_TCO1_STS_TIMEOUT |
B_PCH_TCO1_STS_TCO_INT |
B_PCH_TCO1_STS_SW_TCO_SMI
);
//
// clear GPI SMI STS
//
GpioClearAllGpiSmiSts ();
IoWrite16 (TcoBase + R_PCH_TCO1_STS, Tco1Sts);
//
// We do not want to write 1 to clear INTRD_DET bit.
//
IoWrite16 ((UINTN) (TcoBase + R_PCH_TCO2_STS), (UINT16) ~B_PCH_TCO2_STS_INTRD_DET);
IoWrite16 (ABase + R_PCH_DEVACT_STS, DevActSts);
//
// Clear Power Failure (PWR_FLR), It was used to check S3_Resume State.
//
// MmioOr8 (
// LpcBaseAddress + R_PCH_PMC_GEN_PMCON_B,
// B_PCH_PMC_GEN_PMCON_B_PWR_FLR
// );
return EFI_SUCCESS;
}
/**
Late Silicon Initialization
**/
VOID
LateSiliconInit (
VOID
)
{
ClearIchSmiAndWake ();
}