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