summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/LynxPoint/Pcie/Smm/PchPcieSmm.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/Pcie/Smm/PchPcieSmm.c')
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Pcie/Smm/PchPcieSmm.c388
1 files changed, 388 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/LynxPoint/Pcie/Smm/PchPcieSmm.c b/ReferenceCode/Chipset/LynxPoint/Pcie/Smm/PchPcieSmm.c
new file mode 100644
index 0000000..720fcfc
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/Pcie/Smm/PchPcieSmm.c
@@ -0,0 +1,388 @@
+/** @file
+ PCH Pcie SMM Driver Entry
+
+@copyright
+ Copyright (c) 2010 - 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 "PchPcieSmm.h"
+
+//
+// Global variables
+//
+EFI_SMM_SYSTEM_TABLE *mSmst;
+EFI_SMM_BASE_PROTOCOL *mSmmBase;
+PCH_PCI_EXPRESS_CONFIG *mPciExpressConfig;
+PCH_PWR_OPT_CONFIG *mPchPwrOptConfig;
+UINT8 *mRevision;
+UINT8 mBusNumber;
+
+/**
+ Program Common Clock and ASPM of Downstream Devices
+
+ @param[in] Function Pcie Root Port Function Number
+
+ @retval EFI_SUCCESS Function complete successfully
+**/
+EFI_STATUS
+PchPcieSmi (
+ IN UINT8 Function
+ )
+{
+ UINT16 Data16;
+ UINT8 SecBus;
+ UINT8 SubBus;
+ BOOLEAN L1SubstatesSupported;
+ EFI_HANDLE Handle;
+ PCH_PCIE_EXPRESS_L1SUBSTATES_CONTROL L1SubVal;
+ UINT8 RootPortNumber;
+ UINT32 RootComplexBar;
+ UINTN PciD31F0RegBase;
+ BOOLEAN LtrSupported;
+ PCH_SERIES PchSeries;
+
+ Handle = NULL;
+ PchSeries = GetPchSeries();
+ LtrSupported = TRUE;
+ PciD31F0RegBase = MmPciAddress (
+ 0,
+ mBusNumber,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ 0
+ );
+ RootComplexBar = MmioRead32 (PciD31F0RegBase + R_PCH_LPC_RCBA) & B_PCH_LPC_RCBA_BAR;
+ RootPortNumber = GetPchPcieRpNumber(RootComplexBar, Function);
+
+ if (RootPortNumber == 0xFF) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Check for presense detect state
+ ///
+ Data16 = MmioRead16 (MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, Function, R_PCH_PCIE_SLSTS));
+ Data16 &= B_PCH_PCIE_SLSTS_PDS;
+ if (Data16) {
+ SecBus = MmioRead8 (MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, Function, 0x19));
+ SubBus = MmioRead8 (MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, Function, 0x1A));
+ PchPcieInitRootPortDownstreamDevices (0, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, Function, SecBus, SubBus, NULL);
+ MmioWrite8 (MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, Function, 0x19), SecBus);
+ MmioWrite8 (MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, Function, 0x1A), SubBus);
+ L1SubVal = PchPcieL1SubstatesL1_1_2;
+ if ((*mRevision) >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_2) {
+ L1SubVal = mPciExpressConfig->RootPort[RootPortNumber].L1Substates;
+ }
+ PcieSetPm (
+ 0,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ Function,
+ mPciExpressConfig->RootPort[RootPortNumber].Aspm,
+ mPciExpressConfig->NumOfDevAspmOverride,
+ mPciExpressConfig->DevAspmOverride,
+ mPciExpressConfig->TempRootPortBusNumMin,
+ mPciExpressConfig->TempRootPortBusNumMax,
+ mPchPwrOptConfig->NumOfDevLtrOverride,
+ mPchPwrOptConfig->DevLtrOverride,
+ &(mPchPwrOptConfig->PchPwrOptPcie[RootPortNumber]),
+ &L1SubstatesSupported,
+ L1SubVal,
+ *mRevision,
+ FALSE,
+ FALSE,
+ FALSE,
+ &LtrSupported
+ );
+
+ if(!LtrSupported && (PchSeries == PchLp)) {
+ MmioAndThenOr32 ( (RootComplexBar + 0x3320), 0, 0x00010003);
+ }
+ } else {
+ ///
+ /// Clear CCC and LTSP bits when PCIe Card hot unplugged
+ ///
+ MmioAnd32 (MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, Function, R_PCH_PCIE_MPC2), (UINT32) ~BIT6);
+ MmioAnd16 (MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, Function, R_PCH_PCIE_LCTL), (UINT16) ~B_PCH_PCIE_LCTL_CCC);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ PCIE Hotplug SMI call back function for each Root port
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] DispatchContext Pointer to the dispatch function's context.
+ The DispatchContext fields are filled in by the dispatching driver
+ prior to invoke this dispatch function
+**/
+VOID
+EFIAPI
+PchPcieSmiHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_ICHN_DISPATCH_EX_CONTEXT *DispatchContext
+ )
+{
+ PchPcieSmi ((UINT8) (DispatchContext->Type - IchnExPcie0Hotplug));
+ return;
+}
+
+/**
+ PCIE Link Active State Change Hotplug SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] DispatchContext Pointer to the dispatch function's context.
+ The DispatchContext fields are filled in by the dispatching driver
+ prior to invoke this dispatch function
+**/
+VOID
+EFIAPI
+PchPcieLinkActiveStateChange (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_ICHN_DISPATCH_EX_CONTEXT *DispatchContext
+ )
+{
+ return;
+}
+
+/**
+ Register PCIE Hotplug SMI dispatch function to handle Hotplug enabling
+
+ @param[in] ImageHandle The image handle of this module
+ @param[in] SystemTable The EFI System Table
+
+ @retval EFI_SUCCESS The function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+InitializePchPcieSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINT8 Data8;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINTN RPBase;
+ EFI_HANDLE PcieHandle;
+ static CONST EFI_SMM_ICHN_EX_SMI_TYPE PchHPcieHandlerList[LPTH_PCIE_MAX_ROOT_PORTS * 2] = {
+ IchnExPcie0Hotplug,
+ IchnExPcie1Hotplug,
+ IchnExPcie2Hotplug,
+ IchnExPcie3Hotplug,
+ IchnExPcie4Hotplug,
+ IchnExPcie5Hotplug,
+ IchnExPcie6Hotplug,
+ IchnExPcie7Hotplug,
+ IchnExPcie0LinkActive,
+ IchnExPcie1LinkActive,
+ IchnExPcie2LinkActive,
+ IchnExPcie3LinkActive,
+ IchnExPcie4LinkActive,
+ IchnExPcie5LinkActive,
+ IchnExPcie6LinkActive,
+ IchnExPcie7LinkActive
+ };
+ static CONST EFI_SMM_ICHN_EX_SMI_TYPE PchLpPcieHandlerList[LPTLP_PCIE_MAX_ROOT_PORTS * 2] = {
+ IchnExPcie0Hotplug,
+ IchnExPcie1Hotplug,
+ IchnExPcie2Hotplug,
+ IchnExPcie3Hotplug,
+ IchnExPcie4Hotplug,
+ IchnExPcie5Hotplug,
+ IchnExPcie0LinkActive,
+ IchnExPcie1LinkActive,
+ IchnExPcie2LinkActive,
+ IchnExPcie3LinkActive,
+ IchnExPcie4LinkActive,
+ IchnExPcie5LinkActive
+ };
+ EFI_SMM_ICHN_DISPATCH_EX_PROTOCOL *mIchnDispatch;
+ EFI_SMM_ICHN_DISPATCH_EX_CONTEXT PchPcieContext;
+ UINTN PortIndex;
+ DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy;
+ PCH_PCIE_DEVICE_LTR_OVERRIDE *DevLtrOverrideTbl;
+ UINT32 TableSize;
+ PCH_SERIES PchSeries;
+
+ DEBUG ((EFI_D_INFO, "InitializePchPcieSmm() Start\n"));
+
+ PchSeries = GetPchSeries();
+ DevLtrOverrideTbl = NULL;
+ ///
+ /// Locate SmmBase protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Initialize our module variables
+ ///
+ Status = mSmmBase->GetSmstLocation (mSmmBase, &mSmst);
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Locate the ICHnEx Dispatch protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiSmmIchnDispatchExProtocolGuid, NULL, (VOID **) &mIchnDispatch);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gDxePchPlatformPolicyProtocolGuid, NULL, (VOID **) &PchPlatformPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = mSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (PCH_PCI_EXPRESS_CONFIG),
+ (VOID **) &mPciExpressConfig
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = mSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (PCH_PWR_OPT_CONFIG),
+ (VOID **) &mPchPwrOptConfig
+ );
+ ASSERT_EFI_ERROR (Status);
+ mPciExpressConfig->NumOfDevAspmOverride = PchPlatformPolicy->PciExpressConfig->NumOfDevAspmOverride;
+ TableSize = PchPlatformPolicy->PciExpressConfig->NumOfDevAspmOverride * sizeof (PCH_PCIE_DEVICE_ASPM_OVERRIDE);
+
+ ///
+ /// Allocate and copy ASPM override table to SMM memory
+ ///
+ Status = mSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ TableSize,
+ (VOID **) &mPciExpressConfig->DevAspmOverride
+ );
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (mPciExpressConfig->DevAspmOverride, PchPlatformPolicy->PciExpressConfig->DevAspmOverride, TableSize);
+
+ Status = mSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (PchPlatformPolicy->Revision),
+ &mRevision
+ );
+ ASSERT_EFI_ERROR (Status);
+ *mRevision = PchPlatformPolicy->Revision;
+ mBusNumber = PchPlatformPolicy->BusNumber;
+ ///
+ /// Allocate and copy LTR override table to SMM memory
+ ///
+ mPchPwrOptConfig->NumOfDevLtrOverride = PchPlatformPolicy->PwrOptConfig->NumOfDevLtrOverride;
+ DevLtrOverrideTbl = PchPlatformPolicy->PwrOptConfig->DevLtrOverride;
+ if ((DevLtrOverrideTbl != NULL) && (PchPlatformPolicy->PwrOptConfig->NumOfDevLtrOverride != 0)) {
+ TableSize = PchPlatformPolicy->PwrOptConfig->NumOfDevLtrOverride * sizeof (PCH_PCIE_DEVICE_LTR_OVERRIDE);
+ Status = mSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ TableSize,
+ (VOID **) &mPchPwrOptConfig->DevLtrOverride
+ );
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (mPchPwrOptConfig->DevLtrOverride, DevLtrOverrideTbl, TableSize);
+ }
+
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) {
+ mPciExpressConfig->RootPort[PortIndex].Aspm = PchPlatformPolicy->PciExpressConfig->RootPort[PortIndex].Aspm;
+ if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_2) {
+ mPciExpressConfig->RootPort[PortIndex].L1Substates = PchPlatformPolicy->PciExpressConfig->RootPort[PortIndex].L1Substates;
+ }
+ mPchPwrOptConfig->PchPwrOptPcie[PortIndex].LtrEnable = PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[PortIndex].LtrEnable;
+ mPchPwrOptConfig->PchPwrOptPcie[PortIndex].ObffEnable = PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[PortIndex].ObffEnable;
+ if (PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_7) {
+ mPchPwrOptConfig->PchPwrOptPcie[PortIndex].LtrMaxSnoopLatency = PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[PortIndex].LtrMaxSnoopLatency;
+ mPchPwrOptConfig->PchPwrOptPcie[PortIndex].LtrMaxNoSnoopLatency = PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[PortIndex].LtrMaxNoSnoopLatency;
+ }
+ }
+ ///
+ /// Locate the S3 resume scripting protocol
+ ///
+ INITIALIZE_SCRIPT (ImageHandle, SystemTable);
+
+ //
+ // Throught all PCIE root port function and register the SMI Handler for enabled ports.
+ //
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ RPBase = MmPciAddress (
+ 0,
+ 0,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ Index,
+ 0
+ );
+ //
+ // Skip the root port function which is not enabled
+ //
+ if (MmioRead32 (RPBase) == 0xFFFFFFFF) {
+ continue;
+ }
+
+ Data8 = MmioRead8 (RPBase + R_PCH_PCIE_SLCAP);
+ if (Data8 & B_PCH_PCIE_SLCAP_HPC) {
+ switch (PchSeries) {
+ case PchLp:
+ PchPcieContext.Type = PchLpPcieHandlerList[Index];
+ break;
+
+ case PchH:
+ PchPcieContext.Type = PchHPcieHandlerList[Index];
+ break;
+ default:
+ break;
+ }
+ PcieHandle = NULL;
+ Status = mIchnDispatch->Register (
+ mIchnDispatch,
+ PchPcieSmiHandlerFunction,
+ &PchPcieContext,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ switch (PchSeries) {
+ case PchLp:
+ PchPcieContext.Type = PchLpPcieHandlerList[Index + LPTLP_PCIE_MAX_ROOT_PORTS];
+ break;
+
+ case PchH:
+ PchPcieContext.Type = PchHPcieHandlerList[Index + LPTH_PCIE_MAX_ROOT_PORTS];
+ break;
+ default:
+ break;
+ }
+ Status = mIchnDispatch->Register (
+ mIchnDispatch,
+ PchPcieLinkActiveStateChange,
+ &PchPcieContext,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Data32Or = B_PCH_PCIE_MPC_HPME;
+ Data32And = (UINT32)~B_PCH_PCIE_MPC_HPME;
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_MPC),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "InitializePchPcieSmm() End\n"));
+
+ return EFI_SUCCESS;
+} \ No newline at end of file