688 lines
25 KiB
C
688 lines
25 KiB
C
/** @file
|
|
This is the driver that initializes the Intel PCH.
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 2014 - 2021 Intel Corporation.
|
|
|
|
The source code contained or described herein and all documents related to the
|
|
source code ("Material") are owned by Intel Corporation or its suppliers or
|
|
licensors. Title to the Material remains with Intel Corporation or its suppliers
|
|
and licensors. The Material may contain trade secrets and proprietary and
|
|
confidential information of Intel Corporation and its suppliers and licensors,
|
|
and is protected by worldwide copyright and trade secret laws and treaty
|
|
provisions. No part of the Material may be used, copied, reproduced, modified,
|
|
published, uploaded, posted, transmitted, distributed, or disclosed in any way
|
|
without Intel's prior express written permission.
|
|
|
|
No license under any patent, copyright, trade secret or other intellectual
|
|
property right is granted to or conferred upon you by disclosure or delivery
|
|
of the Materials, either expressly, by implication, inducement, estoppel or
|
|
otherwise. Any license under such intellectual property rights must be
|
|
express and approved by Intel in writing.
|
|
|
|
Unless otherwise agreed by Intel in writing, you may not remove or alter
|
|
this notice or any other notice embedded in Materials by Intel or
|
|
Intel's suppliers or licensors in any way.
|
|
|
|
This file contains an 'Intel Peripheral Driver' and is 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.
|
|
|
|
@par Specification Reference:
|
|
**/
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/IoLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
|
|
#include "PchInit.h"
|
|
#include <Protocol/PchPolicy.h>
|
|
#include <GpioDevConfig.h>
|
|
#include <ScsConfig.h>
|
|
#include <ScsInfoHob.h>
|
|
#include <Library/AslUpdateLib.h>
|
|
#include <Library/PchInfoLib.h>
|
|
#include <Library/GpioLib.h>
|
|
#include <Library/GpioPrivateLib.h>
|
|
#include <Library/GpioNativeLib.h>
|
|
#include <Library/GpioNativePads.h>
|
|
#include <Library/PchCycleDecodingLib.h>
|
|
#include <Library/PmcLib.h>
|
|
#include <Library/SerialIoAccessLib.h>
|
|
#include <Library/SerialIoPrivateLib.h>
|
|
#include <Library/GbeLib.h>
|
|
#include <PchRstHob.h>
|
|
#include <Library/PchPcieRpLib.h>
|
|
#include <Library/CpuPlatformLib.h>
|
|
#include <TraceHubConfig.h>
|
|
#include <Register/TraceHubRegs.h>
|
|
#include <Library/PciSegmentLib.h>
|
|
#include <Register/PchRegs.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Register/UsbRegs.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <IndustryStandard/Pci22.h>
|
|
#include <PcieRegs.h>
|
|
#include <Library/PchPcrLib.h>
|
|
#include <Library/PchPciBdfLib.h>
|
|
#include <PchHybridStorageHob.h>
|
|
#include <PchBdfAssignment.h>
|
|
#include <Library/SataLib.h>
|
|
#include <Library/SataSocLib.h>
|
|
|
|
//
|
|
// Module variables
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA_PROTOCOL mPchNvsAreaProtocol;
|
|
|
|
/**
|
|
Retrieve interrupt information about a PCH device from policy
|
|
|
|
@param[in] UartNumber Uart number
|
|
|
|
@retval PCH_DEVICE_INTERRUPT_CONFIG structure with device's interrupt information
|
|
**/
|
|
PCH_DEVICE_INTERRUPT_CONFIG
|
|
STATIC
|
|
GetUartInterrupt (
|
|
IN UINT8 UartNumber
|
|
)
|
|
{
|
|
PCH_DEVICE_INTERRUPT_CONFIG EmptyRecord;
|
|
UINT8 DevNum;
|
|
UINT8 FuncNum;
|
|
UINT8 Index;
|
|
|
|
ZeroMem (&EmptyRecord, sizeof (PCH_DEVICE_INTERRUPT_CONFIG));
|
|
DevNum = SerialIoUartDevNumber (UartNumber);
|
|
FuncNum = SerialIoUartFuncNumber (UartNumber);
|
|
|
|
for (Index = 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig; Index++) {
|
|
if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device == DevNum) &&
|
|
(mPchConfigHob->Interrupt.DevIntConfig[Index].Function == FuncNum)) {
|
|
return mPchConfigHob->Interrupt.DevIntConfig[Index];
|
|
}
|
|
}
|
|
return EmptyRecord;
|
|
}
|
|
|
|
/**
|
|
Update ASL definitions for SerialIo devices.
|
|
|
|
**/
|
|
VOID
|
|
STATIC
|
|
UpdateSerialIoAcpiData (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
|
|
for (Index = 0; Index < GetPchMaxSerialIoSpiControllersNum (); Index++) {
|
|
mPchNvsAreaProtocol.Area->SM0[Index] = mPchConfigHob->SerialIo.SpiDeviceConfig[Index].Mode;
|
|
mPchNvsAreaProtocol.Area->SC0[Index] = GetSerialIoSpiPciCfg (Index);
|
|
}
|
|
for (Index = 0; Index < GetPchMaxSerialIoI2cControllersNum (); Index++) {
|
|
mPchNvsAreaProtocol.Area->IM0[Index] = mPchConfigHob->SerialIo.I2cDeviceConfig[Index].Mode;
|
|
mPchNvsAreaProtocol.Area->IC0[Index] = GetSerialIoI2cPciCfg (Index);
|
|
}
|
|
for (Index = 0; Index < GetPchMaxSerialIoUartControllersNum (); Index++) {
|
|
mPchNvsAreaProtocol.Area->UM0[Index] = mPchConfigHob->SerialIo.UartDeviceConfig[Index].Mode;
|
|
mPchNvsAreaProtocol.Area->UC0[Index] = GetSerialIoUartPciCfg (Index);
|
|
mPchNvsAreaProtocol.Area->UD0[Index] = mPchConfigHob->SerialIo.UartDeviceConfig[Index].DmaEnable;
|
|
mPchNvsAreaProtocol.Area->UP0[Index] = mPchConfigHob->SerialIo.UartDeviceConfig[Index].PowerGating;
|
|
mPchNvsAreaProtocol.Area->UI0[Index] = (GetUartInterrupt (Index)).Irq;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Update ASL definitions for Touch Host Controller devices.
|
|
|
|
**/
|
|
VOID
|
|
STATIC
|
|
UpdateThcAcpiData (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
GPIO_PAD_NATIVE_FUNCTION ThcHidResetPad;
|
|
|
|
for (Index = 0; Index < GetPchMaxThcCount (); Index++) {
|
|
mPchNvsAreaProtocol.Area->ThcWakOnTouchInterrupt[Index] = 0;
|
|
mPchNvsAreaProtocol.Area->ThcMode[Index] = mPchConfigHob->Thc.ThcPort[Index].Mode;
|
|
mPchNvsAreaProtocol.Area->ThcActiveLtr[Index] = mPchConfigHob->Thc.ThcPort[Index].ActiveLtr;
|
|
mPchNvsAreaProtocol.Area->ThcIdleLtr[Index] = mPchConfigHob->Thc.ThcPort[Index].IdleLtr;
|
|
mPchNvsAreaProtocol.Area->ThcLimitPacketSize[Index] = mPchConfigHob->Thc.ThcPort[Index].LimitPacketSize;
|
|
mPchNvsAreaProtocol.Area->ThcPerformanceLimitation[Index] = mPchConfigHob->Thc.ThcPort[Index].PerformanceLimitation;
|
|
if (mPchConfigHob->Thc.ThcPort[Index].HidOverSpi.ResetPad == 0x0) {
|
|
// Use HW default
|
|
ThcHidResetPad = GpioGetThcSpiReset (Index);
|
|
mPchNvsAreaProtocol.Area->ThcHidResetPad[Index] = ThcHidResetPad.Pad;
|
|
} else {
|
|
// Use Pad provided by the policy
|
|
mPchNvsAreaProtocol.Area->ThcHidResetPad[Index] = mPchConfigHob->Thc.ThcPort[Index].HidOverSpi.ResetPad;
|
|
}
|
|
DEBUG ((DEBUG_INFO, "UpdateThcAcpiData() THC %d HidOverSpi.ResetPad: %X \n", Index, mPchNvsAreaProtocol.Area->ThcHidResetPad[Index]));
|
|
mPchNvsAreaProtocol.Area->ThcHidResetPadTrigger[Index] = (UINT8) mPchConfigHob->Thc.ThcPort[Index].HidOverSpi.ResetPadTrigger;
|
|
mPchNvsAreaProtocol.Area->ThcHidInputReportBodyAddress[Index] = mPchConfigHob->Thc.ThcPort[Index].HidOverSpi.InputReportBodyAddress;
|
|
mPchNvsAreaProtocol.Area->ThcHidInputReportHeaderAddress[Index] = mPchConfigHob->Thc.ThcPort[Index].HidOverSpi.InputReportHeaderAddress;
|
|
mPchNvsAreaProtocol.Area->ThcHidOutputReportAddress[Index] = mPchConfigHob->Thc.ThcPort[Index].HidOverSpi.OutputReportAddress;
|
|
mPchNvsAreaProtocol.Area->ThcHidReadOpcode[Index] = mPchConfigHob->Thc.ThcPort[Index].HidOverSpi.ReadOpcode;
|
|
mPchNvsAreaProtocol.Area->ThcHidWriteOpcode[Index] = mPchConfigHob->Thc.ThcPort[Index].HidOverSpi.WriteOpcode;
|
|
mPchNvsAreaProtocol.Area->ThcHidConnectionSpeed[Index] = mPchConfigHob->Thc.ThcPort[Index].HidOverSpi.Frequency;
|
|
mPchNvsAreaProtocol.Area->ThcHidFlags[Index] = mPchConfigHob->Thc.ThcPort[Index].HidOverSpi.Flags;
|
|
|
|
if (mPchConfigHob->Thc.ThcPort[Index].WakeOnTouch == TRUE) {
|
|
DEBUG ((DEBUG_INFO, "UpdateThcAcpiData() THC %d WakeOnTouch Pad: %X \n", Index, GPIO_NATIVE_TO_GPIO_PAD (GpioGetNativePadByFunction (GPIO_FUNCTION_THC_WOT(Index))) ));
|
|
mPchNvsAreaProtocol.Area->ThcWakOnTouchInterrupt[Index] = GPIO_NATIVE_TO_GPIO_PAD (GpioGetNativePadByFunction (GPIO_FUNCTION_THC_WOT(Index)));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Update ASL definitions for SCS.
|
|
@retval EFI_SUCCESS The function completed successfully
|
|
**/
|
|
VOID
|
|
UpdateScsAcpiData (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_PEI_HOB_POINTERS HobPtr;
|
|
SCS_INFO_HOB *ScsInfoHob;
|
|
|
|
// Get SCS Info HOB.
|
|
HobPtr.Guid = GetFirstGuidHob (&gScsInfoHobGuid);
|
|
if (HobPtr.Guid != NULL) {
|
|
ScsInfoHob = (SCS_INFO_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
|
|
mPchNvsAreaProtocol.Area->Ufs0Enabled = (UINT8)ScsInfoHob->UfsInfo[0].Supported;
|
|
mPchNvsAreaProtocol.Area->Ufs1Enabled = (UINT8)ScsInfoHob->UfsInfo[1].Supported;
|
|
DEBUG ((DEBUG_INFO, "UpdateScsAcpiData() Ufs0 %d Ufs1 %d \n", mPchNvsAreaProtocol.Area->Ufs0Enabled, mPchNvsAreaProtocol.Area->Ufs1Enabled));
|
|
}
|
|
}
|
|
|
|
#if FixedPcdGet8(PcdEmbeddedEnable) == 0x1
|
|
/**
|
|
Update NVS Area for Timed GPIO devices.
|
|
**/
|
|
VOID
|
|
UpdateTimedGpioSetup (
|
|
VOID
|
|
)
|
|
{
|
|
mPchNvsAreaProtocol.Area->EnableTimedGpio0 = (UINT8)mPchConfigHob->Pm.EnableTimedGpio0;
|
|
mPchNvsAreaProtocol.Area->EnableTimedGpio1 = (UINT8)mPchConfigHob->Pm.EnableTimedGpio1;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
Update NVS Area after RST PCIe Storage Remapping and before Boot
|
|
|
|
@retval EFI_SUCCESS The function completed successfully
|
|
@retval EFI_NOT_FOUND Couldn't fetch RstHob
|
|
**/
|
|
EFI_STATUS
|
|
PchUpdateNvsAreaAfterRemapping (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN Index;
|
|
VOID *Hob;
|
|
PCH_RST_HOB *RstHob;
|
|
|
|
Hob = GetFirstGuidHob (&gPchRstHobGuid);
|
|
if (Hob == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
RstHob = (PCH_RST_HOB *) GET_GUID_HOB_DATA (Hob);
|
|
|
|
for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageInterfaceType[Index] = RstHob->RstCrConfiguration[Index].DeviceInterface;
|
|
mPchNvsAreaProtocol.Area->RstPcieStoragePmCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].PmCapPtr;
|
|
mPchNvsAreaProtocol.Area->RstPcieStoragePcieCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].PcieCapPtr;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageL1ssCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].L1ssCapPtr;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl2[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointL1ssControl2;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl1[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointL1ssControl1;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageLtrCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].LtrCapPtr;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageEpLtrData[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointLtrData;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageEpLctlData16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointLctlData16;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageEpDctlData16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointDctlData16;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageEpDctl2Data16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointDctl2Data16;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageRpDctl2Data16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].RootPortDctl2Data16;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBar[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixTableBar;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBarValue[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixTableBarValue;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBar[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixPbaBar;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBarValue[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixPbaBarValue;
|
|
mPchNvsAreaProtocol.Area->RstPcieStorageRootPortNum[Index] = RstHob->RstCrConfiguration[Index].RootPortNum;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update the Hybrid storage location NVS Area if Hybrid Storage device is present
|
|
**/
|
|
EFI_STATUS
|
|
UpdateHybridStorageLocation (
|
|
VOID
|
|
)
|
|
{
|
|
VOID *Hob;
|
|
PCH_HYBRIDSTORAGE_HOB *HybridStorageHob;
|
|
|
|
Hob = GetFirstGuidHob (&gHybridStorageHobGuid);
|
|
if (Hob == NULL) {
|
|
mPchNvsAreaProtocol.Area->HybridStorageCpuRpLocation = 0xFF;
|
|
mPchNvsAreaProtocol.Area->HybridStorageCpuAttachPchRpLocation = 0xFF;
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
HybridStorageHob = (PCH_HYBRIDSTORAGE_HOB *) GET_GUID_HOB_DATA (Hob);
|
|
mPchNvsAreaProtocol.Area->HybridStorageLocation = HybridStorageHob->HybridStorageLocation;
|
|
mPchNvsAreaProtocol.Area->HybridStorageCpuRpLocation = HybridStorageHob->HybridStorageCpuRpLocation;
|
|
mPchNvsAreaProtocol.Area->HybridStorageCpuAttachPchRpLocation = HybridStorageHob->HybridStorageCpuAttachPchRpLocation;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
PCH ACPI initialization before Boot Sript Table is closed
|
|
It update ACPI table and ACPI NVS area.
|
|
|
|
@param[in] Event A pointer to the Event that triggered the callback.
|
|
@param[in] Context A pointer to private data registered with the callback function.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PchAcpiOnEndOfDxe (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() Start\n"));
|
|
|
|
///
|
|
/// Closed the event to avoid call twice when launch shell
|
|
///
|
|
gBS->CloseEvent (Event);
|
|
|
|
//
|
|
// Init HDA Audio ACPI tables
|
|
//
|
|
PchHdAudioAcpiInit ();
|
|
//
|
|
// Update ASL definitions for SerialIo devices.
|
|
//
|
|
UpdateSerialIoAcpiData ();
|
|
UpdateCnviAcpiData ();
|
|
#if FixedPcdGet8(PcdEmbeddedEnable) == 0x1
|
|
UpdateTimedGpioSetup();
|
|
#endif
|
|
|
|
UpdateThcAcpiData ();
|
|
UpdateScsAcpiData ();
|
|
//
|
|
// Update Pch Nvs Area
|
|
//
|
|
PchUpdateNvsArea ();
|
|
|
|
//
|
|
// Patch PchNvsArea Address
|
|
//
|
|
PatchPchNvsAreaAddress ();
|
|
|
|
DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() End\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Initialize Pch acpi
|
|
@param[in] ImageHandle Handle for the image of this driver
|
|
|
|
@retval EFI_SUCCESS The function completed successfully
|
|
@retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchAcpiInit (
|
|
IN EFI_HANDLE ImageHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_EVENT EndOfDxeEvent;
|
|
|
|
DEBUG ((DEBUG_INFO, "Install PCH NVS protocol\n"));
|
|
|
|
Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (PCH_NVS_AREA), (VOID **) &mPchNvsAreaProtocol.Area);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
ZeroMem ((VOID *) mPchNvsAreaProtocol.Area, sizeof (PCH_NVS_AREA));
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&ImageHandle,
|
|
&gPchNvsAreaProtocolGuid,
|
|
&mPchNvsAreaProtocol,
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
///
|
|
/// Update the NVS Area after RST PCIe Storage Remapping
|
|
///
|
|
PchUpdateNvsAreaAfterRemapping ();
|
|
|
|
UpdateHybridStorageLocation ();
|
|
//
|
|
// Register an end of DXE event for PCH ACPI to do tasks before invoking any UEFI drivers,
|
|
// applications, or connecting consoles,...
|
|
//
|
|
Status = gBS->CreateEventEx (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
PchAcpiOnEndOfDxe,
|
|
NULL,
|
|
&gEfiEndOfDxeEventGroupGuid,
|
|
&EndOfDxeEvent
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
Update NVS area for PCIe root ports.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
PcieRpUpdateNvsArea (
|
|
VOID
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
|
|
for (Index = 0; Index < PCH_MAX_PCIE_CLOCKS; Index++) {
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[Index] = mPchConfigHob->PcieRp.PcieClock[Index].Usage;
|
|
mPchNvsAreaProtocol.Area->ClockReq[Index] = mPchConfigHob->PcieRp.PcieClock[Index].ClkReq;
|
|
}
|
|
//todo: to revisit the change for more generic
|
|
if ((IsAdlPch () && IsPchS ())
|
|
) {
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[0] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[1] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[2] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[3] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[4] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[5] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[6] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[7] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[8] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[9] = 0x7;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[10] = 0x0;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[11] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[12] = 0x10;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[13] = 0x24;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[14] = 0x8;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[15] = 0x4;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[16] = 0xFF;
|
|
mPchNvsAreaProtocol.Area->ClockToRootPortMap[17] = 0xFF;
|
|
}
|
|
mPchNvsAreaProtocol.Area->ClkreqIpcCmdSupported = (UINT8)mPchConfigHob->PcieRp.ClkreqIpcCmdSupport;
|
|
}
|
|
|
|
/**
|
|
Updates USB related fields in NVS area.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
UsbUpdateNvsArea (
|
|
VOID
|
|
)
|
|
{
|
|
UINT64 XdciPciBase;
|
|
UINT64 XdciBar;
|
|
UINT8 ClearXdciBar = FALSE;
|
|
UINT16 PciMemConfig;
|
|
|
|
//
|
|
// Saving GCTL value into PCH NVS area
|
|
//
|
|
XdciPciBase = PchXdciPciCfgBase ();
|
|
|
|
//
|
|
// Determine Base address for Base address register (Offset 0x10)
|
|
//
|
|
if (PciSegmentRead32 (XdciPciBase) != 0xFFFFFFFF) {
|
|
XdciBar = PciSegmentRead32 (XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET) & 0xFFFFFFF0;
|
|
|
|
if ((PciSegmentRead32 (XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET) & B_PCI_BAR_MEMORY_TYPE_MASK) == B_PCI_BAR_MEMORY_TYPE_64) {
|
|
XdciBar += (UINT64) PciSegmentRead32 (XdciPciBase + (PCI_BASE_ADDRESSREG_OFFSET + 4)) << 32;
|
|
}
|
|
|
|
if (XdciBar == 0x0) {
|
|
ClearXdciBar = TRUE;
|
|
PciSegmentWrite32 ((XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET), PcdGet32 (PcdSiliconInitTempMemBaseAddr));
|
|
XdciBar = PciSegmentRead32 (XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET) & 0xFFFFFFF0;
|
|
|
|
if ((PciSegmentRead32 (XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET) & B_PCI_BAR_MEMORY_TYPE_MASK) == B_PCI_BAR_MEMORY_TYPE_64) {
|
|
XdciBar += (UINT64) PciSegmentRead32 (XdciPciBase + (PCI_BASE_ADDRESSREG_OFFSET + 4)) << 32;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Enable Pci Memconfig to read the correct value for GCTL register
|
|
//
|
|
PciMemConfig = PciSegmentRead16 (XdciPciBase + PCI_COMMAND_OFFSET);
|
|
PciSegmentWrite16 (XdciPciBase + PCI_COMMAND_OFFSET, PciMemConfig | (EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
|
|
|
|
mPchNvsAreaProtocol.Area->PchxDCIPwrDnScale = MmioRead32(XdciBar + R_XDCI_MEM_GCTL);
|
|
DEBUG ((DEBUG_INFO, "PchxDCIPwrDnScale 0x%x\n", (UINT64)mPchNvsAreaProtocol.Area->PchxDCIPwrDnScale));
|
|
//
|
|
// Disable Pci Memconfig & clear Base address
|
|
//
|
|
PciSegmentWrite16(XdciPciBase + PCI_COMMAND_OFFSET, PciMemConfig);
|
|
|
|
if (ClearXdciBar == TRUE) {
|
|
PciSegmentWrite32 ((XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET), 0x0);
|
|
PciSegmentWrite32 ((XdciPciBase + (PCI_BASE_ADDRESSREG_OFFSET + 4)), 0x0);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update PCH USB ports count
|
|
//
|
|
mPchNvsAreaProtocol.Area->PchUsb2PortCount = (UINT8) GetPchUsb2MaxPhysicalPortNum ();
|
|
mPchNvsAreaProtocol.Area->PchUsb3PortCount = (UINT8) GetPchXhciMaxUsb3PortNum ();
|
|
|
|
//
|
|
// Update USB Audio Offload enable status
|
|
//
|
|
mPchNvsAreaProtocol.Area->UaolEnabled = (UINT8) mPchConfigHob->General.UaolEnable;
|
|
}
|
|
|
|
/**
|
|
Update ASL object before Boot
|
|
|
|
@retval EFI_STATUS
|
|
@retval EFI_NOT_READY The Acpi protocols are not ready.
|
|
**/
|
|
EFI_STATUS
|
|
PchUpdateNvsArea (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
UINT32 HpetBaseAdress;
|
|
GPIO_GROUP GroupToGpeDwX[3];
|
|
UINT32 GroupDw[3];
|
|
UINTN RpDev;
|
|
UINTN RpFun;
|
|
UINT32 Data32;
|
|
PCH_POLICY_PROTOCOL *PchPolicy;
|
|
GPIO_DXE_CONFIG *GpioDxeConfig;
|
|
UINT16 TcoBase;
|
|
|
|
///
|
|
/// Get PCH Policy Protocol
|
|
///
|
|
Status = gBS->LocateProtocol (&gPchPolicyProtocolGuid, NULL, (VOID **)&PchPolicy);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
///
|
|
/// Get GPIO DXE Config Block
|
|
///
|
|
Status = GetConfigBlock ((VOID *)PchPolicy, &gGpioDxeConfigGuid, (VOID *)&GpioDxeConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Update ASL PCIE port address according to root port device and function
|
|
//
|
|
for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
|
|
RpDev = PchPcieRpDevNumber (Index);
|
|
RpFun = PchPcieRpFuncNumber (Index);
|
|
Data32 = ((UINT8) RpDev << 16) | (UINT8) RpFun;
|
|
mPchNvsAreaProtocol.Area->RpAddress[Index] = Data32;
|
|
|
|
//
|
|
// Update Maximum Snoop Latency and Maximum No-Snoop Latency values for PCIE
|
|
//
|
|
mPchNvsAreaProtocol.Area->PcieLtrMaxSnoopLatency[Index] = mPchConfigHob->PcieRp.RootPort[Index].PcieRpCommonConfig.PcieRpLtrConfig.LtrMaxSnoopLatency;
|
|
mPchNvsAreaProtocol.Area->PcieLtrMaxNoSnoopLatency[Index] = mPchConfigHob->PcieRp.RootPort[Index].PcieRpCommonConfig.PcieRpLtrConfig.LtrMaxNoSnoopLatency;
|
|
}
|
|
|
|
//
|
|
// Update PCHS.
|
|
//
|
|
mPchNvsAreaProtocol.Area->PchSeries = PchSeries ();
|
|
//
|
|
// Update PCHG.
|
|
//
|
|
mPchNvsAreaProtocol.Area->PchGeneration = (UINT16) PchGeneration ();
|
|
//
|
|
// Update PSTP.
|
|
//
|
|
mPchNvsAreaProtocol.Area->PchStepping = (UINT16) PchStepping ();
|
|
//
|
|
// Update HPET base address.
|
|
//
|
|
PchHpetBaseGet (&HpetBaseAdress);
|
|
mPchNvsAreaProtocol.Area->HPTE = TRUE; // @todo remove the NVS, since it's always enabled.
|
|
mPchNvsAreaProtocol.Area->HPTB = HpetBaseAdress;
|
|
//
|
|
// Update SBREG_BAR.
|
|
//
|
|
mPchNvsAreaProtocol.Area->SBRG = PCH_PCR_BASE_ADDRESS;
|
|
|
|
//
|
|
// Update base address
|
|
//
|
|
mPchNvsAreaProtocol.Area->PMBS = PmcGetAcpiBase ();
|
|
mPchNvsAreaProtocol.Area->PWRM = PmcGetPwrmBase ();
|
|
PchTcoBaseGet (&TcoBase);
|
|
mPchNvsAreaProtocol.Area->TcoBase = TcoBase;
|
|
|
|
//
|
|
// Update PCH PID info
|
|
//
|
|
mPchNvsAreaProtocol.Area->IclkPid = PchPcrGetPid (PchIpIclk);
|
|
|
|
//
|
|
// Update GPIO device ACPI variables
|
|
//
|
|
mPchNvsAreaProtocol.Area->SGIR = mPchConfigHob->Interrupt.GpioIrqRoute;
|
|
mPchNvsAreaProtocol.Area->GPHD = (UINT8)GpioDxeConfig->HideGpioAcpiDevice;
|
|
|
|
//
|
|
// Update GPP_X to GPE_DWX mapping.
|
|
//
|
|
GpioGetGroupDwToGpeDwX (
|
|
&GroupToGpeDwX[0], &GroupDw[0],
|
|
&GroupToGpeDwX[1], &GroupDw[1],
|
|
&GroupToGpeDwX[2], &GroupDw[2]
|
|
);
|
|
|
|
//
|
|
// GEI0/1/2 and GED0/1/2 are objects for informing how GPIO groups are mapped to GPE0.
|
|
// If Group is mapped to 1-Tier GPE information is also stored on what Group DW
|
|
// is mapped to GPE_DWx. Because GPE_DWx register is 32 bits large if groups have more than
|
|
// 32 pads only part of it can be mapped.
|
|
//
|
|
// GEIx - GroupIndex mapped to GPE0_DWx
|
|
// GEDx - DoubleWorld part of Group: 0 - pins 31-0, 1 - pins 63-32, ...
|
|
//
|
|
mPchNvsAreaProtocol.Area->GEI0 = (UINT8) GpioGetGroupIndexFromGroup (GroupToGpeDwX[0]);
|
|
mPchNvsAreaProtocol.Area->GEI1 = (UINT8) GpioGetGroupIndexFromGroup (GroupToGpeDwX[1]);
|
|
mPchNvsAreaProtocol.Area->GEI2 = (UINT8) GpioGetGroupIndexFromGroup (GroupToGpeDwX[2]);
|
|
mPchNvsAreaProtocol.Area->GED0 = (UINT8) GroupDw[0];
|
|
mPchNvsAreaProtocol.Area->GED1 = (UINT8) GroupDw[1];
|
|
mPchNvsAreaProtocol.Area->GED2 = (UINT8) GroupDw[2];
|
|
|
|
|
|
PcieRpUpdateNvsArea ();
|
|
|
|
//
|
|
// SATA configuration.
|
|
//
|
|
if(PciSegmentRead16 (SataPciCfgBase (SATA_1_CONTROLLER_INDEX) + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
|
|
mPchNvsAreaProtocol.Area->SataPortPresence = 0;
|
|
} else {
|
|
mPchNvsAreaProtocol.Area->SataPortPresence = GetSataPortPresentStatus (SATA_1_CONTROLLER_INDEX);
|
|
}
|
|
DEBUG ((DEBUG_INFO, "SataPortPresence: 0x%x\n", mPchNvsAreaProtocol.Area->SataPortPresence));
|
|
|
|
//
|
|
// CPU SKU
|
|
//
|
|
mPchNvsAreaProtocol.Area->CpuSku = GetCpuSku ();
|
|
mPchNvsAreaProtocol.Area->PsOnEnable = (UINT8)mPchConfigHob->Pm.PsOnEnable;
|
|
|
|
for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
|
|
mPchNvsAreaProtocol.Area->LtrEnable[Index] = (UINT8)mPchConfigHob->PcieRp.RootPort[Index].PcieRpCommonConfig.LtrEnable;
|
|
}
|
|
|
|
mPchNvsAreaProtocol.Area->GBES = IsGbePresent ();
|
|
|
|
//
|
|
// Update PCH Trace Hub Mode
|
|
//
|
|
mPchNvsAreaProtocol.Area->PchTraceHubMode = (UINT8) mPchConfigHob->PchTraceHub.PchTraceHubMode;
|
|
|
|
UsbUpdateNvsArea ();
|
|
|
|
mPchNvsAreaProtocol.Area->AcpiL6dPmeHandling = mPchConfigHob->General.AcpiL6dPmeHandling;
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Initialize PCH Nvs Area opeartion region.
|
|
|
|
@retval EFI_SUCCESS initialized successfully
|
|
@retval EFI_NOT_FOUND Nvs Area operation region is not found
|
|
**/
|
|
EFI_STATUS
|
|
PatchPchNvsAreaAddress (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 Address;
|
|
UINT16 Length;
|
|
|
|
Address = (UINT32) (UINTN) mPchNvsAreaProtocol.Area;
|
|
Length = (UINT16) sizeof (PCH_NVS_AREA);
|
|
DEBUG ((DEBUG_INFO, "PatchPchNvsAreaAddress: PCH NVS Address %x Length %x\n", Address, Length));
|
|
Status = UpdateNameAslCode (SIGNATURE_32 ('P','N','V','B'), &Address, sizeof (Address));
|
|
ASSERT_EFI_ERROR (Status);
|
|
Status = UpdateNameAslCode (SIGNATURE_32 ('P','N','V','L'), &Length, sizeof (Length));
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|