/** @file
Copyright (c) 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#define PCH_DO_STRINGIFY(x) #x
#define PCH_STRINGIFY(x) PCH_DO_STRINGIFY(x)
//
// This module variables are used for cache the static result.
// @note: please pay attention to the PEI phase, the module variables on ROM
// and can't be modified.
//
GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLpcBaseAddr = 0;
GLOBAL_REMOVE_IF_UNREFERENCED PCH_STEPPING mPchStepping = PchSteppingMax;
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mIsPchSupported = 0xFF;
GLOBAL_REMOVE_IF_UNREFERENCED PCH_SERIES mPchSeries = PchUnknownSeries;
GLOBAL_REMOVE_IF_UNREFERENCED PCH_GENERATION mPchGeneration = PchUnknownGeneration;
/**
Return Pch stepping type
@retval PCH_STEPPING Pch stepping type
**/
PCH_STEPPING
EFIAPI
PchStepping (
VOID
)
{
UINT8 RevId;
UINT16 LpcDeviceId;
UINTN LpcBaseAddress;
if (mPchStepping != PchSteppingMax) {
return mPchStepping;
}
LpcBaseAddress = MmPciBase (
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_LPC,
PCI_FUNCTION_NUMBER_PCH_LPC
);
RevId = MmioRead8 (LpcBaseAddress + PCI_REVISION_ID_OFFSET);
LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
if (IS_PCH_H_LPC_DEVICE_ID (LpcDeviceId)) {
switch (RevId) {
case V_PCH_LPC_RID_0:
mPchStepping = PchHA0;
return PchHA0;
case V_PCH_LPC_RID_10:
mPchStepping = PchHB0;
return PchHB0;
case V_PCH_LPC_RID_20:
mPchStepping = PchHC0;
return PchHC0;
case V_PCH_LPC_RID_30:
mPchStepping = PchHD0;
return PchHD0;
case V_PCH_LPC_RID_31:
mPchStepping = PchHD1;
return PchHD1;
default:
DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %a and above\n", PCH_STRINGIFY(PCH_H_MIN_SUPPORTED_STEPPING))) ;
return PchSteppingMax;
}
}
if (IS_PCH_LP_LPC_DEVICE_ID (LpcDeviceId)) {
switch (RevId) {
#ifdef SIMICS_FLAG
case V_PCH_LPC_RID_0:
mPchStepping = PchLpA0;
return PchLpA0;
#endif
case V_PCH_LPC_RID_10:
mPchStepping = PchLpB0;
return PchLpB0;
case V_PCH_LPC_RID_11:
mPchStepping = PchLpB1;
return PchLpB1;
case V_PCH_LPC_RID_20:
mPchStepping = PchLpC0;
return PchLpC0;
case V_PCH_LPC_RID_21:
mPchStepping = PchLpC1;
return PchLpC1;
default:
DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %a and above\n", PCH_STRINGIFY(PCH_LP_MIN_SUPPORTED_STEPPING))) ;
return PchSteppingMax;
}
}
#ifdef SKXD_EN
if (IS_PCH_LBG_D_SSKU_LPC_DEVICE_ID (LpcDeviceId)) {
switch (RevId) {
case V_PCH_LBG_LPC_RID_3:
return LbgB1_D;
default:
DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %s and above\n", PCH_STRINGIFY(V_PCH_LBG_LPC_RID_3)));
return PchSteppingMax;
}
}
#endif // SKXD_EN
if (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)) {
if (RevId == 0) {
return LbgA0;
} else {
switch (RevId) {
case V_PCH_LBG_LPC_RID_0:
return LbgA0;
case V_PCH_LBG_LPC_RID_2:
return LbgB0;
case V_PCH_LBG_LPC_RID_3:
return LbgB1;
case V_PCH_LBG_LPC_RID_4:
return LbgB2;
case V_PCH_LBG_LPC_RID_8:
return LbgS0;
case V_PCH_LBG_LPC_RID_9:
return LbgS1;
default:
DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %s and above\n", PCH_STRINGIFY(PCH_LBG_MIN_SUPPORTED_STEPPING)));
ASSERT (FALSE);
return PchSteppingMax;
}
}
}
return PchSteppingMax;
}
/**
Determine if PCH is supported
@retval TRUE PCH is supported
@retval FALSE PCH is not supported
**/
BOOLEAN
IsPchSupported (
VOID
)
{
UINT16 LpcDeviceId;
UINT16 LpcVendorId;
UINTN LpcBaseAddress;
if (mIsPchSupported != 0xFF) {
return (BOOLEAN) mIsPchSupported;
}
LpcBaseAddress = MmPciBase (
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_LPC,
PCI_FUNCTION_NUMBER_PCH_LPC
);
LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
LpcVendorId = MmioRead16 (LpcBaseAddress + PCI_VENDOR_ID_OFFSET);
///
/// Verify that this is a supported chipset
///
if ((LpcVendorId == V_PCH_LPC_VENDOR_ID) &&
(IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)))
{
mIsPchSupported = TRUE;
return TRUE;
} else {
DEBUG ((DEBUG_ERROR, "PCH code doesn't support the LpcDeviceId: 0x%04x!\n", LpcDeviceId));
mIsPchSupported = FALSE;
return FALSE;
}
}
/**
Return Pch Series
@retval PCH_SERIES Pch Series
**/
PCH_SERIES
EFIAPI
GetPchSeries (
VOID
)
{
UINT16 LpcDeviceId;
UINT32 PchSeries;
UINTN LpcBaseAddress;
if (mPchSeries != PchUnknownSeries) {
return mPchSeries;
}
LpcBaseAddress = MmPciBase (
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_LPC,
PCI_FUNCTION_NUMBER_PCH_LPC
);
LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
if (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)) {
PchSeries = PchH;
} else if (IS_PCH_LP_LPC_DEVICE_ID (LpcDeviceId)) {
PchSeries = PchLp;
} else {
PchSeries = PchUnknownSeries;
DEBUG ((DEBUG_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
ASSERT (FALSE);
}
mPchSeries = PchSeries;
return PchSeries;
}
/**
Return Pch Generation
@retval PCH_GENERATION Pch Generation
**/
PCH_GENERATION
EFIAPI
GetPchGeneration (
VOID
)
{
UINT16 LpcDeviceId;
UINT32 PchGen;
UINTN LpcBaseAddress;
if (mPchGeneration != PchUnknownGeneration) {
return mPchGeneration;
}
LpcBaseAddress = MmPciBase (
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_LPC,
PCI_FUNCTION_NUMBER_PCH_LPC
);
LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
if (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)) {
PchGen = SklPch;
} else {
PchGen = PchUnknownGeneration;
DEBUG ((DEBUG_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
ASSERT (FALSE);
}
mPchGeneration = PchGen;
return PchGen;
}
/**
Get Pch Maximum Pcie Root Port Number
@retval Pch Maximum Pcie Root Port Number
**/
UINT8
EFIAPI
GetPchMaxPciePortNum (
VOID
)
{
PCH_SERIES PchSeries;
PchSeries = GetPchSeries ();
switch (PchSeries) {
case PchLp:
return PCH_LP_PCIE_MAX_ROOT_PORTS;
case PchH:
return PCH_H_PCIE_MAX_ROOT_PORTS;
default:
return 0;
}
}
/**
Get Pch Maximum Sata Port Number
@retval Pch Maximum Sata Port Number
**/
UINT8
EFIAPI
GetPchMaxSataPortNum (
VOID
)
{
PCH_SERIES PchSeries;
PchSeries = GetPchSeries ();
switch (PchSeries) {
case PchLp:
return PCH_LP_AHCI_MAX_PORTS;
case PchH:
return PCH_H_AHCI_MAX_PORTS;
default:
return 0;
}
}
/**
Get Pch Usb Maximum Physical Port Number
@retval Pch Usb Maximum Physical Port Number
**/
UINT8
EFIAPI
GetPchUsbMaxPhysicalPortNum (
VOID
)
{
PCH_SERIES PchSeries;
PchSeries = GetPchSeries ();
switch (PchSeries) {
case PchLp:
return PCH_LP_XHCI_MAX_USB2_PHYSICAL_PORTS;
case PchH:
return PCH_H_XHCI_MAX_USB2_PHYSICAL_PORTS;
default:
return 0;
}
}
/**
Get Pch Maximum Usb2 Port Number of XHCI Controller
@retval Pch Maximum Usb2 Port Number of XHCI Controller
**/
UINT8
EFIAPI
GetPchXhciMaxUsb2PortNum (
VOID
)
{
PCH_SERIES PchSeries;
PchSeries = GetPchSeries ();
switch (PchSeries) {
case PchLp:
return PCH_LP_XHCI_MAX_USB2_PORTS;
case PchH:
return PCH_H_XHCI_MAX_USB2_PORTS;
default:
return 0;
}
}
/**
Get Pch Maximum Usb3 Port Number of XHCI Controller
@retval Pch Maximum Usb3 Port Number of XHCI Controller
**/
UINT8
EFIAPI
GetPchXhciMaxUsb3PortNum (
VOID
)
{
PCH_SERIES PchSeries;
PchSeries = GetPchSeries ();
switch (PchSeries) {
case PchLp:
return PCH_LP_XHCI_MAX_USB3_PORTS;
case PchH:
return PCH_H_XHCI_MAX_USB3_PORTS;
default:
return 0;
}
}
/**
Determine if sSata controller is present or not
@param[in] None
@retval TRUE or FALSE
**/
BOOLEAN
EFIAPI
GetIsPchsSataPresent (
VOID
)
{
UINT16 sSataDeviceId;
UINTN sSataBaseAddress;
sSataBaseAddress = MmPciBase (
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_EVA,
PCI_FUNCTION_NUMBER_PCH_SSATA
);
sSataDeviceId = MmioRead16 ( sSataBaseAddress + PCI_DEVICE_ID_OFFSET);
if (sSataDeviceId != 0xffff){
return TRUE;
}
return FALSE;
}
/**
Get Pch Maximum sSata Controller Number
@param[in] None
@retval Pch Maximum sSata Controller Number
**/
UINT8
EFIAPI
GetPchMaxsSataPortNum (
VOID
)
{
return PCH_SSATA_MAX_PORTS;
}
/**
Get Pch Maximum Sata Controller Number
@param[in] None
@retval Pch Maximum Sata Controller Number
**/
UINT8
EFIAPI
GetPchMaxsSataControllerNum (
VOID
)
{
return PCH_SSATA_MAX_CONTROLLERS;
}
/**
Return Pch Lpc Device Id
@retval UINT16 Pch DeviceId
**/
UINT16
EFIAPI
GetPchLpcDeviceId (
VOID
)
{
UINTN LpcBaseAddress;
if (mPchSeries != PchUnknownSeries) {
return mPchSeries;
}
LpcBaseAddress = mLpcBaseAddr;
if (LpcBaseAddress == 0) {
LpcBaseAddress = MmPciBase (
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_LPC,
PCI_FUNCTION_NUMBER_PCH_LPC
);
mLpcBaseAddr = LpcBaseAddress;
}
return MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
}