/** @file Initializes PCH power management features. @copyright Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved This software and associated documentation (if any) is furnished under a license and may only be used or copied in accordance with the terms of the license. Except as permitted by such license, no part of this software or documentation may be reproduced, stored in a retrieval system, or transmitted in any form or by any means without the express written consent of Intel Corporation. This file contains an 'Intel Peripheral Driver' and uniquely identified as "Intel Reference Module" and is licensed for Intel CPUs and chipsets under the terms of your license agreement with Intel or your vendor. This file may be modified by the user, subject to additional terms of the license agreement **/ #include "PchInit.h" /** Set an PCH IOBP programming S3 dispatch item, this function may assert if any error happend @param[in] RootComplexBar RootComplexBar value of this PCH device @param[in] Address Address of the IOBP register block @param[in] AndMask Mask to AND with the register @param[in] OrMask Mask to OR with the register @retval EFI_SUCCESS The function completed successfully @retval EFI_OUT_OF_RESOURCES Out of resources @retval EFI_INVALID_PARAMETER Invalid parameter @retval EFI_NOT_FOUND Protocol interface not found **/ EFI_STATUS SetProgramIobpS3Item ( IN UINT32 RootComplexBar, IN UINT32 Address, IN UINT32 AndMask, IN UINT32 OrMask ) { EFI_STATUS Status; #ifdef EFI_S3_RESUME STATIC EFI_PCH_S3_SUPPORT_PROTOCOL *PchS3Support; STATIC EFI_PCH_S3_PARAMETER_PROG_IOBP S3ParameterProgramIobp; STATIC EFI_PCH_S3_DISPATCH_ITEM S3DispatchItem = { PchS3ItemTypeProgramIobp, &S3ParameterProgramIobp }; EFI_PHYSICAL_ADDRESS S3DispatchEntryPoint; if (!PchS3Support) { /// /// Get the PCH S3 Support Protocol /// Status = gBS->LocateProtocol ( &gEfiPchS3SupportProtocolGuid, NULL, (VOID **) &PchS3Support ); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { return Status; } } S3ParameterProgramIobp.RootComplexBar = RootComplexBar; S3ParameterProgramIobp.Address = Address; S3ParameterProgramIobp.AndMask = AndMask; S3ParameterProgramIobp.OrMask = OrMask; Status = PchS3Support->SetDispatchItem ( PchS3Support, &S3DispatchItem, &S3DispatchEntryPoint ); ASSERT_EFI_ERROR (Status); /// /// Save the script dispatch item in the Boot Script /// SCRIPT_DISPATCH (EFI_ACPI_S3_RESUME_SCRIPT_TABLE, S3DispatchEntryPoint); #else Status = EFI_SUCCESS; #endif return Status; } /** Locking Thermal Reporting Settings @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance @param[in] GpioBase GPIO base address of this PCH device @retval EFI_SUCCESS The function completed successfully **/ EFI_STATUS ThermalLockDown ( IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, UINT16 GpioBase ) { UINTN PciD31F6RegBase; UINTN PciD31F2RegBase; UINT32 ThermalBaseB; UINT32 ThermalBase; EFI_PHYSICAL_ADDRESS MemBaseAddress; EFI_STATUS Status; UINT8 Index; UINT8 RegData8; UINT16 RegData16; UINT32 RegData32; UINT32 RootComplexBar; UINT32 Data32And; UINT32 Data32Or = 0; UINT16 Data16And; UINT16 Data16Or; UINT32 PchTTLevels = 0; BOOLEAN PchHotEnable; PCH_SERIES PchSeries; EFI_CPUID_REGISTER Cpuid; MSR_REGISTER TempMsr; UINT32 temperature; UINT8 MaxSataPortNum; DEBUG ((EFI_D_INFO, "ThermalLockDown() Start\n")); PchSeries = GetPchSeries(); /// /// Check if TBARB is already initialized by platform code /// PciD31F6RegBase = MmPciAddress ( 0, PchPlatformPolicy->BusNumber, PCI_DEVICE_NUMBER_PCH_THERMAL, PCI_FUNCTION_NUMBER_PCH_THERMAL, 0 ); PciD31F2RegBase = MmPciAddress ( 0, PchPlatformPolicy->BusNumber, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA, 0 ); RootComplexBar = PCH_RCRB_BASE; ThermalBaseB = MmioRead32 (PciD31F6RegBase + R_PCH_THERMAL_TBARB); MemBaseAddress = 0x0ffffffff; if (ThermalBaseB & B_PCH_THERMAL_SPTYPEN) { /// /// Check if TBARB is already initialized and if so use it. /// ThermalBaseB &= B_PCH_THERMAL_TBARB_MASK; } else { #ifndef AMI_OVERRIDE_FOR_PCH Status = gDS->AllocateMemorySpace ( EfiGcdAllocateMaxAddressSearchTopDown, EfiGcdMemoryTypeMemoryMappedIo, N_PCH_THREMAL_TBARB_ALIGNMENT, V_PCH_THERMAL_TBARB_SIZE, &MemBaseAddress, mImageHandle, NULL ); #else Status = gDS->AllocateMemorySpace ( EfiGcdAllocateMaxAddressSearchBottomUp, EfiGcdMemoryTypeMemoryMappedIo, N_PCH_THREMAL_TBARB_ALIGNMENT, V_PCH_THERMAL_TBARB_SIZE, &MemBaseAddress, mImageHandle, NULL ); #endif if (EFI_ERROR (Status)) { return Status; } ThermalBaseB = (UINT32) MemBaseAddress; MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBARB, ThermalBaseB); MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBARBH, 0); MmioOr32 (PciD31F6RegBase + R_PCH_THERMAL_TBARB, (UINT32) B_PCH_THERMAL_SPTYPEN); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARB), 1, (VOID *) (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARB) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARBH), 1, (VOID *) (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARBH) ); } /// /// PCH BIOS Spec Rev 0.5.0, 17.3.1 Initializing Lynx Point Thermal Sensors /// Step 1 /// TSC must then be written to 0x81 to enable the power down and lock the register. /// RegData8 = MmioRead8 (ThermalBaseB + R_PCH_TBARB_TSC); /// /// Enable Catastrophic Power Down /// RegData8 |= (UINT8) B_PCH_TBARB_TSC_CPDE; /// /// Step 8.1 /// It is recommended that TSC [7] set to 1 to lock the CAT Trip behavior. /// if (PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.TscLock == PCH_DEVICE_ENABLE) { RegData8 |= (UINT8) B_PCH_TBARB_TSC_PLD; } MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSC, RegData8); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (ThermalBaseB + R_PCH_TBARB_TSC), 1, (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSC) ); /// /// Step 8.2 /// TSMIC [7] locks SMI reporting of thermal events /// if (PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.TsmicLock == PCH_DEVICE_ENABLE) { MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSMIC, 0x80); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (ThermalBaseB + R_PCH_TBARB_TSMIC), 1, (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSMIC) ); } /// /// Step 5 /// If the PCH_Hot pin reporting is supported, then write the temperature value and set the enable in PHL. /// PchHotEnable = FALSE; #ifdef TRAD_FLAG if (PchSeries == PchH) { /// /// Note: For PCHHOT# support, we need to make sure if GPIO74 is set to native mode and PCHSTRP9[22] is /// set to 1. /// Check if GPIO74 is set to native mode. /// RegData8 = (UINT8)((IoRead32 ((UINTN) (GpioBase + R_PCH_GPIO_USE_SEL3)) & BIT10) >> 10); } #endif // TRAD_FLAG #ifdef ULT_FLAG if (PchSeries == PchLp) { /// /// Note: For PCHHOT# support, we need to make sure if GPIO73 is set to native mode and PCHSTRP9[22] is /// set to 1. /// Check if GPIO73 is set to native mode. /// RegData8 = (UINT8)(IoRead32 ((UINTN) (GpioBase + R_PCH_GP_73_CONFIG0)) & B_PCH_GPIO_OWN0_GPIO_USE_SEL); } #endif // ULT_FLAG if(RegData8 == 0x00) { /// /// Check if PCHSTRP9[22] is set to 1 (PCHHOT# is the native functionality of GPIO74) /// if ((MmioRead16 (RootComplexBar + R_PCH_SPI_HSFS) & B_PCH_SPI_HSFS_FDV) == B_PCH_SPI_HSFS_FDV) { MmioAnd32 ((RootComplexBar + R_PCH_SPI_FDOC), (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK))); MmioOr32 ((RootComplexBar + R_PCH_SPI_FDOC), (UINT32) (V_PCH_SPI_FDOC_FDSS_PCHS | R_PCH_SPI_STRP9)); if (MmioRead32 (RootComplexBar + R_PCH_SPI_FDOD) & B_PCH_SPI_STRP9_HOT_SML1_SEL) { PchHotEnable = TRUE; } } } /// /// The value in PHL register is valid only if it is between 00h and 1FFh. /// if ((PchHotEnable == TRUE) && (PchPlatformPolicy->ThermalConfig->PchHotLevel < 0x0200)) { /// /// Program PHL register according to PchHotLevel setting. /// RegData16 = (PchPlatformPolicy->ThermalConfig->PchHotLevel | B_PCH_TBARB_PHLE); MmioWrite16 (ThermalBaseB + R_PCH_TBARB_PHL, RegData16); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint16, (UINTN) (ThermalBaseB + R_PCH_TBARB_PHL), 1, &RegData16 ); } /// /// Step 8.3 /// PHLC [0] locks the PHL and PHLC registers for PCH_Hot# /// if (PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.PhlcLock == PCH_DEVICE_ENABLE) { MmioWrite8 (ThermalBaseB + R_PCH_TBARB_PHLC, 0x01); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (ThermalBaseB + R_PCH_TBARB_PHLC), 1, (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_PHLC) ); } /// /// PCH BIOS Spec Rev 0.5.0, Section 17.5 Thermal Throttling /// Step 1 /// Additional programming to initialize Thermal Throttle device /// For LPT-H, /// a. Program ThermalBAR + 0xC0 to 8000390Bh /// b. Program ThermalBAR + 0xC4 to C11F0201h /// c. Program ThermalBAR + 0xC8 to 05800000h /// d. Program ThermalBAR + 0xCC to 0000C000h /// e. Program ThermalBAR + 0xD0 to 00000320h /// f. Program ThermalBAR + 0xE0 to 80001E4Fh /// g. Program ThermalBAR + 0xF0 to 00000003h /// For LPT-LP, /// a. Program ThermalBar + 0xC0 to 8000390Bh /// b. Program ThermalBar + 0xC4 to C11F0401h /// c. Program ThermalBAR + 0xC8 to 05800000h /// d. Program ThermalBar + 0xCC to 0000C000h /// e. Program ThermalBar + 0xD0 to 00000320h /// f. Program ThermalBar + 0xE0 to 80001EDCh /// g. Program ThermalBar + 0xF0 to 00000003h /// if (PchSeries == PchH) { MmioWrite32 (ThermalBaseB + 0xC4, 0xC11F0201); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + 0xC4), 1, (VOID *) (UINTN) (ThermalBaseB + 0xC4) ); MmioWrite32 (ThermalBaseB + 0xE0, 0x80001E4F); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + 0xE0), 1, (VOID *) (UINTN) (ThermalBaseB + 0xE0) ); } if (PchSeries == PchLp) { MmioWrite32 (ThermalBaseB + 0xC4, 0xC11F0401); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + 0xC4), 1, (VOID *) (UINTN) (ThermalBaseB + 0xC4) ); MmioWrite32 (ThermalBaseB + 0xE0, 0x80001EDC); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + 0xE0), 1, (VOID *) (UINTN) (ThermalBaseB + 0xE0) ); } MmioWrite32 (ThermalBaseB + 0xC0, 0x8000390B); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + 0xC0), 1, (VOID *) (UINTN) (ThermalBaseB + 0xC0) ); MmioWrite32 (ThermalBaseB + 0xC8, 0x05800000); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + 0xC8), 1, (VOID *) (UINTN) (ThermalBaseB + 0xC8) ); MmioWrite32 (ThermalBaseB + 0xCC, 0x0000C000); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + 0xCC), 1, (VOID *) (UINTN) (ThermalBaseB + 0xCC) ); MmioWrite32 (ThermalBaseB + 0xD0, 0x00000320); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + 0xD0), 1, (VOID *) (UINTN) (ThermalBaseB + 0xD0) ); MmioWrite32 (ThermalBaseB + 0xF0, 0x00000003); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + 0xF0), 1, (VOID *) (UINTN) (ThermalBaseB + 0xF0) ); /// /// HSW BWG 15.8 : Processor PCH-LP cross throttling /// if (PchSeries == PchLp){ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx); if (((Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL) == CPUID_FULL_FAMILY_MODEL_HASWELL_ULT) && ((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.PchCrossThrottling == PCH_DEVICE_ENABLE) || (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.SuggestedSetting == PCH_DEVICE_ENABLE))) { // // Read MSR 0x1A2 TEMPERATURE_TARGET // TempMsr.Qword = AsmReadMsr64 (MSR_TEMPERATURE_TARGET); /// /// Tcc activation offset in temperature target MSR changes from 4 bits [27:24] to 6 bits [29:24] on ULT C step onwards /// since Tcc will never be more than 205C, thus the calculation for PHL will never overflow /// if ((Cpuid.RegEax & CPUID_FULL_STEPPING) >= EnumHswUltC0) { temperature = (TempMsr.Bytes.ThirdByte - (TempMsr.Bytes.FouthByte & 0x3F)); } else { temperature = (TempMsr.Bytes.ThirdByte - (TempMsr.Bytes.FouthByte & 0xF)); } if (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.SuggestedSetting == PCH_DEVICE_ENABLE) { /// /// PCH T0/T1/T2 Level (MMIO TBARB+40h) : /// T0L = (((MSR TEMPERATURE_TARGET[23:16] - TEMPERATURE_TARGET) + 50) * 2) /// T1L = T0L + 5C /// T2L = T1L + 5C /// PchTTLevels = (UINT32)((( temperature + 10 + 50) * 2) << 20) | (UINT32)(((temperature + 5 + 50) * 2) << 10) | (UINT32)((temperature + 50) * 2); Data32Or = BIT31 | BIT29; } else { PchTTLevels = (UINT32) (((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T2Level + 10 + 50) * 2) << 20) | (UINT32) (((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T1Level + 5 + 50) * 2) << 10) | (UINT32) ((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T0Level + 50) * 2); Data32Or = (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTLock << 31) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTState13Enable << 30) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTEnable << 29); } } } else if (PchSeries == PchH) { if (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.SuggestedSetting == PCH_DEVICE_ENABLE) { /// /// Set TBARB + 40h = 0B485093Ch /// Program TBARB + 40h[31:28] in separate write /// PchTTLevels = 0xB485093C; Data32Or = BIT31 | BIT29; }else { /// /// PCH BIOS Spec Rev 0.5.5, Section 17.3.1 Initializing Lynx Point Thermal Sensors /// Trip Point Temperature = (Trip Point Register [8:0]) / 2 - 50 centigrade degree /// If Trip Point Temperature <= T0Level, the system will be in T0 state. /// If T1Level >= Trip Point Temperature > T0Level, the system will be in T1 state. /// If T2Level >= Trip Point Temperature > T1Level, the system will be in T2 state. /// If Trip Point Temperature > T2Level, the system will be in T3 state. /// PchTTLevels = (UINT32) (((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T2Level + 50) * 2) << 20) | (UINT32) (((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T1Level + 50) * 2) << 10) | (UINT32) ((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.T0Level + 50) * 2); Data32Or = (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTLock << 31) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTState13Enable << 30) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.TTEnable << 29); } } /// /// Program TBARB + 40h[27:0] /// MmioWrite32 (ThermalBaseB + R_PCH_TBARB_TL, PchTTLevels); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + R_PCH_TBARB_TL), 1, (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TL) ); /// /// Program TBARB + 40h[31:28] /// /// PCH BIOS Spec Rev 0.5.0, 17.3.1 Initializing Lynx Point Thermal Sensors /// Step 8.4 /// TL [31] locks the thermal throttling registers /// MmioOr32 (ThermalBaseB + R_PCH_TBARB_TL, Data32Or); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (ThermalBaseB + R_PCH_TBARB_TL), 1, (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TL) ); if (PchSeries == PchLp) { /// /// Processor PCH-LP cross throttling - Set RCBA MMIO offset 0x33C4[26:24] = 101b /// AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx); if (((Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL) == CPUID_FULL_FAMILY_MODEL_HASWELL_ULT) && ((PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.PchCrossThrottling == PCH_DEVICE_ENABLE) || (PchPlatformPolicy->ThermalConfig->ThermalThrottling.TTLevels.SuggestedSetting == PCH_DEVICE_ENABLE))) { Data32And = (UINT32)~(BIT26 | BIT25 | BIT24); Data32Or = BIT26 | BIT24; MmioAndThenOr32 ((UINTN) (RootComplexBar + PMSYNC_TPR_CONFIG), Data32And, Data32Or); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + PMSYNC_TPR_CONFIG), 1, (VOID *) (UINTN) (RootComplexBar + PMSYNC_TPR_CONFIG) ); } /// /// Lock PMSYNC_TPR_CFG and PMSYNC_TPR_CFG2 /// Set RCBA + 0x33C4[31] = 1b. /// MmioOr32 (RootComplexBar + PMSYNC_TPR_CONFIG,B_PMSYNC_TPR_CONFIG_LOCK); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + PMSYNC_TPR_CONFIG), 1, (VOID *) (UINTN) (RootComplexBar + PMSYNC_TPR_CONFIG) ); } if (PchSeries == PchH) { /// /// PCH BIOS Spec Rev 0.5.0, Section 17.5 Thermal Throttling /// Step 3 /// Set Chipset Initialization Register 30 (RCBA + 2238h) = 00000941h /// if (PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.SuggestedSetting == PCH_DEVICE_ENABLE) { RegData32 = 0x00000941; } else { RegData32 = (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS3TW << 10) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS2TW << 8) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS1TW << 6) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.TS0TW << 4) | (UINT32) PchPlatformPolicy->ThermalConfig->ThermalThrottling.DmiHaAWC.DmiTsawEn; } /// /// If DMI IOT is enabled, set chipset Initialization Register 30 (RCBA + 2238h) = 00000551h /// if (PchPlatformPolicy->DmiConfig->DmiIot == PCH_DEVICE_ENABLE) { RegData32 = 0x00000551; } MmioWrite32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238), RegData32); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238) ); } /// /// Step 4 /// Program SATA Indexed Register Index and Data: /// a. If port 0 is empty, set D31:F2:A0h=A0h and D31:F2:A4h[15:00] = 0000h /// else if Port 0 has a HDD, set D31:F2:A4h[15:00] = 0039h /// else if Port 0 has a SSD, set D31:F2:A4h[15:00] = 0F39h /// b. If port 1 is empty, set D31:F2:A0h=A0h and D31:F2:A4h[31:16] = 0000h /// else if Port 1 has a HDD, set D31:F2:A4h[31:16] = 0039h /// else if Port 1 has a SSD, set D31:F2:A4h[31:16] = 0F39h /// c. If port 2 is empty, set D31:F2:A0h=A4h and D31:F2:A4h[15:00] = 0000h /// else if Port 2 has a HDD, set D31:F2:A4h[15:00] = 0039h /// else if Port 2 has a SSD, set D31:F2:A4h[15:00] = 0F39h /// d. If port 3 is empty, set D31:F2:A0h=A4h and D31:F2:A4h[31:16] = 0000h /// else if Port 3 has a HDD, set D31:F2:A4h[31:16] = 0039h /// else if Port 3 has a SSD, set D31:F2:A4h[31:16] = 0F39h /// e. If port 4 is empty, set D31:F2:A0h=A8h and D31:F2:A4h[15:00] = 0000h /// else if Port 4 has a HDD, set D31:F2:A4h[15:00] = 0039h /// else if Port 4 has a SSD, set D31:F2:A4h[15:00] = 0F39h /// f. If port 5 is empty, set D31:F2:A0h=A8h and D31:F2:A4h[31:16] = 0000h /// else if Port 5 has a HDD, set D31:F2:A4h[31:16] = 0039h /// else if Port 5 has a SSD, set D31:F2:A4h[31:16] = 0F39h /// MaxSataPortNum = GetPchMaxSataPortNum(); RegData16 = MmioRead16 (PciD31F2RegBase + R_PCH_SATA_PCS); for (Index = 0; Index < (MaxSataPortNum / 2); Index++) { Data32And = 0x70C070C0; Data32Or = 0x00000000; if (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.SuggestedSetting == PCH_DEVICE_ENABLE) { if ((RegData16 & (B_PCH_SATA_PCS_PORT0_DET << (Index * 2))) != 0) { Data32Or |= 0x00000039; if (PchPlatformPolicy->SataConfig->PortSettings[0 + (Index * 2)].SolidStateDrive == PCH_DEVICE_ENABLE) { Data32Or |= 0x00000F00; } } if ((RegData16 & (B_PCH_SATA_PCS_PORT0_DET << ((Index * 2) + 1))) != 0) { Data32Or |= 0x00390000; if (PchPlatformPolicy->SataConfig->PortSettings[1 + (Index * 2)].SolidStateDrive == PCH_DEVICE_ENABLE) { Data32Or |= 0x0F000000; } } } else { Data32Or = (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1TDispFinit << 31) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1Tinact << 26) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1TDisp << 24) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1T3M << 20) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1T2M << 18) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P1T1M << 16) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0TDispFinit << 15) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0Tinact << 10) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0TDisp << 8) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0T3M << 4) | (UINT32) (PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0T2M << 2) | (UINT32) PchPlatformPolicy->ThermalConfig->ThermalThrottling.SataTT.P0T1M; } MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, (0xA0 + (Index * 4))); MmioAndThenOr32 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), Data32And, Data32Or); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), 1, (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), 1, (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) ); } /// /// Program ThermalBar + 0xA4 [1:0] = 11b /// MmioOr8 (ThermalBaseB + 0xA4, (UINT8) (BIT1 | BIT0)); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (ThermalBaseB + 0xA4), 1, (VOID *) (UINTN) (ThermalBaseB + 0xA4) ); /// /// PCH BIOS Spec Rev 0.5.0, 17.3.1 Initializing Lynx Point Thermal Sensors /// Step 7 /// Enable thermal sensor by programming TSEL register to 01h /// This should be done after all thermal initialization steps are finished. /// RegData8 = MmioRead8 (ThermalBaseB + R_PCH_TBARB_TSEL); RegData8 |= (UINT8) B_PCH_TBARB_TSEL_ETS; /// /// Step 8.5 /// TSEL [7] locks the thermal sensor enable, after TAHV and TAHL are programmed by BIOS or driver /// later in case. /// if (PchPlatformPolicy->ThermalConfig->ThermalAlertEnable.TselLock == PCH_DEVICE_ENABLE) { RegData8 |= (UINT8) B_PCH_TBARB_TSEL_PLD; } MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSEL, RegData8); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (ThermalBaseB + R_PCH_TBARB_TSEL), 1, (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSEL) ); /// /// Step 8.6 /// Program ThermalBAR + 0x0A [7] = 1b /// For LP, Program ThermalBar + 0x0A [7, 0] = 1b, 1b /// RegData8 = BIT7; if (PchSeries == PchLp) { RegData8 |= BIT0; } MmioOr8 (ThermalBaseB + R_PCH_TBARB_TSREL, RegData8); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (ThermalBaseB + R_PCH_TBARB_TSREL), 1, (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSREL) ); /// /// For LP, Program ThermalBar + 0x1C [14:0] = 48C8h /// For LP, Program ThermalBar + 0x1C [15] = 1h /// if (PchSeries == PchLp) { Data16And = (B_PCH_TBARB_TSPM_LTT | B_PCH_TBARB_TSPM_MAXTSST | B_PCH_TBARB_TSPM_MINTSST | B_PCH_TBARB_TSPM_DTSSIC0 | B_PCH_TBARB_TSPM_DTSSS0EN); Data16Or = (V_PCH_TBARB_TSPM_LTT | V_PCH_TBARB_TSPM_MAXTSST | B_PCH_TBARB_TSPM_DTSSS0EN); MmioAndThenOr16 (ThermalBaseB + R_PCH_TBARB_TSPM, (UINT16) Data16And, (UINT16) Data16Or); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint16, (UINTN) (ThermalBaseB + R_PCH_TBARB_TSPM), 1, (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSPM) ); MmioOr16 (ThermalBaseB + R_PCH_TBARB_TSPM, (UINT16) B_PCH_TBARB_TSPM_TSPMLOCK); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint16, (UINTN) (ThermalBaseB + R_PCH_TBARB_TSPM), 1, (VOID *) (UINTN) (ThermalBaseB + R_PCH_TBARB_TSPM) ); } /// /// PCH BIOS Spec Rev 0.5.0, Section 17.2, Thermal Subsystem Device Initialization /// Step 5 /// BIOS needs to perform the following steps prior to end of POST to free up the PCI resources /// and hide the thermal subsystem device(OPTIONAL), except on mobile platforms that support /// Intel DPPM. Also, BIOS may keep the TBARBH programmed if BIOS needs runtime access to PCH /// thermal subsystem device data. In that case, BIOS must ensure TBARBH memory is reserved and /// reported to the OS as motherboard resources to avoid memory allocation conflicts. /// if (PchPlatformPolicy->ThermalConfig->ThermalDeviceEnable == FALSE) { /// /// Step 5.1 /// Clear the Memory and Bus Master enable bit of D31:F6 /// MmioAnd16 ( PciD31F6RegBase + R_PCH_THERMAL_COMMAND, (UINT16)~(B_PCH_THERMAL_COMMAND_MSE | B_PCH_THERMAL_COMMAND_BME) ); /// /// Step 5.2 /// Clear and release memory resource assigned in TBAR (D31:F6:10h-13h) /// ThermalBase = MmioRead32 (PciD31F6RegBase + R_PCH_THERMAL_TBAR) & B_PCH_THERMAL_TBAR_MASK; if ((ThermalBase != 0) && (ThermalBase != B_PCH_THERMAL_TBAR_MASK)) { MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBAR, 0); MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBARH, 0); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBAR), 1, (VOID *) (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBAR) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARH), 1, (VOID *) (UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARH) ); gDS->FreeMemorySpace ( (EFI_PHYSICAL_ADDRESS) ThermalBase, V_PCH_THERMAL_TBAR_SIZE ); } /// /// Step 5.3 /// Optionally, release and clear memory resource assigned in TBARB (D31:F6:40h-48h) if BIOS/ASL /// implementation does not require access to PCH thermal subsystem device data during run time. /// Left this to platform code /// /// Step 5.4 /// Hide D31:F6 PCI configuration space by setting FD.TTD (RCBA + 3418h[24]) /// Data32And = 0xFFFFFFFF; Data32Or = (UINT32) B_PCH_RCRB_FUNC_DIS_THERMAL; MmioOr32 (RootComplexBar + R_PCH_RCRB_FUNC_DIS, Data32Or); SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), &Data32Or, // Data to be ORed &Data32And // Data to be ANDed ); /// /// Reads back for posted write to take effect /// Data32Or = MmioRead32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS)); SCRIPT_MEM_POLL ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), &Data32Or, // BitMask &Data32Or, // BitValue 1, // Duration 1 // LoopTimes ); } DEBUG ((EFI_D_INFO, "ThermalLockDown() End\n")); return EFI_SUCCESS; } /** Perform Clock Gating programming Enables clock gating in various PCH interfaces and the registers must be restored during S3 resume. @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance @param[in] RootComplexBar RootComplexBar value of this PCH device @param[in] FuncDisableReg The Function Disable Register @retval EFI_SUCCESS The function completed successfully **/ EFI_STATUS ConfigureClockGating ( IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, IN UINT32 RootComplexBar, IN UINT32 FuncDisableReg ) { UINT8 RegData8; UINT32 RegData32; UINT32 RegDataOr32; UINT32 RegDataAnd32; UINTN PciD31F0RegBase; UINT16 LpcDeviceId; UINT16 Data16Or; PCH_SERIES PchSeries; UINT32 D2F0Base; DEBUG ((EFI_D_INFO, "ConfigureClockGating() Start\n")); PchSeries = GetPchSeries(); PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); /// /// PCH BIOS Spec Rev 0.5.5, section 19.10 /// 1 /// DMI interface /// Enable Dynamic Clock Gating in the DMIC register by programming /// For PCH LP /// RCBA + 2234h [2] to 1b, RCBA + 2234h [0] to 1b /// RCBA + 2234h [3:0] to 1111b /// Set D31:F0:A0h[5] = 1b /// Set D31:F0:A0h[6] = 1b /// Set D31:F0:A0h[7] = 1b /// Set D31:F0:A0h[11] = 0b /// Set D31:F0:A0h[12] = 1b /// For PCH H /// RCBA + 2234h [3:0] to 1111b /// Enable Dynamic Clock Gating in the DMIC register by programming RCBA + 2234h [3:0] to 1111b /// before enabling ASPM. /// Set D31:F0:A0h[11] = 1b /// Set D31:F0:A0h[12] = 1b /// Set D31:F0:A0h[14] = 1b. /// System BIOS is also required to set following bit. /// Dekstop: "Pseudo CLKRUN_EN (PSEUDO_CLKRUN_EN)" bit (D31:F0:A0h[3]) = 1b /// Mobile: "PCI CLKRUN# Enable" bit (D31:F0:A0h[2]) = 1b /// switch (PchSeries) { case PchLp: MmioOr8 ((UINTN) (RootComplexBar + R_PCH_RCRB_DMIC), (UINT8) (B_PCH_LP_RCRB_DMIC_DMICGEN)); break; case PchH: MmioOr8 ((UINTN) (RootComplexBar + R_PCH_RCRB_DMIC), (UINT8) (B_PCH_H_RCRB_DMIC_DMICGEN)); break; default: break; } if (PchSeries == PchLp) { Data16Or = (UINT16)(BIT12 | BIT7 | BIT6 | BIT5); Data16Or |= BIT11; MmioOr16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), Data16Or); } else if (PchSeries == PchH) { MmioOr16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), (UINT16) (BIT14 | BIT12 | BIT11)); } if (PchPlatformPolicy->DeviceEnabling->PciClockRun == PCH_DEVICE_DISABLE) { if (IS_PCH_LPT_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) { MmioAnd16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), (UINT16) (~B_PCH_LPC_GEN_PMCON_CLKRUN_EN)); } else { MmioAnd16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), (UINT16) (~B_PCH_LPC_GEN_PMCON_PSEUDO_CLKRUN_EN)); } } else { if (IS_PCH_LPT_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) { MmioOr16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), (UINT16) (B_PCH_LPC_GEN_PMCON_CLKRUN_EN)); } else { MmioOr16 ((UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), (UINT16) (B_PCH_LPC_GEN_PMCON_PSEUDO_CLKRUN_EN)); } } RegData8 = MmioRead8 (RootComplexBar + R_PCH_RCRB_DMIC); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (RootComplexBar + R_PCH_RCRB_DMIC), 1, &RegData8 ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint16, (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1), 1, (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_1) ); if (PchSeries == PchLp) { /// /// Set RCBA + 2614h[27:25],[14:13],[10],[8] = 101b, 11b, 1b, 1b respectively /// Set RCBA + 2614h[23:16] = 0x20 /// Set RCBA + 2614h[30:28] = 0b /// Set RCBA + 2614h[26] = 1b if D2F0+8 >= 0x0B /// D2F0Base = MmPciAddress (0, 0, 2, 0, 0); RegDataAnd32 = (UINT32) ~(BIT30 | BIT29 | BIT28 | BIT26 | 0x00FF0000); RegDataOr32 = (UINT32) (BIT27 | BIT25 | BIT21 | BIT14 | BIT13 | BIT10 | BIT8); if ((MmioRead16 (D2F0Base) != 0xFFFF) && (MmioRead8 (D2F0Base + 8) >= 0x0B)) { RegDataOr32 |= (UINT32) BIT26; } MmioAndThenOr32 ( (UINTN) (RootComplexBar + 0x2614), RegDataAnd32, RegDataOr32 ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2614), 1, (VOID *) (UINTN) (RootComplexBar + 0x2614) ); /// /// Set Chipset Initialization Register 2 [4:0] (RCBA + 900h) = 11111b /// Set Chipset Initialization Register 2 [9:8] (RCBA + 900h) = 11b /// MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900), (UINT32) (BIT9 | BIT8 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900) ); } else if (PchSeries == PchH) { /// /// Set Chipset Initialization Register 2 [14] (RCBA + 900h) = 1b /// MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900), (UINT32) (BIT14) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR0900) ); } /// /// 2 /// PCI Express* interface /// 2.1 /// For each enabled PCI Express* root port, program D28:F0~F7:Reg E1h[1:0] to 3h to enable dynamic clock gating. /// System BIOS also require to set D28:F0~F7:Reg E8h[0] = 1b /// 2.2 /// Additionally, if port 0 is in x2 mode, these bits should not be set for port 1. /// Likewise, if port 0 is in x4 mode, these bits should not be set for ports 1, 2, or 3 /// Done in PchRootPorts.c PcieEnableClockGating /// 2.2.1 /// If PCIe root ports 0-3 are all disabled, set B0:D28:F0 + E2h[0] = 1b /// if PCIe root ports 4-7 are all disabled, set B0:D28:F4 + E2h[0] = 1b /// 2.3 /// Set B0:D28:F0&F4 + E1h [5:2] = 1111b /// 2.4 /// Set B0:D28:F0&F4:E1h[7] = 1b /// 2.6 /// Set B0:D28:F0~F7 + 324h[5] = 1b /// Done in PchRootPorts.c PcieEnableClockGating /// /// Reg RCBA+341C is modified at multiple places, save at the end of the function /// /// 3 /// Serial ATA* /// - Set bits D31:F2:94h[29:24] to 3Fh as part of the chipset initialization before disabling /// the SATA function when the SATA interface is not supported on the platform. BIOS can also /// set PCD bits to disable clocks for the un-routed ports on the platform. /// - After configuring Port and Control Status (PCS) Register Port x Enabled (PxE) bits accordingly, /// wait 1.4 micro second, then the PCD bits (D31:F2:Reg 94h[29:24]) should be set to be the inverse /// of the Port and Control Status (PCS) Register Port x Enabled (PxE) bits /// Please note that PCS should be set and PCD should not be set when ports are enabled for hot /// plug support or used for SATA testing in test mode. /// Done in ConfigureSata(); /// - Program D31:F2:98h[29] to 1b /// Done in PchInitBeforeBoot() /// - Set SATA Initialization Register 70h[31:0] = 3F00BF1Fh (Done in ConfigureMiscPm) /// Set SATA Initialization Register 54h[31:0] = CF000F0Fh (Done in ConfigureMiscPm) /// Set SATA Initialization Register 58h[31:0] = 190000h (Done in ConfigureMiscPm) /// /// 4 /// USB 1.1 / USB 2.0 / USB 3.0 /// /// ConfigureUsbClockGating() has been moved to ConfigureMiscPm() to run before Function Disable /// /// 5 /// Intel High Definition Audio (HDA) controller. /// if (FuncDisableReg & B_PCH_RCRB_FUNC_DIS_AZALIA) { /// /// 5.1 /// If the HD Audio Controller is not being used, D27:F0 can be disabled and statically gated. Only statically /// gate the Intel High Definition Audio controller if it is not being used in the system by setting RCBA + 341Ch[21]. /// MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_SCG_HDA)); } else { /// /// 5.2 /// When the Intel High Definition Audio controller is used in the system, /// dynamic clock gating can be used by setting RCBA + 341Ch[22]. /// MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_DCG_HDA)); } if (PchSeries == PchLp) { /// /// For PchLp, set RCBA + 341Ch[22] /// MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_DCG_HDA)); /// /// 5.3 /// Set D27:F0:43h[6:5][2:0] = 11b, 111b (Done in ConfigureMiscPm) /// } /// /// Reg RCBA+341C is modified at multiple places, save at the end of the function /// /// 7 /// LPC. /// Enable dynamic clock gating by setting RCRB+341C[31] to 1b. /// MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_DCG_LPC)); if (PchSeries == PchH) { /// /// Reg RCBA+341C is modified at multiple places, save at the end of the function /// /// 8 /// PCI Interface. /// Enable PCI dynamic clock gating by setting RCBA + 341Ch[16]. /// MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_DCG_PCI)); } else if (PchSeries == PchLp) { /// /// Set RCRB+341Ch[30][28:26] to 1b, 111b /// MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_DCG_BLA | B_PCH_RCRB_CG_EN_DCG_GPIO | B_PCH_RCRB_CG_EN_DCG_HPET | B_PCH_RCRB_CG_EN_CG_GPEC)); /// /// Set RCRB+3434h[2:0] to 111b /// MmioOr8 ( (UINTN) (RootComplexBar + 0x3434), (UINT8) (BIT2 | BIT1 | BIT0) ); RegData8 = MmioRead8 (RootComplexBar + 0x3434); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (RootComplexBar + 0x3434), 1, &RegData8 ); /// /// If RCRB+3454h[4] is 0b, then set RCRB+341C[29] to 1b, else set RCRB+341C[29] to 0b /// if ((MmioRead32 (RootComplexBar + R_PCH_RCRB_GSX_CTRL) & B_PCH_RCRB_GSX_BAR_ENABLE) == 0) { MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_SCG_GSX)); } else { MmioAnd32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (~B_PCH_RCRB_CG_EN_SCG_GSX)); } } /// /// PCH BIOS Spec Rev 0.5.0, Section 10.2.1/10.2.2 Enable/Disable the GbE Clock Gating /// Set RCBA + 341Ch[23] /// if (PchPlatformPolicy->DeviceEnabling->Lan == PCH_DEVICE_ENABLE) { MmioAnd32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (~B_PCH_RCRB_CG_EN_SCG_LAN)); } else { MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_SCG_LAN)); } if (PchSeries == PchLp) { /// /// 9 /// SPI Clock gating. /// Enable SPI clock gating by programming RCBA + 38C0h [13:10][2:0] to 1111b, 111b /// MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_SPI_AFC), (UINT32) (BIT13 | BIT12 | BIT11 | BIT10 | B_PCH_SPI_AFC_INF_DCGE | B_PCH_SPI_AFC_CORE_DCGE) ); RegData32 = MmioRead32 (RootComplexBar + R_PCH_SPI_AFC); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_SPI_AFC), 1, &RegData32 ); } else if (PchSeries == PchH) { /// /// 9 /// SPI Clock gating. /// Enable SPI clock gating by programming RCBA + 38C0h [2:0] to 111b /// MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_SPI_AFC), (UINT32) (B_PCH_SPI_AFC_INF_DCGE | B_PCH_SPI_AFC_CORE_DCGE) ); RegData32 = MmioRead32 (RootComplexBar + R_PCH_SPI_AFC); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_SPI_AFC), 1, &RegData32 ); } /// /// 10 /// SMBus /// Enable SMBus dynamic clock gating by setting D31:F3:80h [8, 10, 12 and 14] = 0b respectively (Done in ConfigureMiscPm) /// /// /// PCH BIOS Spec Rev 0.5.5, section 19.10 /// 11 /// Misc /// Set D31:F2:300h [17:16] = 11b (Done in ConfigureMiscPm) /// if (PchSeries == PchLp) { /// /// Set D31:F2:98h [31:30], [23] to 00b, 1b (Done in ConfigureMiscPm) /// /// Set iobp register CE00C000h[0] to 0b /// ProgramIobpWithScript ( RootComplexBar, 0xCE00C000, (UINT32)~(BIT0), 0 ); /// /// Disable legacy DMA (8237) if desired /// Set RCBA + Offset 0x341C[24] = 1 /// if ((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_4) && PchPlatformPolicy->PwrOptConfig->LegacyDmaDisable) { MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CG), (UINT32) (B_PCH_RCRB_CG_EN_SCG_8237)); } } /// /// Save 341C value to the S3 script table. This register is modified at multiple places in this function. So instead of saving /// at each location read the value once at the end of the function and save in S3 resume script. /// RegData32 = MmioRead32 (RootComplexBar + R_PCH_RCRB_CG); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CG), 1, &RegData32 ); DEBUG ((EFI_D_INFO, "ConfigureClockGating() End\n")); return EFI_SUCCESS; } /** Configure miscellaneous power management settings @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance @param[in] RootComplexBar RootComplexBar value of this PCH device @param[in] GpioBase GPIO base address of this PCH device @retval EFI_SUCCESS The function completed successfully **/ EFI_STATUS ConfigureMiscPm ( IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, IN UINT32 RootComplexBar, IN UINT16 GpioBase ) { UINT8 Data8Or; UINT8 Data8And; UINT32 RegData32; UINT16 RegData16; UINT32 RegData32Tmp; UINTN PciD31F0RegBase; UINTN PciD31F3RegBase; UINTN PciD31F2RegBase; UINT16 LpcDeviceId; UINTN PciD27F0RegBase; PCH_SERIES PchSeries; UINT32 DsxCfg; DEBUG ((EFI_D_INFO, "ConfigureMiscPm() Start\n")); PchSeries = GetPchSeries(); PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); PciD31F3RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 3, 0); PciD31F2RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 2, 0); LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); PciD27F0RegBase = 0; if (PchSeries == PchLp) { PciD27F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 27, 0, 0); } /// /// Clear power / reset status bits on PCH Corporate /// RegData32 = 0; if (PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeWakeSts) { RegData32 |= B_PCH_RCRB_PRSTS_ME_WAKE_STS; } if (PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeHrstColdSts) { RegData32 |= B_PCH_RCRB_PRSTS_ME_HRST_COLD_STS; } if (PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeHrstWarmSts) { RegData32 |= B_PCH_RCRB_PRSTS_ME_HRST_WARM_STS; } if (PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.MeHostPowerDn) { RegData32 |= B_PCH_RCRB_PRSTS_ME_HOST_PWRDN; } if (PchPlatformPolicy->MiscPmConfig->PowerResetStatusClear.WolOvrWkSts) { RegData32 |= B_PCH_RCRB_PRSTS_WOL_OVR_WK_STS; } MmioOr32 (RootComplexBar + R_PCH_RCRB_PRSTS, RegData32); RegData32Tmp = 0xFFFFFFFF; SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, RootComplexBar + R_PCH_RCRB_PRSTS, &RegData32, // OR mask &RegData32Tmp // AND mask ); /// /// We need to enable GP27_PIN_DSX_EN for Wake from both SX and DSX /// DsxCfg = MmioRead32(RootComplexBar + 0x3334); if (PchPlatformPolicy->MiscPmConfig->WakeConfig.Gp27WakeFromDeepSx == PCH_DEVICE_ENABLE) { DsxCfg |= BIT0; } else { DsxCfg &= ~BIT0; } /// /// Enable WAKE_PIN__DSX_EN for Wake /// if(PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_5) { if (PchPlatformPolicy->MiscPmConfig->WakeConfig.PcieWakeFromDeepSx == PCH_DEVICE_ENABLE) { DsxCfg |= BIT2; } else { DsxCfg &= ~BIT2; } } MmioWrite32 ((RootComplexBar + 0x3334), DsxCfg); /// /// Handle wake policy /// Don't need to record in S3 script as R_PCH_LPC_GEN_PMCON_3 is in RTC and SUS power well /// RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3) & (UINT16) (~(B_PCH_LPC_GEN_PMCON_PME_B0_S5_DIS + B_PCH_LPC_GEN_PMCON_WOL_ENABLE_OVERRIDE)); if (PchPlatformPolicy->MiscPmConfig->WakeConfig.PmeB0S5Dis) { RegData16 |= B_PCH_LPC_GEN_PMCON_PME_B0_S5_DIS; MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3, RegData16); } if (PchPlatformPolicy->MiscPmConfig->WakeConfig.WolEnableOverride) { /// /// PCH BIOS Spec Rev 0.5.0 Section 10.4 Wake-On-LAN (WOL) Implementation /// Step 1 /// Clear D31:F0:A2h[14] = 0b to ensure the LAN PHY will be powered for WOL /// when the power source is either the AC or the DC battery. /// RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2); RegData16 &= (UINT16) ~B_PCH_LPC_GEN_PMCON_DC_PP_DIS; /// /// Step 2 /// Clear D31:F0:A2h[13] = 0b to ensure the LAN PHY will be powered for WOL in Deep Sx. /// RegData16 &= (UINT16) ~B_PCH_LPC_GEN_PMCON_DSX_PP_DIS; /// /// Step 3 /// Set D31:F0:A2h[12] = 1b to ensure the LAN PHY will be powered for WOL after a G3 transition. /// RegData16 |= (UINT16) B_PCH_LPC_GEN_PMCON_AG3_PP_EN; /// /// Step 4 /// Set D31:F0:A2h[11] = 1b to ensure the LAN PHY will be powered for WOL from Sx. /// RegData16 |= (UINT16) B_PCH_LPC_GEN_PMCON_SX_PP_EN; MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2, RegData16); /// /// Step 5 /// "PME_B0_EN", PMBASE + Offset 28h[13], bit must be programmed to enable wakes /// from S1-S4 at the Power Management Controller /// Done in ASL code(_PRW) /// /// /// Step 6 /// Set "WOL Enable Override", D31:F0:A4h:[13], bit to 1b to guarantee the /// LAN-Wakes are enabled at the Power Management Controller, even in surprise /// S5 cases such as power loss/return and Power Button Override /// RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3); RegData16 |= (UINT16) B_PCH_LPC_GEN_PMCON_WOL_ENABLE_OVERRIDE; MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3, RegData16); /// /// Step 7 /// Moreover, system BIOS also require to enables in the LAN device by performing /// the WOL configuration requirements in the GbE region of the SPI flash. /// Done in PchSmmSxGoToSleep() SMM handler. /// } else { /// /// D31:F0:A2h[14:11] and D31:F0:A4h[13] are all in RTC or DSW well, so BIOS also /// needs to program them while WOL setup option is disabled. /// RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2); RegData16 |= (UINT16) (B_PCH_LPC_GEN_PMCON_DC_PP_DIS | B_PCH_LPC_GEN_PMCON_DSX_PP_DIS); RegData16 &= (UINT16) ~(B_PCH_LPC_GEN_PMCON_AG3_PP_EN | B_PCH_LPC_GEN_PMCON_SX_PP_EN); MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2, RegData16); RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3); RegData16 &= (UINT16) ~(B_PCH_LPC_GEN_PMCON_WOL_ENABLE_OVERRIDE); MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3, RegData16); } /// /// Configure On DC PHY Power Diable according to policy SlpLanLowDc. /// When this bit is set, SLP_LAN# will be driven low when ACPRESENT is low. /// This indicates that LAN PHY should be powered off on battery mode. /// This will override the DC_PP_DIS setting by WolEnableOverride. /// if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_7) { RegData16 = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2); if (PchPlatformPolicy->MiscPmConfig->SlpLanLowDc) { if ((RegData16 & B_PCH_LPC_GEN_PMCON_DC_PP_DIS) == 0) { RegData16 |= (UINT16) (B_PCH_LPC_GEN_PMCON_DC_PP_DIS); MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2, RegData16); } } else { if ((RegData16 & B_PCH_LPC_GEN_PMCON_DC_PP_DIS) != 0) { RegData16 &= (UINT16) ~(B_PCH_LPC_GEN_PMCON_DC_PP_DIS); MmioWrite16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_2, RegData16); } } } /// /// - Set SATA Initialization Register 70h[31:0] = 3F00BF1Fh /// MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x70); MmioWrite32 (PciD31F2RegBase + R_PCH_SATA_STRD, 0x3F00BF1F); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), 1, (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), 1, (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) ); if (PchSeries == PchLp) { /// /// Set SATA Initialization Register 54h[31:0] = CF000F0Fh /// MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x54); MmioWrite32 (PciD31F2RegBase + R_PCH_SATA_STRD, 0xCF000F0F); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), 1, (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), 1, (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) ); /// /// Set SATA Initialization Register 58h[31:0] = 190000h /// MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x58); MmioWrite32 (PciD31F2RegBase + R_PCH_SATA_STRD, 0x190000); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI), 1, (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_SIRI) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), 1, (VOID *) (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD) ); } /// /// 4 /// USB 1.1 / USB 2.0 / USB 3.0 /// ConfigureUsbClockGating (PchPlatformPolicy, RootComplexBar); if (PchSeries == PchLp) { /// /// 5.3 /// Set D27:F0:43h[6:5][3:0] = 11b, 111b /// Data8And = (UINT8) ~0x0; Data8Or = (BIT6 | BIT5 | BIT3 | BIT2 | BIT1 | BIT0); MmioOr8 ((UINTN) (PciD27F0RegBase + 0x43), Data8Or); SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (PciD27F0RegBase + 0x43), &Data8Or, // Data to be ORed &Data8And // Data to be ANDed ); } /// /// 10 /// SMBus /// Enable SMBus dynamic clock gating by setting D31:F3:80h [8, 10, 12 and 14] = 0b respectively /// MmioAnd16 ((UINTN) (PciD31F3RegBase + 0x80), (UINT16) ~(BIT14 | BIT12 | BIT10 | BIT8)); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint16, (UINTN) (PciD31F3RegBase + 0x80), 1, (VOID *) (UINTN) (PciD31F3RegBase + 0x80) ); /// /// PCH BIOS Spec Rev 0.5.5, section 19.10 /// 11 /// Misc /// /// Set D31:F2:300h [31:29] to 111b and [19] to 1b /// MmioOr32 ((UINTN) (PciD31F2RegBase + 0x300), BIT31 | BIT30 | BIT29 | BIT19); /// /// Set D31:F2:300h [17:16] = 11b /// MmioOr32 ((UINTN) (PciD31F2RegBase + 0x300), BIT17 | BIT16); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F2RegBase + 0x300), 1, (VOID *) (UINTN) (PciD31F2RegBase + 0x300) ); if (PchSeries == PchLp) { /// /// Set D31:F2:98h [31:30], [23] to 00b, 1b /// MmioAndThenOr32(PciD31F2RegBase + 0x98, (UINT32)~(BIT31 | BIT30), BIT23); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F2RegBase + 0x98), 1, (VOID *) (UINTN) (PciD31F2RegBase + 0x98) ); /// /// Set RCBA + 0x333C[23:20] to 1100b /// MmioAndThenOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG2), (UINT32)~(BIT21 | BIT20), (UINT32) (BIT22 | BIT23) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG2), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG2) ); } DEBUG ((EFI_D_INFO, "ConfigureMiscPm() End\n")); return EFI_SUCCESS; } /** Configure additional power management settings @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance @param[in] RootComplexBar RootComplexBar value of this PCH device @retval EFI_SUCCESS The function completed successfully **/ EFI_STATUS ConfigureAdditionalPm ( IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, IN UINT32 RootComplexBar ) { UINTN PciD31F0RegBase; UINTN PciD31F2RegBase; UINTN PciD28F0RegBase; UINT32 Data32; UINT8 Data8; UINT16 LpcDeviceId; UINT32 Data32And; UINT32 Data32Or; EFI_STATUS Status; PCH_SERIES PchSeries; Data32 = 0x0; PchSeries = GetPchSeries(); PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); PciD31F2RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 2, 0); PciD28F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 28, 0, 0); LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); /// /// PCH BIOS Spec Rev 0.5.0, Section 19.4 Additional Power Management Programming /// Step 1 /// Set D31:F0:A9h[7:0] = 46h /// MmioWrite8 ( (UINTN) (PciD31F0RegBase + R_PCH_LPC_CIR4), (UINT8) (0x46) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (PciD31F0RegBase + R_PCH_LPC_CIR4), 1, (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_CIR4) ); /// /// Step 2 /// Set Power Management Initialization Register (PMIR) Field 1, D31:F0:ACh[31] = 1b /// Done in Intel Management Engine Framework Reference Code /// Step 3 /// Set GEN_PMCON_LOCK register, D31:F0:A6h = 06h, after stretch and ACPI base programming completed. /// Done in PchInitBeforeBoot() if (PchSeries == PchH) { /// /// Step 4 /// Set RCBA + Offset 2238h[0] = 1b /// MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238), (UINT32) (BIT0) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2238) ); } /// /// Step 5 /// Set RCBA + Offset 232Ch[0] = 1b /// if (PchSeries == PchH) { MmioOr32 ( (UINTN) (RootComplexBar + 0x232C), (UINT32) (BIT0) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x232C), 1, (VOID *) (UINTN) (RootComplexBar + 0x232C) ); } if (PchSeries == PchLp) { /// /// Step 5 /// Set RCBA + Offset 232Ch[0] = 0b /// MmioAnd32 ( (UINTN) (RootComplexBar + 0x232C), (UINT32) ~(BIT0) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x232C), 1, (VOID *) (UINTN) (RootComplexBar + 0x232C) ); /// /// Step 6 /// If Trunk Clock Gating is enabled: /// set RCBA + Offset 1100h[15,14,8,5,4,3,2,1,0] all 1b /// If Trunk Clock Gating is disabled: /// set RCBA + Offset 1100h[15] = 0b /// set RCBA + Offset 1100h[14,8,5,4,3,2,1,0] all 1b /// if((PchPlatformPolicy->UsbConfig->Usb30Settings.Mode != PCH_XHCI_MODE_ON) && (PchPlatformPolicy->UsbConfig->Usb30Settings.Btcg == PCH_DEVICE_DISABLE)) { MmioAndThenOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), (UINT32)~(BIT15), (UINT32) (BIT14 | BIT8 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0) ); } else { MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), (UINT32) (BIT15 | BIT14 | BIT8 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0) ); } SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100) ); } else if (PchSeries == PchH) { /// /// Step 6 /// If Truck Clock Gating is enabled: /// set RCBA + Offset 1100h[14:13] = 11b /// If Truck Clock Gating is disabled: /// set RCBA + Offset 1100h[14:13] = 10b /// if((PchPlatformPolicy->UsbConfig->Usb30Settings.Mode != PCH_XHCI_MODE_ON) && (PchPlatformPolicy->UsbConfig->Usb30Settings.Btcg == PCH_DEVICE_DISABLE)) { MmioAndThenOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), (UINT32) ~(BIT13), (UINT32) (BIT14)); } else { MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), (UINT32) (BIT14 | BIT13) ); } SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR1100) ); } if (PchSeries == PchLp) { /// /// Set IOBP register 0xCF000000[14:12] = 111b /// Set IOBP register 0XCF000000[0] = 1b /// Data32And = (UINT32)~(0); Data32Or = 0x7001; Status = ProgramIobp ( RootComplexBar, 0xCF000000, Data32And, Data32Or ); ASSERT_EFI_ERROR (Status); Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( RootComplexBar, 0xCF000000, Data32And, Data32Or ); ASSERT_EFI_ERROR (Status); /// /// Set IOBP register 0xCA000000[3] = 1b /// Set IOBP register 0XCA000000[0] = 1b /// Data32And = (UINT32)~(0); Data32Or = (UINT32) (0x09); Status = ProgramIobp ( RootComplexBar, 0xCA000000, Data32And, Data32Or ); ASSERT_EFI_ERROR (Status); Status = PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM ( RootComplexBar, 0xCA000000, Data32And, Data32Or ); ASSERT_EFI_ERROR (Status); } else if (PchSeries == PchH) { /// /// Step 7 /// Set RCBA + Offset 2304h[31:0] = 0xC07B8400 /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_DMC), (UINT32) (0xC07B8400) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_DMC), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_DMC) ); /// /// Step 8 /// Set RCBA + Offset 2314h[23 and 5] = 1b /// MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2314), (UINT32) (BIT23 | BIT5) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2314), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2314) ); } /// /// PCH BIOS Spec Rev 0.5.5, Section 19.4 Additional Power Management Programming /// Step 9 /// Set B0:D28:F0 + F5h[3:0] = 0101b /// MmioAndThenOr8 ( (UINTN) (PciD28F0RegBase + 0xF5), (UINT8) ~(BIT3 | BIT1), (UINT8) (BIT2 | BIT0) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint8, (UINTN) (PciD28F0RegBase + 0xF5), 1, (VOID *) (UINTN) (PciD28F0RegBase + 0xF5) ); if (PchSeries == PchH) { /// /// Step 10 /// Set RCBA + Offset 2320h [1] = 1b /// MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320), (UINT32) (BIT1)); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320) ); } if (PchSeries == PchLp) { /// /// Step 10 /// Set RCBA + Offset 2320h [6:4] = 001b /// MmioAndThenOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320), (UINT8) ~(BIT6 | BIT5), (UINT8) (BIT4) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2320) ); } switch (PchSeries) { case PchLp: /// /// Step 11 /// Set RCBA + Offset 3314h[31:0] = 0x00012FFF /// Data32 = 0x00012FFF; break; case PchH: default: /// /// Step 11 /// Set RCBA + Offset 3314h[31:0] = 0x000007BF /// Data32 = 0x000007BF; break; } MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3314), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3314), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3314) ); switch (PchSeries) { case PchLp: /// /// Step 12 /// Set RCBA + Offset 3318h[31:0] = 0x0DCF0400 /// Data32 = 0x0DCF0400; break; case PchH: default: /// /// Step 12 /// Set RCBA + Offset 3318h[31:0] = 0x0DCF0020 (Note: Keep BIT5 unchanged) /// Data32 = 0x0DCF0020; break; } /// /// Note: RCBA + 3318h[19:16] are platform dependent settings (0Fh provides longest assertion), /// please consult with your board design engineers for correct values to be programmed to. /// /// For RCBA + 3318h[9:8] Reset Power Cycle Duration could be customized, please refer to EDS /// and make sure the setting correct, which never less than the following register. /// - GEN_PMCON_3.SLP_S3_MIN_ASST_WDTH /// - GEN_PMCON_3.SLP_S4_MIN_ASST_WDTH /// - PM_CFG.SLP_A_MIN_ASST_WDTH /// - PM_CFG.SLP_LAN_MIN_ASST_WDTH /// Data32 &= (UINT32)~(B_PCH_RCRB_PM_CFG_SSMAW_MASK | B_PCH_RCRB_PM_CFG_SAMAW_MASK); if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_4) { Data32 &= (UINT32)~(B_PCH_RCRB_PM_CFG_RPCD_MASK); } switch (PchPlatformPolicy->MiscPmConfig->PchSlpSusMinAssert) { case PchSlpSus0ms: Data32 |= V_PCH_RCRB_PM_CFG_SSMAW_0S; break; case PchSlpSus500ms: Data32 |= V_PCH_RCRB_PM_CFG_SSMAW_0_5S; break; case PchSlpSus1s: Data32 |= V_PCH_RCRB_PM_CFG_SSMAW_1S; break; case PchSlpSus4s: default: Data32 |= V_PCH_RCRB_PM_CFG_SSMAW_4S; break; } switch (PchPlatformPolicy->MiscPmConfig->PchSlpAMinAssert) { case PchSlpA0ms: Data32 |= V_PCH_RCRB_PM_CFG_SAMAW_0S; break; case PchSlpA4s: Data32 |= V_PCH_RCRB_PM_CFG_SAMAW_4S; break; case PchSlpA98ms: Data32 |= V_PCH_RCRB_PM_CFG_SAMAW_98ms; break; case PchSlpA2s: default: Data32 |= V_PCH_RCRB_PM_CFG_SAMAW_2S; break; } if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_4) { switch (PchPlatformPolicy->MiscPmConfig->PchPwrCycDur) { case 0: // treat as PCH default Data32 |= V_PCH_RCRB_PM_CFG_RPCD_4S; break; case 1: Data32 |= V_PCH_RCRB_PM_CFG_RPCD_1S; break; case 2: Data32 |= V_PCH_RCRB_PM_CFG_RPCD_2S; break; case 3: Data32 |= V_PCH_RCRB_PM_CFG_RPCD_3S; break; case 4: Data32 |= V_PCH_RCRB_PM_CFG_RPCD_4S; break; default: Data32 |= V_PCH_RCRB_PM_CFG_RPCD_4S; DEBUG ((EFI_D_ERROR, "Error. Not a valid PCH reset power cycle duration setting.\n")); break; } } /// /// For LP, force bit 5 = 0 /// For LPT-H, preserve bit 5 /// if (PchSeries == PchLp) { Data32 &= (UINT32) ~(BIT5); MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG), Data32 ); } else { MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG), Data32 ); } SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_PM_CFG) ); /// /// PCH BIOS Spec Rev 0.5.0, Section 19.4 Additional Power Management Programming /// Step 13 /// Set RCBA + Offset 3324h[31:0] = 0x04000000 /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3324), (UINT32) (0x04000000) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3324), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3324) ); if (PchSeries == PchH) { /// /// Step 14 /// Set RCBA + Offset 3340h[31:0] = 0x020DDBFF /// MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3340), (UINT32) (0x020DDBFF) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3340), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3340) ); /// /// Step 15 /// Set RCBA + Offset 3344h[0] = 1b /// MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3344), (UINT32) (BIT0) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3344), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3344) ); } switch (PchSeries) { case PchLp: /// /// Step 16 /// Set RCBA + Offset 3368h[31:0] = 0x00041400 /// Data32 = 0x00041400; break; case PchH: default: /// /// Step 16 /// Set RCBA + Offset 3368h[31:0] = 0x00041000 /// Data32 = 0x00041000; break; } MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3368), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3368), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3368) ); if (PchSeries == PchH) { /// /// Step 17 /// Set RCBA + Offset 3378h[31:0] = 3F8DDBFFh /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3378), (UINT32) (0x3F8DDBFF) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3378), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3378) ); /// /// Step 18 /// Set RCBA + Offset 337Ch[31:0] = 000001E1h /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR337C), (UINT32) (0x000001E1) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR337C), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR337C) ); } switch (PchSeries) { case PchLp: /// /// Step 19 /// Set RCBA + Offset 3388h[31:0] = 0x3F8DDBFF /// Data32 = 0x3F8DDBFF; break; case PchH: default: /// /// Step 19 /// Set RCBA + Offset 3388h[31:0] = 0x00001000 /// Data32 = 0x00001000; break; } MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3388), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3388), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3388) ); if (PchSeries == PchH) { /// /// Step 20 /// Set RCBA + Offset 33A0h[31:0] = 00000800h /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33A0), (UINT32) (0x00000800) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33A0), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33A0) ); } switch (PchSeries) { case PchLp: /// /// Step 21 /// Set RCBA + Offset 33ACh[31:0] = 0x00007001 /// MmioWrite32 ( (UINTN) (RootComplexBar + 0x33AC), (UINT32) (0x00007001) ); break; case PchH: default: /// /// Step 21 /// Set RCBA + Offset 33ACh[31:0] = 00001000h /// MmioWrite32 ( (UINTN) (RootComplexBar + 0x33AC), (UINT32) (0x00001000) ); break; } SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x33AC), 1, (VOID *) (UINTN) (RootComplexBar + 0x33AC) ); switch (PchSeries) { case PchLp: /// /// Step 22 /// Set RCBA + Offset 33B0h[31:0] = 0x00181900 /// Data32 = 0x00181900; break; case PchH: default: /// /// Step 22 /// Set RCBA + Offset 33B0h[31:0] = 0x00001000 /// Data32 = 0x00001000; break; } MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33B0), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33B0), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33B0) ); switch (PchSeries) { case PchLp: /// /// Step 23 /// Set RCBA + Offset 33C0h[31:0] = 0x00060A00 /// Data32 = 0x00060A00; break; case PchH: default: /// /// Step 23 /// Set RCBA + Offset 33C0h[31:0] = 0x00011900 /// Data32 = 0x00011900; break; } MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33C0), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33C0), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33C0) ); /// /// Step 24 /// LP Set RCBA + Offset 33D0h[31:0] = 0x06200840 /// LP Set RCBA + Offset 33D0h[31:0] = 06004622h for LPT LP A0/A1 only /// LPT-H Set RCBA + Offset 33D0h[31:0] = 06000802h switch (PchSeries) { case PchLp: if (PchSeries == PchLp && PchStepping() < LptLpB0) { Data32 = 0x06004622; } else { Data32 = 0x06200840; } break; case PchH: default: Data32 = 0x06000802; break; } MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D0), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D0), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D0) ); /// /// Step 25 -- Note, this step has been moved to meet programming sequence requirements /// Register 3A80 - 3A88 must be program after 3A00-3A3F and before 3A6C /// Set RCBA + 3A88h[31:0] = 0x00000001 /// switch (PchSeries) { case PchLp: /// /// Step 26 /// Set RCBA + Offset 3A28h[31:0] = 01010101h /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A28), (UINT32) (0x01010101) ); break; case PchH: default: /// /// Step 26 /// Set RCBA + Offset 3A28h[31:0] = 01010000h /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A28), (UINT32) (0x01010000) ); break; } SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A28), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A28) ); switch (PchSeries) { case PchLp: /// /// Step 27 /// Set RCBA + Offset 3A2Ch[31:0] = 04040404h /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A2C), (UINT32) (0x04040404) ); break; case PchH: default: /// /// Step 27 /// Set RCBA + Offset 3A2Ch[31:0] = 01010404h /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A2C), (UINT32) (0x01010404) ); break; } SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A2C), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A2C) ); /// /// Step 29 /// Set RCBA + Offset 3A6Ch[31:0] = 00000001h, after all steps in this routine are done /// Done in PchInitBeforeBoot() /// /// Step 30 /// For PCH H /// Set RCBA + Offset 2344h[31:24] = 0FFh /// Set RCBA + Offset 2344h[7:0] = 0Ch /// Done in PchInitBeforeBoot() /// /// Step 31 /// For LPT-H set RCBA + Offset 33A4h[0] = 1b /// if (PchSeries == PchH) { MmioOr32 ( (UINTN) (RootComplexBar + 0x33A4), (UINT32) (BIT0) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x33A4), 1, (VOID *) (UINTN) (RootComplexBar + 0x33A4) ); } if (PchSeries == PchLp) { /// /// Step 32 /// /// Set RCBA + Offset 2B1Ch /// [31:30] =2'b00 /// [29] =0 if Audio DSP is enabled. 1 if disabled (RCBA offset x3418[1]=1). ConfigureAudioDsp will take care of this bit, which is executed later /// Note1: Must assume enable in this flow because ConfigureAudioDsp only program this in the "audio disable flow" only /// [28:22] = 7'b0001110 /// [21:16]=corresponding bit has to be set for each SRC[5:0]CLKRQ# pin that is enabled (ie attached to a PCIe device) /// [15:0]=0x8033h /// Data32 = 0x03808033; MmioWrite32 ( (UINTN) (RootComplexBar + 0x2B1C), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2B1C), 1, (VOID *) (UINTN) (RootComplexBar + 0x2B1C) ); /// /// Step 33 /// Set RCBA + Offset 2B34[31:0] = 80000009h /// Set bit 3 and 0, PMC shutdown time = 16us /// Data32 = 0x80000009; MmioWrite32 ( (UINTN) (RootComplexBar + 0x2B34), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2B34), 1, (VOID *) (UINTN) (RootComplexBar + 0x2B34) ); /// /// Step 34 /// Set RCBA + Offset 3348[31:0] = 022DDFFFh /// Data32 = 0x022DDFFF; MmioWrite32 ( (UINTN) (RootComplexBar + 0x3348), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x3348), 1, (VOID *) (UINTN) (RootComplexBar + 0x3348) ); /// /// Step 35 /// Set RCBA + Offset 334C[31:0] = 00000001h /// Data32 = 0x00000001; MmioWrite32 ( (UINTN) (RootComplexBar + 0x334C), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x334C), 1, (VOID *) (UINTN) (RootComplexBar + 0x334C) ); /// /// Step 36 /// Set RCBA + Offset 3358[31:0] = 0001C000h /// Data32 = 0x0001C000; MmioWrite32 ( (UINTN) (RootComplexBar + 0x3358), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x3358), 1, (VOID *) (UINTN) (RootComplexBar + 0x3358) ); /// /// Step 37 /// Set RCBA + Offset 3380[31:0] = 3F8DDBFFh /// Data32 = 0x3F8DDBFF; MmioWrite32 ( (UINTN) (RootComplexBar + 0x3380), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x3380), 1, (VOID *) (UINTN) (RootComplexBar + 0x3380) ); /// /// Step 38 /// Set RCBA + Offset 3384[31:0] = 0001C7E1h /// Data32 = 0x0001C7E1; MmioWrite32 ( (UINTN) (RootComplexBar + 0x3384), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x3384), 1, (VOID *) (UINTN) (RootComplexBar + 0x3384) ); /// /// Step 39 /// Set RCBA + Offset 338C[31:0] = 0x0001C7E1 /// Data32 = 0x0001C7E1; MmioWrite32 ( (UINTN) (RootComplexBar + 0x338C), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x338C), 1, (VOID *) (UINTN) (RootComplexBar + 0x338C) ); /// /// Step 40 /// Set RCBA + Offset 3398[31:0] = 0001C000h /// Data32 = 0x0001C000; MmioWrite32 ( (UINTN) (RootComplexBar + 0x3398), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x3398), 1, (VOID *) (UINTN) (RootComplexBar + 0x3398) ); /// /// Step 41 /// Set RCBA + Offset 33A8[31:0] = 0x00181900 /// Data32 = 0x00181900; MmioWrite32 ( (UINTN) (RootComplexBar + 0x33A8), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x33A8), 1, (VOID *) (UINTN) (RootComplexBar + 0x33A8) ); /// /// Step 42 /// Set RCBA + Offset 33DC[31:0] = 00080000h /// Data32 = 0x00080000; MmioWrite32 ( (UINTN) (RootComplexBar + 0x33DC), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x33DC), 1, (VOID *) (UINTN) (RootComplexBar + 0x33DC) ); /// /// Step 43 /// Set RCBA + Offset 33E0[31:0] = 00000001h /// Data32 = 0x00000001; MmioWrite32 ( (UINTN) (RootComplexBar + 0x33E0), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x33E0), 1, (VOID *) (UINTN) (RootComplexBar + 0x33E0) ); /// /// Step 44 /// Set RCBA + Offset 3A20[31:0] = 00000404h /// Data32 = 0x00000404; MmioWrite32 ( (UINTN) (RootComplexBar + 0x3A20), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x3A20), 1, (VOID *) (UINTN) (RootComplexBar + 0x3A20) ); /// /// Step 45 /// Set RCBA + Offset 3A24[31:0] = 01010101h /// Data32 = 0x01010101; MmioWrite32 ( (UINTN) (RootComplexBar + 0x3A24), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x3A24), 1, (VOID *) (UINTN) (RootComplexBar + 0x3A24) ); /// /// Step 46 /// Set RCBA + Offset 3A30[31:0] = 01010101h /// Data32 = 0x01010101; MmioWrite32 ( (UINTN) (RootComplexBar + 0x3A30), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x3A30), 1, (VOID *) (UINTN) (RootComplexBar + 0x3A30) ); /// /// Step 47 /// Set D31:F0:ACh[21] = 0b /// MmioAnd32 ( (UINTN) (PciD31F0RegBase + R_PCH_LPC_PMIR), (UINT32) ~(BIT21) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (PciD31F0RegBase + R_PCH_LPC_PMIR), 1, (VOID *) (UINTN) (PciD31F0RegBase + R_PCH_LPC_PMIR) ); /// /// Step 48 /// set RCBA + Offset 410h[1:0] = 11b /// MmioOr32 ( (UINTN) (RootComplexBar + 0x410), (UINT32) (BIT1 | BIT0) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x410), 1, (VOID *) (UINTN) (RootComplexBar + 0x410) ); /// /// Step 49 /// Set RCBA + 2618h[27] = 1b /// MmioOr32 ( (UINTN) (RootComplexBar + 0x2618), (UINT32) BIT27 ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2618), 1, (VOID *) (UINTN) (RootComplexBar + 0x2618) ); /// /// Step 50 /// Set RCBA + 2300h[1] = 1b /// Data32And = 0xFFFFFFFF; Data32Or = (UINT32) BIT1; MmioOr32 (RootComplexBar + 0x2300 , Data32Or); SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2300), &Data32Or, // Data to be ORed &Data32And // Data to be ANDed ); /// /// Step 51 /// Set RCBA + 2600h[3] = 1b /// MmioOr32 ( (UINTN) (RootComplexBar + 0x2600), (UINT32) BIT3 ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2600), 1, (VOID *) (UINTN) (RootComplexBar + 0x2600) ); /// /// Step 52 /// Set RCBA + 33B4h[0] = 0x00007001 /// Data32 = 0x00007001; MmioWrite32 ( (UINTN) (RootComplexBar + 0x33B4), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x33B4), 1, (VOID *) (UINTN) (RootComplexBar + 0x33B4) ); /// Step 53 /// Set RCBA + Offset 3350[31:0] = 0x022DDFFF /// Data32 = 0x022DDFFF; MmioWrite32 ( (UINTN) (RootComplexBar + 0x3350), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x3350), 1, (VOID *) (UINTN) (RootComplexBar + 0x3350) ); /// /// Step 54 /// Set RCBA + Offset 3354[31:0] = 0x00000001 /// Data32 = 0x00000001; MmioWrite32 ( (UINTN) (RootComplexBar + 0x3354), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x3354), 1, (VOID *) (UINTN) (RootComplexBar + 0x3354) ); } if ((PchPlatformPolicy->PwrOptConfig->PchPwrOptDmi == PCH_DEVICE_ENABLE)) { /// /// PCH BIOS Spec Rev 0.5.0, Section 19.13 Power Optimizer Considerations (MB Only) /// Notes: Settings is not recommended for Lynx Point Power on ES0 samples /// Step 1 /// Enable PM SYNC State 12 /// Program RCBA + 33D4h[27] = 1b /// For PCH LP /// Program RCBA + 2B14[31:0] = 1E0A4616h /// Program RCBA + 2B24[31:0] = 40000005h /// For PCH H /// Program RCBA + 2B14[31:0] = 1E0A0317h /// Program RCBA + 2B24[31:0] = 4000000Bh /// Program RCBA + 2B28[31:0] = 00000002h /// Program RCBA + 2B2C[31:0] = 00008813h /// MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D4), (UINT32) BIT27 ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D4), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR33D4) ); /// /// Program RCBA + 33C8h[27] = 1b /// Data32Or = BIT27; if (PchSeries == PchLp) { /// /// Program RCBA + 33C8h[7] = 1b /// Data32Or = BIT7; } MmioOr32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_PMSYNC), (UINT32) Data32Or ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_PMSYNC), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_PMSYNC) ); /// /// For LPT-LP, Program RCBA + 2B10[31:0] = 0000883Ch /// if (PchSeries == PchLp) { MmioWrite32 ( (UINTN) (RootComplexBar + 0x2B10), (UINT32) (0x0000883C) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2B10), 1, (VOID *) (UINTN) (RootComplexBar + 0x2B10) ); } /// /// Program RCBA + 2B14[31:0] = 1E0A0317h /// For LP Program RCBA + 2B14[31:0] = 1E0A4616h /// Data32 = 0x1E0A0317; if (PchSeries == PchLp) { Data32 = 0x1E0A4616; } if (PchPlatformPolicy->PwrOptConfig->MemCloseStateEn == PCH_DEVICE_DISABLE) { Data32 &= (UINT32) ~(BIT2); } if (PchPlatformPolicy->PwrOptConfig->InternalObffEn == PCH_DEVICE_DISABLE) { Data32 &= (UINT32) ~(BIT1); } if (PchPlatformPolicy->PwrOptConfig->ExternalObffEn == PCH_DEVICE_DISABLE) { Data32 &= (UINT32) ~(BIT0); } MmioWrite32 ( (UINTN) (RootComplexBar + 0x2B14), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2B14), 1, (VOID *) (UINTN) (RootComplexBar + 0x2B14) ); if (PchSeries == PchLp) { /// /// Set RCBA + Offset 2B24[31:0] = 0x40000005 /// Data32 = 0x40000005; } else { /// /// Set RCBA + Offset 2B24[31:0] = 0x4000000B /// Data32 = 0x4000000B; } MmioWrite32 ( (UINTN) (RootComplexBar + 0x2B24), Data32 ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2B24), 1, (VOID *) (UINTN) (RootComplexBar + 0x2B24) ); if (PchSeries == PchH) { /// /// Set RCBA + Offset 2B28[31:0] = 0x00000002 /// MmioWrite32 ( (UINTN) (RootComplexBar + 0x2B28), (UINT32) (0x00000002) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2B28), 1, (VOID *) (UINTN) (RootComplexBar + 0x2B28) ); } if (PchSeries == PchH) { /// /// Set RCBA + Offset 2B2C[31:0] = 0x00008813 /// Data32 = 0x00008813; MmioWrite32 ( (UINTN) (RootComplexBar + 0x2B2C), Data32 ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2B2C), 1, (VOID *) (UINTN) (RootComplexBar + 0x2B2C) ); } /// Step 7 /// Enable PM Demand in Cx States /// For LPT-H, use default /// For LPT-LP Program RCBA + 02B20h[1:0] = 0x0005DB01 /// if (PchSeries == PchLp) { Data32 = 0x0005DB01; MmioWrite32 ( (UINTN) (RootComplexBar + 0x2B20), Data32 ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2B20), 1, (VOID *) (UINTN) (RootComplexBar + 0x2B20) ); } } switch (PchSeries) { case PchLp: /// /// Step 55 /// Set RCBA + 3A80h[31:0] = 05145005h /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A80), (UINT32) (0x05145005) ); break; case PchH: default: /// /// Step 55 /// Set RCBA + 3A80h[31:0] = 01040000h /// MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A80), (UINT32) (0x01040000) ); break; } SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A80), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A80) ); /// /// Step 56 /// Ensure this is done after 3A00-3A3C and before 3A6C /// if PchLp, Set RCBA + Offset 3A84h[31:0] = 0x00001005 /// if PchH, Set RCBA + Offset 3A84h[31:0] = 0x01041001 /// if PCS.P0E and PCS.P1E = 0b, Set RCBA + Offset 3A84h[20,18] = 1b, 1b /// if PCS.P2E and PCS.P3E = 0b, Set RCBA + Offset 3A84h[24,26] = 1b, 1b /// if (PchSeries == PchLp) { Data32 = 0x00001005; } else { Data32 = 0x01041001; } Data8 = MmioRead8 (PciD31F2RegBase + R_PCH_SATA_PCS); if((Data8 & (UINT8) (B_PCH_SATA_PCS_PORT0_EN | B_PCH_SATA_PCS_PORT1_EN)) == 0) { Data32 |= (BIT20 | BIT18); } if((Data8 & (UINT8) (B_PCH_SATA_PCS_PORT2_EN | B_PCH_SATA_PCS_PORT3_EN)) == 0) { Data32 |= (BIT24 | BIT26); } MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A84), (UINT32) (Data32) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A84), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A84) ); /// /// Step 57 /// Set RCBA + 3A88h[31:0] = 0x00000001 /// if (PchSeries == PchH) { MmioWrite32 ( (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A88), (UINT32) (0x00000001) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A88), 1, (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR3A88) ); } /// /// Step 58 /// For LPT-LP Set RCBA + Offset 33D4h = 0x2FFF2FB1, after step #14 to #24 and D31:F0:A9h are done /// Note for LP only: Preserve bits 31,30,28,15,14,12, which are platform specific /// For LPT-H Set RCBA + Offset 33D4h = 0xC00BC000, after step #14 to #24 and D31:F0:A9h are done /// switch (PchSeries) { case PchLp: MmioOr32 ( (UINTN) (RootComplexBar + 0x33D4), (UINT32) (0x2FFF2FB1) ); break; case PchH: default: MmioWrite32 ( (UINTN) (RootComplexBar + 0x33D4), (UINT32) (0xC00BC000) ); break; } SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x33D4), 1, (VOID *) (UINTN) (RootComplexBar + 0x33D4) ); if (PchSeries == PchLp) { /// /// This is the last step which only apply for LPT-LP /// Set RCBA + Offset 33C8h[15] = 1b /// MmioOr32 ( (UINTN) (RootComplexBar + 0x33C8), (UINT32) (BIT15) ); SCRIPT_MEM_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x33C8), 1, (VOID *) (UINTN) (RootComplexBar + 0x33C8) ); } return EFI_SUCCESS; } /** Configures PCH DMI according to policies specified in PCH Platform Policy protocol @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance @param[in] RootComplexBar RootComplexBar value of this PCH device @retval EFI_SUCCESS Successfully completed. **/ EFI_STATUS EFIAPI ConfigureDmiPm ( IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, IN UINT32 RootComplexBar ) { UINT32 Data32And; UINT32 Data32Or; UINT16 Data16And; UINT16 Data16Or; UINTN PciD28F0RegBase; PCH_PCI_EXPRESS_ASPM_CONTROL DmiAspmCtrl; PCH_SERIES PchSeries; DEBUG ((EFI_D_INFO, "ConfigureDmi() Start\n")); PchSeries = GetPchSeries(); PciD28F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 28, 0, 0); /// /// PCH BIOS Spec Rev 0.5.0 Section 7.1.5 Additional PCH DMI Programming Steps /// if (PchSeries == PchH) { /// Step 4.1 /// If RCBA + Offset 2320h[1] = 0 and B0:D28:F0 + F5h[0] = 0, set RCBA + Offset 21A4h[17:15] = 010b /// Else set RCBA + Offset 21A4h[17:15] = 100b /// if (((MmioRead32 ((UINTN) RootComplexBar + R_PCH_RCRB_CIR2320) & (UINT32) (BIT1)) == 0) && ((MmioRead8 (PciD28F0RegBase + 0xF5) & BIT0) == 0)) { Data32Or = BIT16; } else { Data32Or = BIT17; } /// /// Step 4.2 /// Set RCBA + Offset 21A4h[14:12] = 011b /// Data32Or |= BIT13 | BIT12; Data32And = (UINT32)~(B_PCH_RCRB_LCAP_EL1 | B_PCH_RCRB_LCAP_EL0); MmioAndThenOr32 (RootComplexBar + R_PCH_RCRB_LCAP, Data32And, Data32Or); SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_LCAP), &Data32Or, // Data to be ORed &Data32And // Data to be ANDed ); } /// /// Step 4.3 /// Set RCBA + 2348[3:0] = 0h /// Data32Or = 0; Data32And = (UINT32) ~(BIT0 | BIT1 | BIT2 | BIT3); MmioAnd32 (RootComplexBar + 0x2348, Data32And); SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + 0x2348), &Data32Or, // Data to be ORed &Data32And // Data to be ANDed ); /// /// Enable DMI ASPM /// /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 ASPM on DMI and the PCI Express* Root Ports /// if (PchPlatformPolicy->DmiConfig->DmiAspm == PCH_DEVICE_ENABLE) { /// /// While DmiAspm is enabled, DMI ASPM will be set to Intel recommended value. /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 ASPM on DMI and the PCI Express* Root Ports /// Note: We recommend PCH platforms to enable L0s and L1, but unless both sides of the link have L0s and/or /// L1 enabled they will be disabled by the link. /// DmiAspmCtrl = PchPcieAspmL0sL1; } else { DmiAspmCtrl = PchPcieAspmDisabled; } if (DmiAspmCtrl != PchPcieAspmDisabled) { if (PchSeries == PchH) { /// /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 /// BIOS should set RCBA + 2304h[10] to 0b prior to enabling DMI ASPM. /// Data32And = (UINT32)~(BIT10); Data32Or = 0; MmioAnd32 (RootComplexBar + R_PCH_RCRB_DMC, Data32And); SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_DMC), &Data32Or, // Data to be ORed &Data32And // Data to be ANDed ); /// /// PCH BIOS Spec Rev 0.5.0, Section 8.3.1 /// /// Step 1 /// RCBA + 21A4h[11:10] = 11b /// Data32And = 0xFFFFFFFF; Data32Or = B_PCH_RCRB_LCAP_APMS; MmioOr32 (RootComplexBar + R_PCH_RCRB_LCAP, Data32Or); SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_LCAP), &Data32Or, // Data to be ORed &Data32And // Data to be ANDed ); } if (DmiAspmCtrl == PchPcieAspmL0sL1) { /// /// Step 2 /// Enable L0s/L1 on DMI by setting RCBA + offset 21A8h[1:0] to 11b /// Data16And = (UINT16) (~(BIT1 + BIT0)); Data16Or = (UINT16) (BIT1 + BIT0); } else { // // Do nothing // Data16And = 0xFFFF; Data16Or = 0; } if (PchSeries == PchH) { /// /// Program RCBA + offset 21A8h[1:0] /// MmioAndThenOr16 (RootComplexBar + R_PCH_RCRB_LCTL, Data16And, Data16Or); SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint16, (UINTN) (RootComplexBar + R_PCH_RCRB_LCTL), &Data16Or, // Data to be ORed &Data16And // Data to be ANDed ); /// /// BIOS should set RCBA + 2304h[10] back to 1b after enabling DMI ASPM. /// Data32And = 0xFFFFFFFF; Data32Or = (UINT32) (BIT10); MmioOr32 (RootComplexBar + R_PCH_RCRB_DMC, Data32Or); SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint32, (UINTN) (RootComplexBar + R_PCH_RCRB_DMC), &Data32Or, // Data to be ORed &Data32And // Data to be ANDed ); } } if (PchSeries == PchH) { if (PchPlatformPolicy->DmiConfig->DmiExtSync == PCH_DEVICE_ENABLE) { Data16And = (UINT16) (~(B_PCH_RCRB_LCTL_ES)); Data16Or = (UINT16) B_PCH_RCRB_LCTL_ES; MmioAndThenOr16 (RootComplexBar + R_PCH_RCRB_LCTL, Data16And, Data16Or); SCRIPT_MEM_READ_WRITE ( EFI_ACPI_S3_RESUME_SCRIPT_TABLE, EfiBootScriptWidthUint16, (UINTN) (RootComplexBar + R_PCH_RCRB_LCTL), &Data16Or, // Data to be ORed &Data16And // Data to be ANDed ); } } DEBUG ((EFI_D_INFO, "ConfigureDmi() End\n")); return EFI_SUCCESS; } /** Configure deep Sx programming @param[in] PchPlatformPolicy The PCH Platform Policy protocol instance @param[in] RootComplexBar RootComplexBar value of this PCH device @retval EFI_SUCCESS The function completed successfully **/ EFI_STATUS ProgramDeepSx ( DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy, UINT32 RootComplexBar ) { UINT32 S3Data32; UINT32 S4Data32; UINT32 S5Data32; UINTN PciD31F0RegBase; UINT16 LpcDeviceId; PciD31F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, 31, 0, 0); LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); /// /// PCH BIOS Spec Rev 0.5.0, Section 19.11 Deep Sx Power Policies /// The System BIOS can perform the following register programming guidelines to enable system /// enter Deep S4 or Deep S5. /// /// DPS3_EN_DC DPS3_EN_AC DPS4_EN_DC DPS4_EN_AC DPS5_EN_DC DPS5_EN_AC /// RCBA+3328h[1] RCBA + 3328h[0] RCBA + 332Ch[1] RCBA + 332Ch[0] RCBA + 3330h[15] RCBA + 3330h[14] /// Deep Sx disabled 0 0 0 0 0 0 /// /// Enabled in S5 0 0 0 0 1 1 /// /// Enabled in S4 and S5 0 0 1 1 1 1 /// /// Enabled in S3, S4 and S5 1 1 1 1 1 1 /// /// Configuration supported by MOBILE: /// Enabled in S5 0 0 0 0 1 0 /// (Battery mode) /// Enabled in S4 and S5 0 0 1 0 1 0 /// (Battery Mode) /// Enabled in S3, S4 and S5 1 0 1 0 1 0 /// (Battery Mode) /// /// NOTE: Mobile platforms support Deep S4/S5 in DC ONLY, /// Desktop and Intel C206 Chipset (LPC Dev ID 0x1C56) platforms support Deep S4/S5 in AC ONLY, /// Intel C204 Chipset (LPC Dev ID 0x1C54) and Intel C202 Chipset (LPC Dev ID 0x1C52) platforms DO NOT support Deep S4/S5. /// /// Deep Sx disabled 0 0 0 0 0 0 /// if (IS_PCH_LPT_LPC_DEVICE_ID_DESKTOP (LpcDeviceId) || IS_PCH_LPT_LPC_DEVICE_ID_SERVER (LpcDeviceId) || IS_PCH_LPT_LPC_DEVICE_ID_WS (LpcDeviceId)) { if ((PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchMobileDpS5En) || (PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchMobileDpS4S5En) || (PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchMobileDpS3S4S5En)) { /// /// Set PchDeepSxPol to PchDeepSxPolDisable for unsupported deep Sx policy /// PchPlatformPolicy->MiscPmConfig->PchDeepSxPol = PchDeepSxPolDisable; DEBUG ((EFI_D_ERROR, "Unsupported Deep Sx policy for desktop system\n")); } } else { if ((PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchDesktopDpS5En) || (PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchDesktopDpS4S5En) || (PchPlatformPolicy->MiscPmConfig->PchDeepSxPol == PchDesktopDpS3S4S5En)) { /// /// Set PchDeepSxPol to PchDeepSxPolDisable for unsupported deep Sx policy /// PchPlatformPolicy->MiscPmConfig->PchDeepSxPol = PchDeepSxPolDisable; DEBUG ((EFI_D_ERROR, "Unsupported Deep Sx policy for mobile system\n")); } } switch (PchPlatformPolicy->MiscPmConfig->PchDeepSxPol) { case PchDesktopDpS5En: /// /// Configuration 2: Enabled in S5/AC-DC /// DEEP_S3_POL.DPS3_EN_DC = 0; DEEP_S3_POL.DPS3_EN_AC = 0; /// DEEP_S4_POL.DPS4_EN_DC = 0; DEEP_S4_POL.DPS4_EN_AC = 0; /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 1; /// S3Data32 = 0; S4Data32 = 0; S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_AC | B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); break; case PchDesktopDpS4S5En: /// /// Configuration 4: Enabled only in S4-S5 /// DEEP_S3_POL.DPS3_EN_DC = 0; DEEP_S3_POL.DPS3_EN_AC = 0; /// DEEP_S4_POL.DPS4_EN_DC = 1; DEEP_S4_POL.DPS4_EN_AC = 1; /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 1; /// S3Data32 = 0; S4Data32 = (UINT32) (B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_AC | B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_DC); S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_AC | B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); break; case PchDesktopDpS3S4S5En: /// /// Configuration 6: Enabled only in S3-S4-S5 /// DEEP_S3_POL.DPS3_EN_DC = 1; DEEP_S3_POL.DPS3_EN_AC = 1; /// DEEP_S4_POL.DPS4_EN_DC = 1; DEEP_S4_POL.DPS4_EN_AC = 1; /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 1; /// S3Data32 = (UINT32) (B_PCH_RCRB_DEEP_S3_POL_DPS3_EN_AC | B_PCH_RCRB_DEEP_S3_POL_DPS3_EN_DC); S4Data32 = (UINT32) (B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_AC | B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_DC); S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_AC | B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); break; case PchMobileDpS5En: /// /// Configuration 1: Enabled in S5/Battery only /// DEEP_S3_POL.DPS3_EN_DC = 0; DEEP_S3_POL.DPS3_EN_AC = 0; /// DEEP_S4_POL.DPS4_EN_DC = 0; DEEP_S4_POL.DPS4_EN_AC = 0; /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 0; /// S3Data32 = 0; S4Data32 = 0; S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); break; case PchMobileDpS4S5En: /// /// Configuration 3: Enabled only in S4-S5/Battery Mode /// DEEP_S3_POL.DPS3_EN_DC = 0; DEEP_S3_POL.DPS3_EN_AC = 0; /// DEEP_S4_POL.DPS4_EN_DC = 1; DEEP_S4_POL.DPS4_EN_AC = 0; /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 0; /// S3Data32 = 0; S4Data32 = (UINT32) (B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_DC); S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); break; case PchMobileDpS3S4S5En: /// /// Configuration 5: Enabled only in S4-S5/Battery Mode /// DEEP_S3_POL.DPS3_EN_DC = 1; DEEP_S3_POL.DPS3_EN_AC = 0; /// DEEP_S4_POL.DPS4_EN_DC = 1; DEEP_S4_POL.DPS4_EN_AC = 0; /// DEEP_S5_POL.DPS5_EN_DC = 1; DEEP_S5_POL.DPS5_EN_AC = 0; /// S3Data32 = (UINT32) (B_PCH_RCRB_DEEP_S3_POL_DPS3_EN_DC); S4Data32 = (UINT32) (B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_DC); S5Data32 = (UINT32) (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC); break; case PchDeepSxPolDisable: default: /// /// Configuration 5: DeepSx Disabled /// DEEP_S3_POL.DPS3_EN_DC = 0; DEEP_S3_POL.DPS3_EN_AC = 0; /// DEEP_S4_POL.DPS4_EN_DC = 0; DEEP_S4_POL.DPS4_EN_AC = 0; /// DEEP_S5_POL.DPS5_EN_DC = 0; DEEP_S5_POL.DPS5_EN_AC = 0; /// S3Data32 = 0; S4Data32 = 0; S5Data32 = 0; break; } MmioWrite32 ((RootComplexBar + R_PCH_RCRB_DEEP_S3_POL), S3Data32); MmioWrite32 ((RootComplexBar + R_PCH_RCRB_DEEP_S4_POL), S4Data32); MmioWrite32 ((RootComplexBar + R_PCH_RCRB_DEEP_S5_POL), S5Data32); return EFI_SUCCESS; }