/** @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 (); }