summaryrefslogtreecommitdiff
path: root/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster')
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScAcpi.c74
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScHda.c288
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInit.c907
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInit.h267
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInitDxe.inf104
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScIosf.c35
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScIsh.c53
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScLpss.c283
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScPmc.c108
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScSata.c18
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScXdci.c18
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.c183
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.h320
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.inf81
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScPcieSmm.c328
15 files changed, 3067 insertions, 0 deletions
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScAcpi.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScAcpi.c
new file mode 100644
index 0000000000..b63a18b872
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScAcpi.c
@@ -0,0 +1,74 @@
+/** @file
+ This is the driver that initializes the Intel SC devices
+
+ Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScInit.h"
+
+/**
+ Update ASL object before Boot
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_STATUS
+ @retval EFI_NOT_READY The Acpi protocols are not ready.
+
+**/
+EFI_STATUS
+UpdateNvsArea (
+ IN SC_POLICY_HOB *ScPolicy
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN RpDev;
+ UINTN RpFun;
+ UINT32 Data32;
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea;
+ BXT_SERIES BxtSeries;
+ UINT8 MaxPciePortNum;
+ SC_PCIE_CONFIG *PcieRpConfig;
+
+ Status = GetConfigBlock ((VOID *) ScPolicy, &gPcieRpConfigGuid, (VOID *) &PcieRpConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = EFI_SUCCESS;
+ Status = gBS->LocateProtocol (
+ &gEfiGlobalNvsAreaProtocolGuid,
+ NULL,
+ (VOID **) &GlobalNvsArea
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Update ASL PCIE port address according to root port device and function
+ //
+ BxtSeries = GetBxtSeries ();
+ if ((BxtSeries == BxtP) || (BxtSeries == Bxt1)) {
+ MaxPciePortNum = GetScMaxPciePortNum ();
+ for (Index = 0; Index < MaxPciePortNum; Index++) {
+ Status = GetScPcieRpDevFun (Index, &RpDev, &RpFun);
+ ASSERT_EFI_ERROR (Status);
+
+ Data32 = ((UINT8) RpDev << 16) | (UINT8) RpFun;
+ GlobalNvsArea->Area->RpAddress[Index] = Data32;
+ //
+ // Update Maximum Snoop Latency and Maximum No-Snoop Latency values for PCIE
+ //
+ GlobalNvsArea->Area->PcieLtrMaxSnoopLatency[Index] = PcieRpConfig->RootPort[Index].LtrMaxSnoopLatency;
+ GlobalNvsArea->Area->PcieLtrMaxNoSnoopLatency[Index] = PcieRpConfig->RootPort[Index].LtrMaxNoSnoopLatency;
+ }
+ }
+
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScHda.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScHda.c
new file mode 100644
index 0000000000..16efcbe859
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScHda.c
@@ -0,0 +1,288 @@
+/** @file
+ Initializes the HD-Audio Controller and Codec.
+
+ Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScInit.h"
+#include <ScAccess.h>
+#include <Guid/Acpi.h>
+#include <Library/PcdLib.h>
+#include <Library/SteppingLib.h>
+#include <Private/Library/ScHdaLib.h>
+
+SC_HDA_NHLT_ENDPOINTS mScHdaNhltEndpoints[HdaEndpointMax] =
+{
+ {HdaDmicX2, FALSE},
+ {HdaDmicX4, FALSE},
+ {HdaBtRender, FALSE},
+ {HdaBtCapture, FALSE},
+ {HdaI2sRenderSKP, FALSE},
+ {HdaI2sCaptureSKP, FALSE},
+ {HdaI2sRenderHP, FALSE},
+ {HdaI2sCaptureHP, FALSE},
+ {HdaModem1Render, FALSE},
+ {HdaModem1Capture, FALSE},
+ {HdaModem2Render, FALSE},
+ {HdaModem2Capture, FALSE}
+};
+
+
+/**
+ Retrieves address of NHLT table from XSDT/RSDT.
+
+ @retval NHLT_ACPI_TABLE* Pointer to NHLT table if found
+ @retval NULL NHLT could not be found
+
+**/
+NHLT_ACPI_TABLE *
+LocateNhltAcpiTable (
+ VOID
+ )
+{
+ EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
+ EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
+ NHLT_ACPI_TABLE *Nhlt;
+ UINTN Index;
+ UINT32 Data32;
+ EFI_STATUS Status;
+ Rsdp = NULL;
+ Xsdt = NULL;
+ Nhlt = NULL;
+
+ //
+ // Find the AcpiSupport protocol returns RSDP (or RSD PTR) address.
+ //
+ DEBUG ((DEBUG_INFO, "LocateNhltAcpiTable () Start\n"));
+
+ Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID *) &Rsdp);
+ if (EFI_ERROR (Status) || (Rsdp == NULL)) {
+ DEBUG ((DEBUG_ERROR, "EFI_ERROR or Rsdp == NULL\n"));
+ return NULL;
+ }
+
+ Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;
+ if (Xsdt == NULL || Xsdt->Signature != EFI_ACPI_5_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ //
+ // If XSDT has not been found, check RSDT
+ //
+ Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
+ if (Xsdt == NULL || Xsdt->Signature != EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "XSDT/RSDT == NULL or wrong signature\n"));
+ return NULL;
+ }
+ }
+
+ for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < Xsdt->Length; Index = Index + sizeof (UINT32)) {
+ Data32 = *(UINT32 *) ((UINT8 *) Xsdt + Index);
+ Nhlt = (NHLT_ACPI_TABLE *) (UINT32 *) (UINTN) Data32;
+ if (Nhlt->Header.Signature == NHLT_ACPI_TABLE_SIGNATURE) {
+ break;
+ }
+ }
+
+ if (Nhlt == NULL || Nhlt->Header.Signature != NHLT_ACPI_TABLE_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "Nhlt == NULL or wrong signature\n"));
+ return NULL;
+ }
+
+ DEBUG ((DEBUG_INFO, "Found NhltTable, Address = 0x%x\n", Nhlt));
+
+ return Nhlt;
+}
+
+
+/**
+ Constructs and installs NHLT table.
+
+ @retval EFI_SUCCESS ACPI Table installed successfully
+ @retval EFI_UNSUPPORTED ACPI Table protocol not found
+
+**/
+EFI_STATUS
+PublishNhltAcpiTable (
+ VOID
+ )
+{
+ UINTN AcpiTableKey;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ NHLT_ACPI_TABLE *NhltTable;
+ UINT32 TableLength;
+ EFI_STATUS Status;
+
+ AcpiTable = NULL;
+ NhltTable = NULL;
+ AcpiTableKey = 0;
+
+ DEBUG ((DEBUG_INFO, "PublishNhltAcpiTable() Start\n"));
+
+ //
+ // Locate ACPI support protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
+ if (EFI_ERROR (Status) || AcpiTable == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ NhltConstructor (mScHdaNhltEndpoints, &NhltTable, &TableLength);
+ NhltAcpiHeaderConstructor (NhltTable, TableLength);
+
+ Status = AcpiTable->InstallAcpiTable (AcpiTable, NhltTable, NhltTable->Header.Length, &AcpiTableKey);
+
+ DEBUG ((DEBUG_INFO, "PublishNhltAcpiTable() End\n"));
+ return Status;
+}
+
+
+/**
+ Sets NVS ACPI variables for _DSM accordingly to policy.
+
+ @param[in] NhltAcpiTableAddress NHLT ACPI Table address
+ @param[in] NhltAcpiTableLength NHLT ACPI Table length
+ @param[in] DspFeatureMask Dsp feature mask
+ @param[in] DspPpModuleMask Dsp post process module mask
+
+**/
+VOID
+UpdateHdaAcpiData (
+ IN UINT32 NhltAcpiTableAddress,
+ IN UINT32 NhltAcpiTableLength,
+ IN UINT32 DspFeatureMask,
+ IN UINT32 DspPpModuleMask
+ )
+{
+ EFI_STATUS Status;
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea;
+
+ Status = gBS->LocateProtocol (
+ &gEfiGlobalNvsAreaProtocolGuid,
+ NULL,
+ (VOID **) &GlobalNvsArea
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "UpdateHdaAcpiData():\n NHLT Address = 0x%08x, Length = 0x%08x\n", NhltAcpiTableAddress, NhltAcpiTableLength));
+ DEBUG ((DEBUG_INFO, " FeatureMask = 0x%08x\n PostProcessingModuleMask = 0x%08x\n", DspFeatureMask, DspPpModuleMask));
+
+ GlobalNvsArea->Area->HdaNhltAcpiAddr = NhltAcpiTableAddress;
+ GlobalNvsArea->Area->HdaNhltAcpiLength = NhltAcpiTableLength;
+ GlobalNvsArea->Area->HdaDspFeatureMask = DspFeatureMask;
+ GlobalNvsArea->Area->HdaDspModMask = DspPpModuleMask;
+}
+
+
+/**
+ Initialize and publish NHLT (Non-HDA Link Table), update NVS variables.
+
+ @param[in] *HdaConfig Pointer to SC_HDAUDIO_CONFIG
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED No NHLT ACPI Table available
+
+**/
+EFI_STATUS
+SetHdaAcpiTable (
+ IN CONST SC_HDAUDIO_CONFIG *HdaConfig
+ )
+{
+ NHLT_ACPI_TABLE *NhltTable;
+ EFI_STATUS Status;
+ NhltTable = NULL;
+
+ //
+ // DMIC X2
+ //
+ switch (HdaConfig->DspEndpointDmic) {
+ case ScHdaDmic2chArray:
+ mScHdaNhltEndpoints[HdaDmicX2].Enable = TRUE;
+ break;
+
+ case ScHdaDmic4chArray:
+ mScHdaNhltEndpoints[HdaDmicX4].Enable = TRUE;
+ break;
+
+ case ScHdaDmicDisabled:
+ default:
+ mScHdaNhltEndpoints[HdaDmicX2].Enable = FALSE;
+ mScHdaNhltEndpoints[HdaDmicX4].Enable = FALSE;
+ }
+
+ if (HdaConfig->DspEndpointBluetooth) {
+ mScHdaNhltEndpoints[HdaBtRender].Enable = TRUE;
+ mScHdaNhltEndpoints[HdaBtCapture].Enable = TRUE;
+ }
+
+ if (HdaConfig->DspEndpointI2sSkp) {
+ mScHdaNhltEndpoints[HdaI2sRenderSKP].Enable = TRUE;
+ mScHdaNhltEndpoints[HdaI2sCaptureSKP].Enable = TRUE;
+ }
+
+ if (HdaConfig->DspEndpointI2sHp) {
+ mScHdaNhltEndpoints[HdaI2sRenderHP].Enable = TRUE;
+ mScHdaNhltEndpoints[HdaI2sCaptureHP].Enable = TRUE;
+ }
+
+ Status = PublishNhltAcpiTable ();
+ NhltTable = LocateNhltAcpiTable ();
+ if (NhltTable == NULL) {
+ return EFI_LOAD_ERROR;
+ }
+
+ UpdateHdaAcpiData ((UINT32) (UINTN) NhltTable, (UINT32) (NhltTable->Header.Length), HdaConfig->DspFeatureMask, HdaConfig->DspPpModuleMask);
+
+ NhltAcpiTableDump (NhltTable);
+ return Status;
+}
+
+
+/**
+ Hide PCI config space of HD-Audio device and do any final initialization.
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Device non-exist or Dsp is disabled
+
+**/
+EFI_STATUS
+ConfigureHdaAtBoot (
+ IN SC_POLICY_HOB *ScPolicy
+ )
+{
+ EFI_STATUS Status;
+ UINTN HdaPciBase;
+ SC_HDAUDIO_CONFIG *HdaConfig;
+
+ DEBUG ((DEBUG_INFO, "ConfigureHdaAtBoot() Start\n"));
+ Status = GetConfigBlock ((VOID *) ScPolicy, &gHdAudioConfigGuid, (VOID *) &HdaConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ HdaPciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_HDA,
+ PCI_FUNCTION_NUMBER_HDA
+ );
+
+ if ((MmioRead32 (HdaPciBase) == 0xFFFFFFFF) || (HdaConfig->DspEnable == FALSE)) {
+ //
+ // Do not set ACPI tables if HD-Audio or audio DSP is function disabled.
+ //
+ DEBUG ((DEBUG_INFO, "HD-Audio ACPI table is not set!\n"));
+
+ return EFI_UNSUPPORTED;
+ }
+ Status = SetHdaAcpiTable (HdaConfig);
+ DEBUG ((DEBUG_INFO, "ConfigureHdaAtBoot() End\n"));
+
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInit.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInit.c
new file mode 100644
index 0000000000..6fb6c8df48
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInit.c
@@ -0,0 +1,907 @@
+/** @file
+ This is the driver that initializes the Intel SC devices
+
+ Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScInit.h"
+#include <Library/UefiDriverEntryPoint.h>
+#include <Protocol/PciIo.h>
+#include <Library/PmcIpcLib.h>
+#include <Library/DxeVtdLib.h>
+#include <SaAccess.h>
+#include <ScAccess.h>
+#include <ScRegs/RegsPcu.h>
+#include <Library/SteppingLib.h>
+#include <Library/HeciMsgLib.h>
+#include <SeCChipset.h>
+#include <SeCState.h>
+#include <Private/ScPmcFunctionDisableResetHob.h>
+
+#define FUNC_ACPI_ENUM_1 0x74
+
+//
+// Global Variables
+//
+EFI_HANDLE mImageHandle;
+GLOBAL_REMOVE_IF_UNREFERENCED SC_POLICY_HOB *mScPolicy;
+
+/**
+ SC initialization before booting to OS
+
+ @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
+ScOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ BXT_SERIES BxtSeries;
+ SC_LOCK_DOWN_CONFIG *LockDownConfig;
+
+ DEBUG ((DEBUG_INFO, "ScOnReadyToBoot() Start\n"));
+
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ BxtSeries = GetBxtSeries ();
+ Status = GetConfigBlock ((VOID *) mScPolicy, &gLockDownConfigGuid, (VOID *) &LockDownConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Trigger an SW SMI to config PCIE power management setting after PCI enumeration is done
+ //
+ if (BxtSeries == BxtP || (BxtSeries == Bxt1)) {
+ IoWrite8 (R_APM_CNT, SW_SMI_PCIE_ASPM_OVERRIDE);
+ }
+
+ //
+ // Trigger an SW SMI to do BiosWriteProtect
+ //
+ if ((BxtSeries == BxtP) && (LockDownConfig->BiosLock == TRUE)) {
+ IoWrite8 (R_APM_CNT, (UINT8) LockDownConfig->BiosLockSwSmiNumber);
+ }
+ DEBUG ((DEBUG_INFO, "ScOnReadyToBoot() End\n"));
+}
+
+
+/**
+ This is the callback function for PCI Enumeration Complete.
+
+**/
+VOID
+EFIAPI
+ScOnPciEnumComplete (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ UINT8 Reset;
+ EFI_PEI_HOB_POINTERS HobPtr;
+ SC_PMC_FUNCTION_DISABLE_RESET_HOB *FuncDisHob;
+ EFI_HOB_GUID_TYPE *FdoEnabledGuidHob = NULL;
+
+ DEBUG ((DEBUG_INFO, "ScOnPciEnumComplete ()\n"));
+
+ //
+ // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
+ // if it is, we will skip it until real event is triggered
+ //
+ Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+ gBS->CloseEvent (Event);
+
+ //
+ // Get SC PMC fuction disable reset HOB.
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gScPmcFunctionDisableResetHobGuid);
+ if (HobPtr.Guid != NULL) {
+ FuncDisHob = GET_GUID_HOB_DATA (HobPtr.Guid);
+ //
+ // CSE status. When CSE is in recovery mode. CSE convert the cold reset to the Global reset
+ // so function disable register is not preserved
+ //
+ FdoEnabledGuidHob = GetFirstGuidHob (&gFdoModeEnabledHobGuid);
+ if (FdoEnabledGuidHob == NULL) {
+ //
+ // Do not change the order of Global reset and Cold reset.
+ // Global reset clears the PMC function disable register.
+ // If done after cold reset, it will end up in a dead loop.
+ //
+ if (FuncDisHob->ResetType == SC_PMC_FUNCTION_DISABLE_GLOBAL_RESET) {
+ DEBUG ((DEBUG_INFO, "PMC function disable updated, do global reset. \n"));
+ HeciSendResetRequest (CBM_RR_REQ_ORIGIN_BIOS_POST, CBM_HRR_GLOBAL_RESET);
+ CpuDeadLoop(); // Should not continue execution after global reset
+ }
+ if (FuncDisHob->ResetType == SC_PMC_FUNCTION_DISABLE_COLD_RESET) {
+ DEBUG ((DEBUG_INFO, "PMC function disable updated, do cold reset. \n"));
+ Reset = IoRead8 (R_RST_CNT);
+ Reset &= 0xF1;
+ Reset |= 0xE;
+ IoWrite8 (R_RST_CNT, Reset);
+ CpuDeadLoop (); // Should not continue execution after cold reset
+ }
+ }
+ }
+ return;
+}
+
+
+/**
+ Register EndOfDXE, ReadyToBoot, ExitBootService event functions
+ for SC configuration in different stages
+
+**/
+VOID
+ScRegisterNotifications (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT ReadyToBoot;
+ EFI_EVENT LegacyBootEvent;
+ EFI_EVENT ExitBootServicesEvent;
+ VOID *Registration;
+
+ //
+ // Create PCI Enumeration Completed callback
+ //
+ EfiCreateProtocolNotifyEvent (
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ TPL_CALLBACK,
+ ScOnPciEnumComplete,
+ NULL,
+ &Registration
+ );
+
+ //
+ // Register an end of DXE event for PCH to do tasks before invoking any UEFI drivers,
+ // applications, or connecting consoles,...
+ //
+ //
+ // Create an ExitPmAuth protocol call back event.
+ //
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ TPL_CALLBACK,
+ ScOnEndOfDxe,
+ NULL,
+ &Registration
+ );
+
+ //
+ // Register a Ready to boot event to config PCIE power management setting after OPROM executed
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ ScOnReadyToBoot,
+ NULL,
+ &ReadyToBoot
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create events for SC to do the task before ExitBootServices/LegacyBoot.
+ // It is guaranteed that only one of two events below will be signalled
+ //
+ Status = gBS->CreateEvent (
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_CALLBACK,
+ ScExitBootServicesEvent,
+ NULL,
+ &ExitBootServicesEvent
+ );
+ Status = gBS->CreateEvent (
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_NOTIFY,
+ ScLpssExitBootServicesEvent,
+ NULL,
+ &ExitBootServicesEvent
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = EfiCreateEventLegacyBootEx (
+ TPL_CALLBACK,
+ ScExitBootServicesEvent,
+ NULL,
+ &LegacyBootEvent
+ );
+ Status = EfiCreateEventLegacyBootEx (
+ TPL_NOTIFY,
+ ScLpssExitBootServicesEvent,
+ NULL,
+ &LegacyBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+
+/**
+ South cluster initialization entry point
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+EFIAPI
+ScInitEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PmcBase;
+ EFI_PEI_HOB_POINTERS HobPtr;
+ SC_INSTANCE_PRIVATE_DATA *ScInstance;
+ UINT16 AcpiBaseAddr;
+ EFI_HANDLE Handle;
+
+ DEBUG ((DEBUG_INFO, "ScInitEntryPoint() Start\n"));
+
+ ScInstance = NULL;
+ mScPolicy = NULL;
+ AcpiBaseAddr = 0;
+
+ Handle = NULL;
+ mImageHandle = ImageHandle;
+
+ //
+ // Get SC Policy HOB.
+ //
+ Status = EFI_NOT_FOUND;
+ HobPtr.Guid = GetFirstGuidHob (&gScPolicyHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mScPolicy = GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ //
+ // Allocate and install the SC Info protocol
+ //
+ PmcBase = PMC_BASE_ADDRESS;
+ AcpiBaseAddr = (UINT16) PcdGet16 (PcdScAcpiIoPortBaseAddress);
+
+ DEBUG ((DEBUG_INFO, "SC Base Addresses:\n-------------------\n"));
+ DEBUG ((DEBUG_INFO, " PmcBase 0x%X\n", PmcBase));
+ DEBUG ((DEBUG_INFO, " AcpiBase 0x%X\n", AcpiBaseAddr));
+ DEBUG ((DEBUG_INFO, "-------------------\n"));
+ ASSERT (PmcBase != 0);
+ ASSERT (AcpiBaseAddr != 0);
+ DEBUG ((DEBUG_INFO, "SC Base Addresses:\n----START---------------\n"));
+ DEBUG ((DEBUG_INFO, " AcpiBase 0x%X\n", AcpiBaseAddr));
+#if (ENBDT_PF_ENABLE == 1)
+ DEBUG ((DEBUG_INFO, "CAUTION Broxton P ACPI offsets\n"));
+#else
+ DEBUG ((DEBUG_INFO, "Broxton M ACPI offsets\n"));
+#endif
+ DEBUG ((DEBUG_INFO, " PM1_STS_EN 0x%X 0x%X\n", R_ACPI_PM1_STS, IoRead32 ((UINTN) (AcpiBaseAddr + R_ACPI_PM1_STS))));;
+ DEBUG ((DEBUG_INFO, " PM1_CNT 0x%X 0x%X\n", R_ACPI_PM1_CNT, IoRead32 ((UINTN) (AcpiBaseAddr + R_ACPI_PM1_CNT))));;
+ DEBUG ((DEBUG_INFO, " PM1_TMR 0x%X 0x%X\n", R_ACPI_PM1_TMR, IoRead32 ((UINTN) (AcpiBaseAddr + R_ACPI_PM1_TMR))));;
+ DEBUG ((DEBUG_INFO, " GPE0a_STS 0x%X 0x%X\n", R_ACPI_GPE0a_STS, IoRead32 ((UINTN) (AcpiBaseAddr + R_ACPI_GPE0a_STS))));;
+ DEBUG ((DEBUG_INFO, " GPE0a_EN 0x%X 0x%X\n", R_ACPI_GPE0a_EN, IoRead32 ((UINTN) (AcpiBaseAddr + R_ACPI_GPE0a_EN))));;
+ DEBUG ((DEBUG_INFO, " SMI_EN 0x%X 0x%X\n", R_SMI_EN, IoRead32 ((UINTN) (AcpiBaseAddr + R_SMI_EN))));;
+ DEBUG ((DEBUG_INFO, " SMI_STS 0x%X 0x%X\n", R_SMI_STS, IoRead32 ((UINTN) (AcpiBaseAddr + R_SMI_STS))));;
+ DEBUG ((DEBUG_INFO, " GPE_CTRL 0x%X 0x%X\n", R_ACPI_GPE_CNTL, IoRead32 ((UINTN) (AcpiBaseAddr + R_ACPI_GPE_CNTL))));;
+ DEBUG ((DEBUG_INFO, " TCO_RLD 0x%X 0x%X\n", R_TCO_RLD, IoRead32 ((UINTN) (AcpiBaseAddr + R_TCO_RLD))));;
+ DEBUG ((DEBUG_INFO, " TCO_STS 0x%X 0x%X\n", R_TCO_STS, IoRead32 ((UINTN) (AcpiBaseAddr + R_TCO_STS))));;
+ DEBUG ((DEBUG_INFO, " TCO1_CNT 0x%X 0x%X\n", R_TCO_CNT, IoRead32 ((UINTN) (AcpiBaseAddr + R_TCO_CNT))));;
+ DEBUG ((DEBUG_INFO, " TCO_TMR 0x%X 0x%X\n", R_TCO_TMR, IoRead32 ((UINTN) (AcpiBaseAddr + R_TCO_TMR))));;
+ DEBUG ((DEBUG_INFO, "SC Base Addresses:\n----END---------------\n"));
+
+ //
+ // Initialize the SC device
+ //
+ InitializeScDevice (ScInstance, mScPolicy, PmcBase, AcpiBaseAddr);
+
+ ScRegisterNotifications ();
+
+ ScInstance = AllocateZeroPool (sizeof (SC_INSTANCE_PRIVATE_DATA));
+ if (ScInstance == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ScInstance->ScInfo.Revision = INFO_PROTOCOL_REVISION_1;
+ ScInstance->ScInfo.BusNumber = DEFAULT_PCI_BUS_NUMBER_SC;
+ ScInstance->ScInfo.RCVersion = SC_POLICY_REVISION;
+
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiInfoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(ScInstance->ScInfo)
+ );
+
+ DEBUG ((DEBUG_INFO, "ScInitEntryPoint() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize the SC device according to the SC Platform Policy
+
+ @param[in, out] ScInstance SC instance private data. May get updated by this function
+ @param[in] ScPolicy The SC Platform Policy protocol instance
+ @param[in] PmcBase PMC base address of this SC device
+ @param[in] AcpiBaseAddr ACPI IO base address of this SC device
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+InitializeScDevice (
+ IN OUT SC_INSTANCE_PRIVATE_DATA *ScInstance,
+ IN SC_POLICY_HOB *ScPolicy,
+ IN UINT32 PmcBase,
+ IN UINT16 AcpiBaseAddr
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FuncDisableReg;
+ BXT_SERIES BxtSeries;
+
+ DEBUG ((DEBUG_INFO, "InitializeScDevice() Start\n"));
+ FuncDisableReg = MmioRead32 (PmcBase + R_PMC_FUNC_DIS);
+ BxtSeries = GetBxtSeries ();
+
+ //
+ // VT-d Initialization
+ //
+ DEBUG ((DEBUG_INFO, "Initializing VT-d in Dxe to update DMAR table\n"));
+ VtdInit ();
+
+ //
+ // Configure PMC Devices
+ //
+ Status = ConfigurePmcAfterPciEnum (ScPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "InitializeScDevice() End\n"));
+
+ return Status;
+}
+
+
+/**
+ Program Sc devices dedicated IRQ#.
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+ConfigureIrqAtBoot (
+ IN SC_POLICY_HOB *ScPolicy
+ )
+{
+ UINTN Index;
+ UINTN TblIndex;
+ UINTN Segment;
+ UINTN BusNum;
+ UINTN DevNum;
+ UINTN FunNum;
+ UINTN HandleCount;
+ EFI_STATUS Status;
+ EFI_HANDLE *Handles;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ STATIC SC_IRQ_INIT_ENTRY IrqInitTable[] = {
+ //
+ // Bus Dev Fun Irq
+ //
+ {0, 0, 1, 24}, // PUINT
+ {0, 0, 3, 23}, // gmm
+ {0, 3, 0, 21}, // iunit
+
+
+ {0, 0xE, 0, 25}, // HD-Audio
+
+ {0, 0x11, 0, 26}, // ISH
+
+ {0, 0x15, 0, 17}, // XHCI
+ {0, 0x15, 1, 13}, // xDCI
+
+ {0, 0x16, 0, 27}, // I2C1
+ {0, 0x16, 1, 28}, // I2C2
+ {0, 0x16, 2, 29}, // I2C3
+ {0, 0x16, 3, 30}, // I2C4
+
+ {0, 0x17, 0, 31}, // I2C5
+ {0, 0x17, 1, 32}, // I2C6
+ {0, 0x17, 2, 33}, // I2C7
+ {0, 0x17, 3, 34}, // I2C8
+
+ {0, 0x18, 0, 4}, // UART1
+ {0, 0x18, 1, 5}, // UART2
+ {0, 0x18, 2, 6}, // UART3
+ {0, 0x18, 3, 7}, // UART4
+
+ {0, 0x19, 0, 35}, // SPI1
+ {0, 0x19, 1, 36}, // SPI2
+ {0, 0x19, 2, 37}, // SPI3
+
+ {0, 0x1B, 0, 3 }, // SDCard
+ {0, 0x1C, 0, 39 }, // eMMC
+ {0, 0x1D, 0, 38 }, // UFS
+ {0, 0x1E, 0, 42 }, // SDIO
+ };
+
+ DEBUG ((EFI_D_INFO, "ConfigureIrqAtBoot() Start\n"));
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+
+ DEBUG ((EFI_D_INFO, "Status = %r\n", Status));
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for(Index = 0; Index < HandleCount; Index ++) {
+ Status = gBS->HandleProtocol (
+ Handles[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ Status = PciIo->GetLocation(
+ PciIo,
+ &Segment,
+ &BusNum,
+ &DevNum,
+ &FunNum
+ );
+
+ for (TblIndex = 0; TblIndex < (sizeof (IrqInitTable) / sizeof (SC_IRQ_INIT_ENTRY)); TblIndex++) {
+ if ((BusNum == IrqInitTable[TblIndex].BusNumber) &&
+ (DevNum == IrqInitTable[TblIndex].DeviceNumber) &&
+ (FunNum == IrqInitTable[TblIndex].FunctionNumber)) {
+
+ Status = PciIo->Pci.Write(
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0x3c, //Offset 0x3c :PCI Interrupt Line
+ 1,
+ &IrqInitTable[TblIndex].Irq
+ );
+
+ DEBUG ((EFI_D_INFO, "Writing IRQ#%d for B%d/D%d/F%d\n", IrqInitTable[TblIndex].Irq, BusNum, DevNum, FunNum));
+ } else {
+ continue;
+ }
+
+ }
+
+ }
+
+ DEBUG ((EFI_D_INFO, "ConfigureIrqAtBoot() End\n"));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ SC initialization triggered by ExitBootServices events
+ Useful for operations which must happen later than at the end of post
+
+ @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
+ScExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN P2SBBase;
+ UINT32 Buffer9;
+ BXT_SERIES BxtSeries;
+
+ Buffer9 = 0;
+ BxtSeries = GetBxtSeries ();
+
+ //
+ // Closed the event to avoid call twice
+ //
+ gBS->CloseEvent (Event);
+
+ UpdateNvsArea (mScPolicy);
+ ConfigureHdaAtBoot (mScPolicy);
+
+ ConfigureIrqAtBoot (mScPolicy);
+ StopLpssAtBoot ();
+
+ if (BxtSeries != BxtP) {
+ SideBandAndThenOr32(
+ 0xC6,
+ 0x2338,
+ 0xFFFFFFFF,
+ BIT0
+ );
+ }
+
+ //
+ // Hide P2SB device in OS phase
+ //
+ DEBUG ((DEBUG_INFO, "Hide P2SB on normal mode..........\n"));
+ P2SBBase = MmPciAddress (
+ 0,
+ 0,
+ PCI_DEVICE_NUMBER_P2SB,
+ PCI_FUNCTION_NUMBER_P2SB,
+ R_P2SB_P2SBC
+ );
+ MmioOr32 (P2SBBase, B_P2SB_P2SBC_HIDE);
+
+ //
+ // Set the P2SB bit in FUNC_ACPI_ENUM_1.
+ //
+ Buffer9 = MmioRead32 (GCR_BASE_ADDRESS + FUNC_ACPI_ENUM_1);
+ Buffer9 = Buffer9 | BIT0;
+ MmioWrite32 (GCR_BASE_ADDRESS + FUNC_ACPI_ENUM_1, Buffer9);
+
+ return;
+}
+
+
+/**
+ SC initialization triggered by ExitBootServices for LPSS events
+ This should be at a higher TPL than the callback that sets Untrusted Mode.
+
+ @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
+ScLpssExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // Closed the event to avoid call twice
+ //
+ gBS->CloseEvent (Event);
+
+ ConfigureLpssAtBoot (mScPolicy);
+}
+
+
+/**
+ SC initialization before Boot Script Table is closed
+
+ @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
+ScOnEndOfDxe (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINT32 FuncDisableReg;
+ UINT32 Data32;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT16 AcpiBaseAddr;
+ UINT32 PmcBase;
+ UINT8 NumOfDevltrOverride;
+ UINT32 DlockValue;
+ UINTN PciLpcRegBase;
+ UINTN PciSpiRegBase;
+ UINTN SpiBar0;
+ BXT_SERIES BxtSeries;
+ UINT8 Data8;
+ SC_LOCK_DOWN_CONFIG *LockDownConfig;
+ SC_FLASH_PROTECTION_CONFIG *FlashProtectionConfig;
+ UINT16 Data16And;
+ UINT16 Data16Or;
+ SI_POLICY_HOB *SiPolicyHob;
+ EFI_PEI_HOB_POINTERS HobPtr;
+
+ NumOfDevltrOverride = 0;
+ PciLpcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ PciSpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_SPI,
+ PCI_FUNCTION_NUMBER_SPI
+ );
+
+ DEBUG ((DEBUG_INFO, "ScOnEndOfDxe() Start\n"));
+
+ //
+ // Closed the event to avoid call twice when launch shell
+ //
+ gBS->CloseEvent (Event);
+
+ BxtSeries = GetBxtSeries ();
+ AcpiBaseAddr = (UINT16) PcdGet16 (PcdScAcpiIoPortBaseAddress);
+ PmcBase = PMC_BASE_ADDRESS;
+ FuncDisableReg = MmioRead32 (PmcBase + R_PMC_FUNC_DIS);
+
+ MmioAnd32 (
+ (UINTN) (PmcBase + R_PMC_PMIR),
+ (UINT32) ~(B_PMC_PMIR_CF9GR)
+ );
+ S3BootScriptSaveMemWrite (
+ EfiBootScriptWidthUint32,
+ (UINTN) (PmcBase + R_PMC_PMIR),
+ 1,
+ (VOID *) (UINTN) (PmcBase + R_PMC_PMIR)
+ );
+
+ if (BxtSeries == BxtP){
+ SpiBar0 = MmioRead32 (PciSpiRegBase + R_SPI_BASE) & ~(B_SPI_BAR0_MASK);
+ Status = GetConfigBlock ((VOID *) mScPolicy, &gFlashProtectionConfigGuid, (VOID *) &FlashProtectionConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Program the Flash Protection Range Register based on policy
+ //
+ DlockValue = MmioRead32 (SpiBar0 + R_SPI_DLOCK);
+
+ FlashProtectionConfig->ProtectRange[0].ProtectedRangeBase = (UINT16) ((FixedPcdGet32 (PcdFlashIbbRegionMappedBase) - FixedPcdGet32 (PcdFlashAreaBaseAddress)) >> 12);
+ FlashProtectionConfig->ProtectRange[0].ProtectedRangeLimit = (UINT16) ((FixedPcdGet32 (PcdFlashIbbRegionMappedBase) - FixedPcdGet32 (PcdFlashAreaBaseAddress) + FixedPcdGet32 (PcdFlashIbbRegionSize) - 1) >> 12);
+ FlashProtectionConfig->ProtectRange[1].ProtectedRangeBase = (UINT16) ((FixedPcdGet32 (PcdFlashObbRegionMappedBase) - FixedPcdGet32 (PcdFlashAreaBaseAddress)) >> 12);
+ FlashProtectionConfig->ProtectRange[1].ProtectedRangeLimit = (UINT16) ((FixedPcdGet32 (PcdFlashObbRegionMappedBase) - FixedPcdGet32 (PcdFlashAreaBaseAddress) + FixedPcdGet32 (PcdFlashObbRegionSize) - 1) >> 12);
+
+ for (Index = 0; Index < SC_FLASH_PROTECTED_RANGES; ++Index) {
+ if ((FlashProtectionConfig->ProtectRange[Index].WriteProtectionEnable ||
+ FlashProtectionConfig->ProtectRange[Index].ReadProtectionEnable) != TRUE) {
+ continue;
+ }
+
+ //
+ // Proceed to program the register after ensure it is enabled
+ //
+ Data32 = 0;
+ Data32 |= (FlashProtectionConfig->ProtectRange[Index].WriteProtectionEnable == TRUE) ? B_SPI_PRX_WPE : 0;
+ Data32 |= (FlashProtectionConfig->ProtectRange[Index].ReadProtectionEnable == TRUE) ? B_SPI_PRX_RPE : 0;
+ Data32 |= ((UINT32) FlashProtectionConfig->ProtectRange[Index].ProtectedRangeLimit << N_SPI_PRX_PRL) & B_SPI_PRX_PRL_MASK;
+ Data32 |= ((UINT32) FlashProtectionConfig->ProtectRange[Index].ProtectedRangeBase << N_SPI_PRX_PRB) & B_SPI_PRX_PRB_MASK;
+ DEBUG ((DEBUG_INFO, "Protected range %d: 0x%08x \n", Index, Data32));
+
+ DlockValue |= (UINT32) (B_SPI_DLOCK_PR0LOCKDN << Index);
+ MmioWrite32 ((UINTN) (SpiBar0 + (R_SPI_PR0 + (Index * S_SPI_PRX))), Data32);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (SpiBar0 + (R_SPI_PR0 + (Index * S_SPI_PRX))),
+ 1,
+ (VOID *) (UINTN) (SpiBar0 + (R_SPI_PR0 + (Index * S_SPI_PRX)))
+ );
+ }
+
+ //
+ // Program DLOCK register
+ //
+ MmioWrite32 ((UINTN) (SpiBar0 + R_SPI_DLOCK), DlockValue);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (SpiBar0 + R_SPI_DLOCK),
+ 1,
+ (VOID *) (UINTN) (SpiBar0 + R_SPI_DLOCK)
+ );
+
+ //
+ // In SPI controller the BIOS should set the Flash Configuration Lock-Down bit
+ // (SPI_BAR0 + 04[15]) at end of post. When set to 1, those Flash Program Registers
+ // that are locked down by this FLOCKDN bit cannot be written.
+ //
+ MmioOr32 ((UINTN) (SpiBar0 + R_SPI_HSFS), (UINT32) (B_SPI_HSFS_FLOCKDN));
+ S3BootScriptSaveMemWrite (
+ EfiBootScriptWidthUint32,
+ (UINTN) (SpiBar0 + R_SPI_HSFS),
+ 1,
+ (VOID *) (UINTN) (SpiBar0 + R_SPI_HSFS)
+ );
+ }
+
+ Status = GetConfigBlock ((VOID *) mScPolicy, &gLockDownConfigGuid, (VOID *) &LockDownConfig);
+ ASSERT_EFI_ERROR (Status);
+ if (LockDownConfig->GlobalSmi == TRUE) {
+ //
+ // Save Global SMI Enable bit setting before BIOS enables SMI_LOCK during S3 resume
+ //
+ Data32Or = IoRead32 ((UINTN) (AcpiBaseAddr + R_SMI_EN));
+ if ((Data32Or & B_SMI_EN_GBL_SMI) != 0) {
+ Data32And = 0xFFFFFFFF;
+ Data32Or &= B_SMI_EN_GBL_SMI;
+ S3BootScriptSaveIoReadWrite (
+ EfiBootScriptWidthUint32,
+ (UINTN) (AcpiBaseAddr + R_SMI_EN),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ }
+
+ MmioOr8 ((UINTN) (PmcBase + R_PMC_GEN_PMCON_2), B_PMC_GEN_PMCON_SMI_LOCK);
+ S3BootScriptSaveMemWrite (
+ EfiBootScriptWidthUint8,
+ (UINTN) (PmcBase + R_PMC_GEN_PMCON_2),
+ 1,
+ (VOID *) (UINTN) (PmcBase + R_PMC_GEN_PMCON_2)
+ );
+ }
+
+ if (GetBxtSeries () == BxtP) {
+ if (LockDownConfig->BiosLock == TRUE) {
+ //
+ // LPC
+ //
+ if (! (MmioRead8 (PciLpcRegBase + R_PCH_LPC_BC) & B_PCH_LPC_BC_LE)) {
+ DEBUG ((DEBUG_INFO, "Set LPC bios lock\n"));
+ MmioOr8 ((UINTN) (PciLpcRegBase + R_PCH_LPC_BC), B_PCH_LPC_BC_LE);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciLpcRegBase + R_PCH_LPC_BC),
+ 1,
+ (VOID *) (UINTN) (PciLpcRegBase + R_PCH_LPC_BC)
+ );
+ }
+
+ //
+ // SPI
+ //
+ if (! (MmioRead8 (PciSpiRegBase + R_SPI_BCR) & B_SPI_BCR_BLE)) {
+ DEBUG ((DEBUG_INFO, "Set SPI bios lock\n"));
+ MmioOr8 ((UINTN) (PciSpiRegBase + R_SPI_BCR), (UINT8) B_SPI_BCR_BLE);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciSpiRegBase + R_SPI_BCR),
+ 1,
+ (VOID *) (UINTN) (PciSpiRegBase + R_SPI_BCR)
+ );
+ }
+ }
+
+ if (LockDownConfig->BiosInterface == TRUE) {
+ //
+ // LPC
+ //
+ MmioOr8 ((UINTN) (PciLpcRegBase + R_PCH_LPC_BC), (UINT8) B_PCH_LPC_BC_BILD);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciLpcRegBase + R_PCH_LPC_BC),
+ 1,
+ (VOID *) (UINTN) (PciLpcRegBase + R_PCH_LPC_BC)
+ );
+
+ //
+ // Reads back for posted write to take effect
+ //
+ Data8 = MmioRead8 ((UINTN) (PciLpcRegBase + R_PCH_LPC_BC));
+ S3BootScriptSaveMemPoll (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciLpcRegBase + R_PCH_LPC_BC),
+ &Data8, // BitMask
+ &Data8, // BitValue
+ 1, // Duration
+ 1 // LoopTimes
+ );
+
+ //
+ // SPI
+ //
+ MmioOr8 ((UINTN) (PciSpiRegBase + R_SPI_BCR), (UINT8) B_SPI_BCR_BILD);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciSpiRegBase + R_SPI_BCR),
+ 1,
+ (VOID *) (UINTN) (PciSpiRegBase + R_SPI_BCR)
+ );
+
+ //
+ // Reads back for posted write to take effect
+ //
+ Data8 = MmioRead8 ((UINTN) (PciSpiRegBase + R_SPI_BCR));
+ S3BootScriptSaveMemPoll (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciSpiRegBase + R_SPI_BCR),
+ &Data8, // BitMask
+ &Data8, // BitValue
+ 1, // Duration
+ 1 // LoopTimes
+ );
+ }
+ }
+
+ if (LockDownConfig->TcoLock) {
+ //
+ // Enable TCO and Lock Down TCO
+ //
+ DEBUG ((DEBUG_INFO, "Enable TCO and Lock Down TCO\n"));
+ Data16And = 0xFFFF;
+ Data16Or = B_SMI_EN_TCO;
+ IoOr16 (AcpiBaseAddr + R_SMI_EN, Data16Or);
+
+ Data16And = 0xFFFF;
+ Data16Or = B_TCO_CNT_LOCK;
+ IoOr16 (AcpiBaseAddr + R_TCO_CNT, Data16Or);
+
+ S3BootScriptSaveIoReadWrite (
+ EfiBootScriptWidthUint16,
+ (UINTN) (AcpiBaseAddr + R_TCO_CNT),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+
+ HobPtr.Guid = GetFirstGuidHob (&gSiPolicyHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ SiPolicyHob = GET_GUID_HOB_DATA (HobPtr.Guid);
+ UsbInitBeforeBoot (SiPolicyHob, mScPolicy);
+ DEBUG ((DEBUG_INFO, "Enable TCO and Lock Down TCO ---- END\n"));
+
+ }
+
+ if (LockDownConfig->RtcLock == TRUE) {
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (B_PCH_PCR_RTC_CONF_UCMOS_LOCK | B_PCH_PCR_RTC_CONF_LCMOS_LOCK | B_PCH_PCR_RTC_CONF_BILD);
+ PchPcrAndThenOr32 (
+ 0xD1,
+ R_PCH_PCR_RTC_CONF,
+ Data32And,
+ Data32Or
+ );
+ PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ 0xD1,
+ R_PCH_PCR_RTC_CONF,
+ &Data32Or,
+ &Data32And
+ );
+ }
+
+ if ((BxtSeries == BxtP) || (BxtSeries == Bxt1)){
+ Data8 = SW_SMI_PCIE_ASPM_OVERRIDE;
+ S3BootScriptSaveIoWrite (
+ EfiBootScriptWidthUint8,
+ (UINTN) (R_APM_CNT),
+ 1,
+ &Data8
+ );
+ }
+ DEBUG ((DEBUG_INFO, "ScOnEndOfDxe() End\n"));
+
+ return;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInit.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInit.h
new file mode 100644
index 0000000000..0fc3b59505
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInit.h
@@ -0,0 +1,267 @@
+/** @file
+ Header file for Initialization Driver.
+
+ Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SC_INITIALIZATION_DRIVER_H_
+#define _SC_INITIALIZATION_DRIVER_H_
+
+#include <Library/UefiLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Guid/EventGroup.h>
+#include <Library/ConfigBlockLib.h>
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/BootScriptSave.h>
+#include <Protocol/ExitPmAuth.h>
+#include <Protocol/ScS3Support.h>
+#include <Library/ScAslUpdateLib.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/ScInfo.h>
+#include <ScAccess.h>
+#include <Library/ScPlatformLib.h>
+#include <Library/SideBandLib.h>
+#include <PlatformBaseAddresses.h>
+#include <Private/Library/UsbCommonLib.h>
+#include <Private/Guid/ScPolicyHobGuid.h>
+#include <Library/MmPciLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/SteppingLib.h>
+
+#define SC_PM_ENABLE
+
+typedef struct {
+ EFI_SC_INFO_PROTOCOL ScInfo;
+} SC_INSTANCE_PRIVATE_DATA;
+
+//
+// Data definitions
+//
+extern EFI_HANDLE mImageHandle;
+
+///
+/// IRQ routing init table entry
+///
+typedef struct {
+ UINTN BusNumber;
+ UINTN DeviceNumber;
+ UINTN FunctionNumber;
+ UINTN Irq;
+} SC_IRQ_INIT_ENTRY;
+
+/**
+ Initialize the SC device according to the SC Platform Policy
+
+ @param[in, out] ScInstance SC instance private data. May get updated by this function
+ @param[in] ScPolicy The SC Policy instance
+ @param[in] PmcBase PMC base address of this SC device
+ @param[in] AcpiBaseAddr ACPI IO base address of this SC device
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+InitializeScDevice (
+ IN OUT SC_INSTANCE_PRIVATE_DATA *ScInstance,
+ IN SC_POLICY_HOB *ScPolicy,
+ IN UINT32 PmcBase,
+ IN UINT16 AcpiBaseAddr
+ );
+
+/**
+ Program Sc devices dedicated IRQ#.
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+ConfigureIrqAtBoot (
+ IN SC_POLICY_HOB *ScPolicy
+ );
+
+/**
+ SC initialization triggered by ExitBootServices events
+ Useful for operations which must happen later than at the end of post
+
+ @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
+ScExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ SC initialization triggered by ExitBootServices for LPSS events
+ This should be at a higher TPL than the callback that sets Untrusted Mode.
+
+ @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
+ScLpssExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ SC initialization before Boot Script Table is closed
+
+ @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
+ScOnEndOfDxe (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Hide PCI config space of HD-Audio device and do any final initialization.
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Device non-exist or Dsp is disabled
+
+**/
+EFI_STATUS
+ConfigureHdaAtBoot (
+ IN SC_POLICY_HOB *ScPolicy
+ );
+
+/**
+ Perform the remaining configuration on SC SATA to perform device detection
+ at end of Dxe, then set the SATA SPD and PxE corresponding, and set the Register Lock
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+ConfigureSataDxe (
+ IN SC_POLICY_HOB *ScPolicy
+ );
+
+/**
+ Hide PCI config space of Otg device and do any final initialization.
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND GNVS Protocol interface not found
+
+**/
+EFI_STATUS
+ConfigureOtgAtBoot (
+ IN SC_POLICY_HOB *ScPolicy
+ );
+
+/**
+ Hide PCI config space of Lpss devices and do any final initialization.
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND GNVS Protocol interface not found
+
+**/
+EFI_STATUS
+ConfigureLpssAtBoot (
+ IN SC_POLICY_HOB *ScPolicy
+ );
+
+/**
+ Stop Lpss devices[I2C and SPI] if any is running.
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+StopLpssAtBoot (
+ VOID
+ );
+
+/**
+ Register notification function for PM configuration after PCI enumeration
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+ConfigurePmcAfterPciEnum (
+ IN SC_POLICY_HOB *ScPolicy
+ );
+
+/**
+ Dump whole SC_POLICY_HOB and serial out.
+
+ @param[in] ScPolicy The SC Policy instance
+
+**/
+VOID
+ScDumpPolicy (
+ IN SC_POLICY_HOB *ScPolicy
+ );
+
+/**
+ Configures ports of the SC USB3 (xHCI) controller before entering OS. the SC USB3 (xHCI) controller
+
+ @param[in] ScPolicy The SC Policy instance
+
+**/
+VOID
+ConfigureXhciAtBoot (
+ IN SC_POLICY_HOB *ScPolicy
+ );
+
+/**
+ Update ASL object before Boot
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_STATUS
+ @retval EFI_NOT_READY The Acpi protocols are not ready.
+
+**/
+EFI_STATUS
+UpdateNvsArea (
+ IN SC_POLICY_HOB *ScPolicy
+ );
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInitDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInitDxe.inf
new file mode 100644
index 0000000000..5b31b18fab
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScInitDxe.inf
@@ -0,0 +1,104 @@
+## @file
+# SC Initialization driver
+#
+# Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ScInitDxe
+ FILE_GUID = 149A6B53-FAFA-44F9-8BAF-F50C68A05236
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = ScInitEntryPoint
+
+[Sources]
+ ScInit.h
+ ScInit.c
+ ScHda.c
+ ScLpss.c
+ ScIsh.c
+ ScPmc.c
+ ScIosf.c
+ ScSata.c
+ ScXdci.c
+ ScAcpi.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+ BroxtonPlatformPkg/PlatformPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ DebugLib
+ PcdLib
+ IoLib
+ ScPlatformLib
+ UefiLib
+ S3BootScriptLib
+ ScAslUpdateLib
+ SteppingLib
+ MmPciLib
+ HobLib
+ TimerLib
+ ScHdaLib
+ SideBandLib
+ SteppingLib
+ UsbCommonLib
+ DxeVtdLib
+ GpioLib
+ ConfigBlockLib
+ HeciMsgLib
+
+[Protocols]
+ gEfiInfoProtocolGuid ## PRODUCES
+ gExitPmAuthProtocolGuid ## PRODUCES
+ gEfiAcpiTableProtocolGuid ## CONSUMES
+ gEfiGlobalNvsAreaProtocolGuid ## CONSUMES
+ gEfiPciIoProtocolGuid ## CONSUMES
+ gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
+
+[Guids]
+ gScPolicyHobGuid ## UNDEFINED
+ gEfiAcpiTableGuid ## UNDEFINED
+ gSiPolicyHobGuid
+ gPcieRpConfigGuid
+ gSataConfigGuid
+ gHdAudioConfigGuid
+ gLockDownConfigGuid
+ gLpssConfigGuid
+ gFlashProtectionConfigGuid
+ gFdoModeEnabledHobGuid
+ gScPmcFunctionDisableResetHobGuid
+ gP2sbConfigGuid
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## SOMETIMES_CONSUMES
+ gEfiBxtTokenSpaceGuid.PcdScAcpiIoPortBaseAddress ## SOMETIMES_CONSUMES
+ gEfiBxtTokenSpaceGuid.PcdPmcGcrBaseAddress ## SOMETIMES_CONSUMES
+ gEfiBxtTokenSpaceGuid.PcdP2SBBaseAddress
+
+ gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize
+ gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress
+ gPlatformModuleTokenSpaceGuid.PcdFlashIbbRegionMappedBase
+ gPlatformModuleTokenSpaceGuid.PcdFlashIbbRegionSize
+ gPlatformModuleTokenSpaceGuid.PcdFlashObbRegionMappedBase
+ gPlatformModuleTokenSpaceGuid.PcdFlashObbRegionSize
+
+[Depex]
+ gEfiSmmControl2ProtocolGuid
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScIosf.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScIosf.c
new file mode 100644
index 0000000000..50c554aad1
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScIosf.c
@@ -0,0 +1,35 @@
+/** @file
+ Initializes SC IOSF Devices
+
+ Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScInit.h"
+#include <Protocol/GlobalNvsArea.h>
+#include "SaAccess.h"
+
+/**
+ Hide PCI config space of Iosf devices and do any final initialization.
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+ConfigureIosfAtBoot (
+ IN SC_POLICY_HOB *ScPolicy
+ )
+{
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScIsh.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScIsh.c
new file mode 100644
index 0000000000..91f5dd7dbe
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScIsh.c
@@ -0,0 +1,53 @@
+/** @file
+ Initializes SC ISH Devices.
+
+ Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScInit.h"
+#include <Protocol/GlobalNvsArea.h>
+#include <ScRegs/RegsIsh.h>
+#include "SaAccess.h"
+
+/**
+ Hide PCI config space of ISH devices and do any final initialization.
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+ConfigureIshAtBoot (
+ IN SC_POLICY_HOB *ScPolicy
+ )
+{
+ UINTN IshPciMmBase;
+ UINT32 IshMmioBase0;
+ UINT32 IshMmioBase1;
+ UINT32 Buffer32;
+
+ DEBUG ((DEBUG_INFO, "ConfigureIshAtBoot() Start\n"));
+
+ //
+ // Initialize Variables
+ //
+ IshPciMmBase = 0;
+ IshMmioBase0 = 0;
+ IshMmioBase1 = 0;
+ Buffer32 = 0;
+
+ DEBUG ((DEBUG_INFO, "ConfigureIshAtBoot() End\n"));
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScLpss.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScLpss.c
new file mode 100644
index 0000000000..593db9816f
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScLpss.c
@@ -0,0 +1,283 @@
+/** @file
+ Initializes SC LPSS Devices.
+
+ Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/GpioLib.h>
+#include <Library/PmcIpcLib.h>
+#include <Library/SteppingLib.h>
+#include <SaAccess.h>
+#include "ScInit.h"
+
+typedef struct {
+ UINT32 PciDeviceNum;
+ UINT32 PciFuncNum;
+ UINT16 LpssPciCfgCtrl;
+ UINT16 Psf3BaseAddress;
+ UINT32 LpssFuncDisableBit;
+} SERIAL_IO_CONTROLLER_DESCRIPTOR;
+
+#define LPSS_IO_DEVICE_NUM 15
+
+//
+// Note: the devices order need to align with the order defined in SC_LPSS_CONFIG
+//
+SERIAL_IO_CONTROLLER_DESCRIPTOR mLpssIoDevices[LPSS_IO_DEVICE_NUM] =
+{
+ //
+ // I2C 0~7
+ //
+ {PCI_DEVICE_NUMBER_LPSS_I2C0, PCI_FUNCTION_NUMBER_LPSS_I2C0, 0x200, 0x1900, B_PMC_FUNC_DIS_LPSS_I2C0},
+ {PCI_DEVICE_NUMBER_LPSS_I2C0, PCI_FUNCTION_NUMBER_LPSS_I2C1, 0x204, 0x1800, B_PMC_FUNC_DIS_LPSS_I2C1},
+ {PCI_DEVICE_NUMBER_LPSS_I2C0, PCI_FUNCTION_NUMBER_LPSS_I2C2, 0x208, 0x1700, B_PMC_FUNC_DIS_LPSS_I2C2},
+ {PCI_DEVICE_NUMBER_LPSS_I2C0, PCI_FUNCTION_NUMBER_LPSS_I2C3, 0x20C, 0x1600, B_PMC_FUNC_DIS_LPSS_I2C3},
+ {PCI_DEVICE_NUMBER_LPSS_I2C1, PCI_FUNCTION_NUMBER_LPSS_I2C4, 0x210, 0x1500, B_PMC_FUNC_DIS_LPSS_I2C4},
+ {PCI_DEVICE_NUMBER_LPSS_I2C1, PCI_FUNCTION_NUMBER_LPSS_I2C5, 0x214, 0x1400, B_PMC_FUNC_DIS_LPSS_I2C5},
+ {PCI_DEVICE_NUMBER_LPSS_I2C1, PCI_FUNCTION_NUMBER_LPSS_I2C6, 0x218, 0x1300, B_PMC_FUNC_DIS_LPSS_I2C6},
+ {PCI_DEVICE_NUMBER_LPSS_I2C1, PCI_FUNCTION_NUMBER_LPSS_I2C7, 0x21C, 0x1200, B_PMC_FUNC_DIS_LPSS_I2C7},
+
+ //
+ // UART 0~3
+ //
+ {PCI_DEVICE_NUMBER_LPSS_HSUART, PCI_FUNCTION_NUMBER_LPSS_HSUART0, 0x220, 0x1100, B_PMC_FUNC_DIS_LPSS_UART0},
+ {PCI_DEVICE_NUMBER_LPSS_HSUART, PCI_FUNCTION_NUMBER_LPSS_HSUART1, 0x224, 0x1000, B_PMC_FUNC_DIS_LPSS_UART1},
+ {PCI_DEVICE_NUMBER_LPSS_HSUART, PCI_FUNCTION_NUMBER_LPSS_HSUART2, 0x228, 0x0F00, B_PMC_FUNC_DIS_LPSS_UART2},
+ {PCI_DEVICE_NUMBER_LPSS_HSUART, PCI_FUNCTION_NUMBER_LPSS_HSUART3, 0x22C, 0x0E00, B_PMC_FUNC_DIS_LPSS_UART3},
+
+ //
+ // SPI 0~2
+ //
+ {PCI_DEVICE_NUMBER_LPSS_SPI, PCI_FUNCTION_NUMBER_LPSS_SPI0, 0x230, 0x0D00, B_PMC_FUNC_DIS_LPSS_SPI0},
+ {PCI_DEVICE_NUMBER_LPSS_SPI, PCI_FUNCTION_NUMBER_LPSS_SPI1, 0x234, 0x0C00, B_PMC_FUNC_DIS_LPSS_SPI1},
+ {PCI_DEVICE_NUMBER_LPSS_SPI, PCI_FUNCTION_NUMBER_LPSS_SPI2, 0x238, 0x0B00, B_PMC_FUNC_DIS_LPSS_SPI2}
+};
+
+
+/**
+ Hide PCI config space of LPSS devices and do any final initialization.
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND GNVS Protocol interface not found
+
+**/
+EFI_STATUS
+ConfigureLpssAtBoot (
+ IN SC_POLICY_HOB *ScPolicy
+ )
+{
+ UINTN LpssPciMmBase;
+ UINT32 LpssMmioBase0;
+ UINT32 LpssMmioBase0_High;
+ UINT32 P2sbMmioBar;
+ UINT32 Buffer32;
+ EFI_STATUS AcpiTablePresent;
+ EFI_STATUS Status;
+ UINT64 Data64;
+ UINTN AcpiTableKey;
+ UINT8 Index;
+ SC_LPSS_CONFIG *LpssConfig;
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea;
+ UINT32 PciP2sbBar0RegOffset;
+
+ DEBUG ((DEBUG_INFO, "ConfigureLpssAtBoot() Start\n"));
+ Status = GetConfigBlock ((VOID *) ScPolicy, &gLpssConfigGuid, (VOID *) &LpssConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize Variables
+ //
+ LpssPciMmBase = 0;
+ LpssMmioBase0 = 0;
+ LpssMmioBase0_High = 0;
+ P2sbMmioBar = 0;
+
+ Buffer32 = 0;
+ AcpiTablePresent = EFI_NOT_FOUND;
+ AcpiTableKey = 0;
+ Data64 = 0;
+ Index = 0;
+ Status = EFI_SUCCESS;
+
+ //
+ // Locate ACPI table
+ //
+ AcpiTablePresent = InitializeScAslUpdateLib ();
+
+ for (Index = 0; Index < LPSS_IO_DEVICE_NUM; Index++) {
+ LpssPciMmBase = MmPciBase(
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ mLpssIoDevices[Index].PciDeviceNum,
+ mLpssIoDevices[Index].PciFuncNum
+ );
+
+ LpssMmioBase0 = MmioRead32 ((UINTN) (LpssPciMmBase + R_LPSS_IO_BAR));
+ LpssMmioBase0 &= 0xFFFFFFF0; // Mask off the last byte read from BAR
+ LpssMmioBase0_High = MmioRead32 ((UINTN) (LpssPciMmBase + R_LPSS_IO_BAR_HIGH));
+
+ //
+ // Assume the MMIO address for BAR0 is always 32 bits (high DW is 0).
+ //
+ MmioWrite32 ((UINTN) (LpssMmioBase0 + R_LPSS_IO_REMAP_ADDRESS_LOW), LpssMmioBase0);
+ MmioWrite32 ((UINTN) (LpssMmioBase0 + R_LPSS_IO_REMAP_ADDRESS_HI), LpssMmioBase0_High);
+
+ DEBUG ((DEBUG_INFO, "Read back LPSS REMAP Register, High DW = 0x%x, Low DW = 0x%x, Index = %d\n",
+ MmioRead32 ((UINTN) (LpssMmioBase0 + R_LPSS_IO_REMAP_ADDRESS_HI)),
+ MmioRead32 ((UINTN) (LpssMmioBase0 + R_LPSS_IO_REMAP_ADDRESS_LOW)),
+ Index));
+
+ // Hide the UART2 device if kernel debugger mode is enabled
+ // BXT UART2 device is hidden in OnReadyToBoot (BIOS and OS use different debug COM port)
+ //
+ if (mLpssIoDevices[Index].PciDeviceNum == PCI_DEVICE_NUMBER_LPSS_HSUART
+ && mLpssIoDevices[Index].PciFuncNum == PCI_FUNCTION_NUMBER_LPSS_HSUART2
+ && GetBxtSeries () == BxtP
+ && LpssConfig->OsDbgEnable
+ && LpssMmioBase0 != 0xFFFFFFFF) {
+
+ DEBUG ((DEBUG_INFO, "Kernel Debug is Enabled\n"));
+ DEBUG ((DEBUG_INFO, "---------------------------------------------------------------------------------\n"));
+ DEBUG ((DEBUG_INFO, "This concludes BIOS serial debug messages, open the kernel debugger (WinDBG) now.\n\n"));
+ DEBUG ((DEBUG_INFO, "To enable continued serial and console redirection:\n"));
+ DEBUG ((DEBUG_INFO, " 1) Open the BIOS setup menu\n"));
+ DEBUG ((DEBUG_INFO, " 2) Navigate to Device Manager->System Setup->Debug Configuration->Kernel Debugger Enable\n"));
+ DEBUG ((DEBUG_INFO, " 3) Select the \"Disabled\" option and save\n\n"));
+
+ SideBandAndThenOr32 (
+ 0xC6,
+ 0x0F38,
+ 0xFFFFFFFF,
+ BIT0
+ );
+
+ DEBUG ((DEBUG_INFO, "Kernel Debugger Mode Enabled - LPSS D24 F2 CFG_DIS: 0x%08X\n", SideBandRead32 (0xC6, 0x0F38)));
+ }
+ }
+
+ //
+ // Update LPSS devices ACPI variables
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiGlobalNvsAreaProtocolGuid,
+ NULL,
+ (VOID **) &GlobalNvsArea
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciP2sbBar0RegOffset = (UINT32) MmPciAddress (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_P2SB,
+ PCI_FUNCTION_NUMBER_P2SB,
+ R_P2SB_BASE
+ );
+
+ //
+ // Read back P2SB MMIO BAR Base Addr
+ //
+ P2sbMmioBar = MmioRead32 (PciP2sbBar0RegOffset);
+ if (P2sbMmioBar == 0xFFFFFFFF) {
+ //
+ // P2SB has been hidden, read it from Pcd
+ //
+ P2sbMmioBar = PcdGet32 (PcdP2SBBaseAddress);
+ } else {
+ P2sbMmioBar &= B_P2SB_BAR_BA;
+ }
+
+ GlobalNvsArea->Area->GPIO0Addr = P2SB_MMIO_ADDR (P2sbMmioBar, NORTH, 0);
+ GlobalNvsArea->Area->GPIO0Len = GPIO_NORTH_COMMUNITY_LENGTH;
+
+ GlobalNvsArea->Area->GPIO1Addr = P2SB_MMIO_ADDR (P2sbMmioBar, NORTHWEST, 0);
+ GlobalNvsArea->Area->GPIO1Len = GPIO_NORTHWEST_COMMUNITY_LENGTH;
+
+ GlobalNvsArea->Area->GPIO2Addr = P2SB_MMIO_ADDR (P2sbMmioBar, WEST, 0);
+ GlobalNvsArea->Area->GPIO2Len = GPIO_WEST_COMMUNITY_LENGTH;
+
+ GlobalNvsArea->Area->GPIO3Addr = P2SB_MMIO_ADDR (P2sbMmioBar, SOUTHWEST, 0);
+ GlobalNvsArea->Area->GPIO3Len = GPIO_SOUTHWEST_COMMUNITY_LENGTH;
+
+ DEBUG ((DEBUG_INFO, "GPIOxAddr: North: 0x%X, Northwest: 0x%X, West: 0x%X, Southwest: 0x%X, South: 0x%X\n", \
+ GlobalNvsArea->Area->GPIO0Addr,
+ GlobalNvsArea->Area->GPIO1Addr,
+ GlobalNvsArea->Area->GPIO2Addr,
+ GlobalNvsArea->Area->GPIO3Addr,
+ GlobalNvsArea->Area->GPIO4Addr
+ ));
+
+#ifdef SC_PM_ENABLE
+ DEBUG ((DEBUG_INFO, "Start SC_PM_ENABLE for GPIO\n"));
+ GpioWrite (NORTH, R_GPIO_MISCCFG, GpioRead (NORTH , R_GPIO_MISCCFG) | B_GPIP_MISCCFG);
+ GpioWrite (NORTHWEST, R_GPIO_MISCCFG, GpioRead (NORTHWEST, R_GPIO_MISCCFG) | B_GPIP_MISCCFG);
+ GpioWrite (WEST, R_GPIO_MISCCFG, GpioRead (WEST , R_GPIO_MISCCFG) | B_GPIP_MISCCFG);
+ GpioWrite (SOUTHWEST, R_GPIO_MISCCFG, GpioRead (SOUTHWEST, R_GPIO_MISCCFG) | B_GPIP_MISCCFG);
+ DEBUG ((DEBUG_INFO, "End SC_PM_ENABLE for GPIO\n"));
+#endif
+
+ DEBUG ((DEBUG_INFO, "ConfigureLpssAtBoot() End\n"));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Stop Lpss devices[I2C and SPI] if any is running.
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+StopLpssAtBoot (
+ VOID
+ )
+{
+ UINTN LpssPciMmBase;
+ UINT32 LpssMmioBase0;
+ UINT8 Index;
+ UINT32 D32 = 0;
+
+ DEBUG ((DEBUG_INFO, "Stop LPSS controllers if any controller is running(I2C and SPI)...\n"));
+ for (Index = 0; Index < LPSS_IO_DEVICE_NUM; Index++) {
+ LpssPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ mLpssIoDevices[Index].PciDeviceNum,
+ mLpssIoDevices[Index].PciFuncNum
+ );
+
+ LpssMmioBase0 = MmioRead32 ((UINTN) (LpssPciMmBase + R_LPSS_IO_BAR));
+ LpssMmioBase0 &= 0xFFFFFFF0; // Mask off the last byte read from BAR
+
+ if ((mLpssIoDevices[Index].PciDeviceNum == PCI_DEVICE_NUMBER_LPSS_I2C0) || \
+ (mLpssIoDevices[Index].PciDeviceNum == PCI_DEVICE_NUMBER_LPSS_I2C1)) {
+ D32 = MmioRead32 ((UINTN) (LpssMmioBase0 + R_LPSS_I2C_IC_ENABLE));
+ if (D32 & B_LPSS_I2C_IC_ENABLE_ENABLE) {
+ DEBUG ((DEBUG_INFO, "Stop I2C controller D:%02X, F: %02X...\n", mLpssIoDevices[Index].PciDeviceNum, mLpssIoDevices[Index].PciFuncNum));
+ MmioWrite32 ((UINTN) LpssMmioBase0 + R_LPSS_I2C_IC_ENABLE, \
+ MmioRead32 ((UINTN) (LpssMmioBase0 + R_LPSS_I2C_IC_ENABLE)) & (~(UINT32) B_LPSS_I2C_IC_ENABLE_ENABLE));
+ }
+ } else if (mLpssIoDevices[Index].PciDeviceNum == PCI_DEVICE_NUMBER_LPSS_SPI) {
+ D32 = MmioRead32 ((UINTN) (LpssMmioBase0 + R_LPSS_SPI_MEM_SSP_CONTROL0));
+ if (D32 & B_LPSS_SPI_MEM_SSP_CONTROL0_SSE) {
+ DEBUG ((DEBUG_INFO, "Stop SPI controller D:%02X, F: %02X...\n", mLpssIoDevices[Index].PciDeviceNum, mLpssIoDevices[Index].PciFuncNum));
+ MmioWrite32 ((UINTN) LpssMmioBase0 + R_LPSS_SPI_MEM_SSP_CONTROL0, \
+ MmioRead32 ((UINTN) (LpssMmioBase0 + R_LPSS_SPI_MEM_SSP_CONTROL0)) & (~(UINT32) B_LPSS_SPI_MEM_SSP_CONTROL0_SSE));
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScPmc.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScPmc.c
new file mode 100644
index 0000000000..209838e68b
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScPmc.c
@@ -0,0 +1,108 @@
+/** @file
+ Initializes SC PMC Devices.
+
+ Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScInit.h"
+#include <Protocol/PciEnumerationComplete.h>
+
+/**
+ Set PMC IO enable bit (Command register (BIT2 | BIT1 | BIT0)) after PCI enumeration
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+
+**/
+VOID
+EFIAPI
+PmcPciEnumeratedCompleteNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN PmcBaseAddr;
+ UINT16 AcpiBaseAddr;
+ UINT32 IpcBaseAddr;
+
+ DEBUG ((DEBUG_INFO, "Override Broxton PMC (bus 0, device 13, function 1) bar2 (offset 0x20) to PcdScAcpiIoPortBaseAddress(0x400)\n"));
+ AcpiBaseAddr = (UINT16) PcdGet16 (PcdScAcpiIoPortBaseAddress);
+ PmcBaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PMC_IPC1,
+ PCI_FUNCTION_NUMBER_PMC_IPC1
+ );
+ MmioWrite32 (PmcBaseAddr + R_PMC_ACPI_BASE, AcpiBaseAddr);
+
+ DEBUG ((DEBUG_INFO, "Set PMC IO enable bit (Command register (BIT2 | BIT1 | BIT0)) after PCI enumeration\n"));
+ MmioOr32 (PmcBaseAddr + 0x04, (BIT2 | BIT1 | BIT0));
+
+ IpcBaseAddr = MmioRead32 (PmcBaseAddr + R_PMC_IPC1_BASE);
+ S3BootScriptSaveMemWrite (
+ EfiBootScriptWidthUint32,
+ (UINTN) (PmcBaseAddr + R_PMC_IPC1_BASE),
+ 1,
+ &IpcBaseAddr
+ );
+
+ DEBUG ((DEBUG_INFO, "PmcPciEnumeratedCompleteNotify IpcBaseAddr = 0x%x.\n", IpcBaseAddr));
+
+ gBS->CloseEvent (Event);
+}
+
+
+/**
+ Register notification function for PM configuration after PCI enumeration
+
+ @param[in] ScPolicy The SC Policy instance
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+ConfigurePmcAfterPciEnum (
+ IN SC_POLICY_HOB *ScPolicy
+ )
+{
+ EFI_EVENT PCIEnumerationCompleteEvent = NULL;
+ VOID *Registration;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "ConfigurePmcAfterPciEnum () Start\n"));
+
+ //
+ // Register InternalIpcLibPciEnumeratedNotifyEvent() notify function
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ PmcPciEnumeratedCompleteNotify,
+ NULL,
+ NULL,
+ &PCIEnumerationCompleteEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for protocol notifications on this event
+ //
+ Status = gBS->RegisterProtocolNotify (
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ PCIEnumerationCompleteEvent,
+ &Registration
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "ConfigurePmcAfterPciEnum () End\n"));
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScSata.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScSata.c
new file mode 100644
index 0000000000..63c2b88d14
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScSata.c
@@ -0,0 +1,18 @@
+/** @file
+ Perform related functions for SC Sata in DXE phase.
+
+ Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <ScInit.h>
+
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScXdci.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScXdci.c
new file mode 100644
index 0000000000..d8e5b85629
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Dxe/ScXdci.c
@@ -0,0 +1,18 @@
+/** @file
+ Initializes SC USB xDCI Device.
+
+ Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScInit.h"
+#include <Library/PcdLib.h>
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.c
new file mode 100644
index 0000000000..ed8a74b1ce
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.c
@@ -0,0 +1,183 @@
+/** @file
+ SC Init Smm module for SC specific SMI handlers.
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScInitSmm.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SW_DISPATCH2_PROTOCOL *mSwDispatch;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
+GLOBAL_REMOVE_IF_UNREFERENCED SC_NVS_AREA *mScNvsArea;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mAcpiBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED SC_POLICY_HOB *mScPolicy;
+GLOBAL_REMOVE_IF_UNREFERENCED SC_PCIE_CONFIG *mPcieRpConfig;
+
+//
+// The reserved MMIO range to be used in Sx handler
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS mResvMmioBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mResvMmioSize;
+
+
+/**
+ PCH Sx entry SMI handler.
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+ @param[in, out] CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param[in, out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+PchSxHandler (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize PCH Sx entry SMI handler.
+
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval None
+
+**/
+VOID
+InitializeSxHandler (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_SMM_SX_REGISTER_CONTEXT SxDispatchContext;
+ EFI_HANDLE SxDispatchHandle;
+ EFI_SLEEP_TYPE SxType;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "InitializeSxHandler() Start\n"));
+
+ //
+ // Register the callback for S3/S4/S5 entry
+ //
+ SxDispatchContext.Phase = SxEntry;
+ for (SxType = SxS3; SxType <= SxS5; SxType++) {
+ SxDispatchContext.Type = SxType;
+ Status = mSxDispatch->Register (
+ mSxDispatch,
+ PchSxHandler,
+ &SxDispatchContext,
+ &SxDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ DEBUG ((DEBUG_INFO, "InitializeSxHandler() End\n"));
+}
+
+
+/**
+ Initializes the PCH SMM handler for for PCIE hot plug support
+ <b>PchInit SMM Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchInitSmm module is a SMM driver that initializes the Intel Platform Controller Hub
+ SMM requirements and services. It consumes the PCH_POLICY_PROTOCOL for expected
+ configurations per policy.
+
+ - <b>Details</b>\n
+ This module provides SMI handlers to services PCIE HotPlug SMI, LinkActive SMI, and LinkEq SMI.
+ And also provides port 0x61 emulation support, GPIO Sx isolation requirement, and register BIOS WP
+ handler to process BIOSWP status.
+
+ - @pre
+ - @link _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL @endlink
+ - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+ - EFI_SMM_BASE2_PROTOCOL
+ - @link _EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL @endlink
+ - @link _EFI_SMM_SX_DISPATCH2_PROTOCOL EFI_SMM_SX_DISPATCH2_PROTOCOL @endlink
+ - @link _EFI_SMM_CPU_PROTOCOL EFI_SMM_CPU_PROTOCOL @endlink
+ - @link _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_PCIE_SMI_DISPATCH_PROTOCOL PCH_PCIE_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_TCO_SMI_DISPATCH_PROTOCOL PCH_TCO_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_ESPI_SMI_DISPATCH_PROTOCOL PCH_ESPI_SMI_DISPATCH_PROTOCOL @endlink
+ - SC_NVS_AREA_PROTOCOL
+ - @link PeiDxeSmmPchPlatformLib.h PeiDxeSmmPchPlatformLib @endlink library
+ - @link PeiDxeSmmPchPciExpressHelpersLib.h PchPciExpressHelpersLib @endlink library
+
+ - <b>References</b>\n
+ @link _PCH_POLICY PCH_POLICY_PROTOCOL @endlink.
+
+ - <b>Integration Checklists</b>\n
+ - Verify prerequisites are met. Porting Recommendations.
+ - No modification of this module should be necessary
+ - Any modification of this module should follow the PCH BIOS Specification and EDS
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS PCH SMM handler was installed
+
+**/
+EFI_STATUS
+EFIAPI
+ScInitSmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS HobPtr;
+
+ DEBUG ((DEBUG_INFO, "ScInitSmmEntryPoint()\n"));
+
+ //
+ // Locate the SMM SW dispatch protocol
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ NULL,
+ (VOID **) &mSwDispatch
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ NULL,
+ (VOID**) &mSxDispatch
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Sc Policy Hob
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gScPolicyHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mScPolicy = (SC_POLICY_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ Status = GetConfigBlock ((VOID *) mScPolicy, &gPcieRpConfigGuid, (VOID *) &mPcieRpConfig);
+ ASSERT_EFI_ERROR (Status);
+ InitializeSxHandler (ImageHandle);
+
+ Status = InitializeScPcieSmm (ImageHandle, SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.h
new file mode 100644
index 0000000000..81748ba1f0
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.h
@@ -0,0 +1,320 @@
+/** @file
+ Header file for SC Init SMM Handler
+
+ Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SC_INIT_SMM_H_
+#define _SC_INIT_SMM_H_
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmIoTrapDispatch2.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/HobLib.h>
+#include <Protocol/SmmCpu.h>
+#include <IndustryStandard/Pci30.h>
+#include <ScAccess.h>
+#include <Library/ScPlatformLib.h>
+#include <Library/MmPciLib.h>
+#include <Private/Library/PeiDxeSmmScPciExpressHelpersLib.h>
+#include <Private/Guid/ScPolicyHobGuid.h>
+#include <Ppi/ScPcieDeviceTable.h>
+#include <Protocol/ScPcieSmiDispatch.h>
+#include <Protocol/ScSmmIoTrapControl.h>
+#include <Private/Protocol/ScNvs.h>
+#include <Private/Protocol/PcieIoTrap.h>
+#include <Include/SiPolicyHob.h>
+#include <Library/ConfigBlockLib.h>
+
+extern EFI_SMM_SW_DISPATCH2_PROTOCOL *mSwDispatch;
+extern EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
+extern SC_NVS_AREA *mScNvsArea;
+extern UINT16 mAcpiBaseAddr;
+extern SC_POLICY_HOB *mScPolicy;
+extern SC_PCIE_CONFIG *mPcieRpConfig;
+extern EFI_PHYSICAL_ADDRESS mResvMmioBaseAddr;
+extern UINTN mResvMmioSize;
+
+#define EFI_PCI_CAPABILITY_ID_PCIPM 0x01
+
+#define DeviceD0 0x00
+#define DeviceD3 0x03
+
+#define ARRAY_SIZE (data) (sizeof (data) / sizeof (data[0]))
+
+typedef enum {
+ PciCfg,
+ PciMmr
+} SC_PCI_ACCESS_TYPE;
+
+typedef enum {
+ Acpi,
+ Rcrb,
+ Tco
+} SC_ACCESS_TYPE;
+
+typedef struct {
+ SC_ACCESS_TYPE AccessType;
+ UINT32 Address;
+ UINT32 Data;
+ UINT32 Mask;
+ UINT8 Width;
+} SC_SAVE_RESTORE_REG;
+
+typedef struct {
+ SC_SAVE_RESTORE_REG* ScSaveRestoreReg;
+ UINT8 size;
+} SC_SAVE_RESTORE_REG_WRAP;
+
+struct _SC_SAVE_RESTORE_PCI;
+
+typedef struct _SC_SAVE_RESTORE_PCI{
+ SC_PCI_ACCESS_TYPE AccessType;
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 BarOffset;
+ UINT16 Offset;
+ UINT32 Data;
+ UINT32 Mask;
+ UINT8 Width;
+ VOID (*RestoreFunction) (struct _SC_SAVE_RESTORE_PCI *ScSaveRestorePci);
+} SC_SAVE_RESTORE_PCI;
+
+typedef struct {
+ SC_SAVE_RESTORE_PCI* ScSaveRestorePci;
+ UINT8 size;
+} Sc_SAVE_RESTORE_PCI_WRAP;
+
+typedef struct {
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 PowerState;
+} DEVICE_POWER_STATE;
+
+/**
+ 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
+InitializeScPcieSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Program Common Clock and ASPM of Downstream Devices
+
+ @param[in] PortIndex Pcie Root Port Number
+ @param[in] RpDevice Pcie Root Pci Device Number
+ @param[in] RpFunction Pcie Root Pci Function Number
+
+ @retval EFI_SUCCESS Root port complete successfully
+ @retval EFI_UNSUPPORTED PMC has invalid vendor ID
+
+**/
+EFI_STATUS
+ScPcieSmi (
+ IN UINT8 PortIndex,
+ IN UINT8 RpDevice,
+ IN UINT8 RpFunction
+ );
+
+/**
+ PCIE Link Active State Change Hotplug SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+
+ @retval None
+
+**/
+VOID
+EFIAPI
+ScPcieLinkActiveStateChange (
+ IN EFI_HANDLE DispatchHandle,
+ IN SC_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ PCIE Link Equalization Request SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+
+ @retval None
+
+**/
+VOID
+EFIAPI
+ScPcieLinkEqHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN SC_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ The SW SMI callback to config PCIE power management settings
+
+ @param[in] DispatchHandle The handle of this callback, obtained when registering
+ @param[in] CallbackContext Pointer to the EFI_SMM_SW_REGISTER_CONTEXT
+ @param[in, out] CommBuffer Point to the CommBuffer structure
+ @param[in, out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+ScPciePmSwSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_REGISTER_CONTEXT *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+/**
+ Initializes the PCH SMM handler for PCH save and restore
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS PCH SMM handler was installed
+
+**/
+EFI_STATUS
+EFIAPI
+ScInitLateSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Locate required protocol and register the 61h IO trap
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS PCH SMM handler was installed
+
+**/
+EFI_STATUS
+EFIAPI
+InstallIoTrapPort61h (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Initialize PCH Sx entry SMI handler.
+
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval None
+
+**/
+VOID
+InitializeSxHandler (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ PCH Sx entry SMI handler.
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+ @param[in, out] CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param[in, out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+ScSxHandler (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ );
+
+/**
+ GbE Sx entry handler.
+
+ @param[in] None
+
+ @retval None
+
+**/
+VOID
+ScLanSxCallback (
+ VOID
+ );
+
+/**
+ This function performs GPIO Sx Isolation steps.
+
+ @param[in] None
+
+ @retval None
+
+**/
+VOID
+ScGpioSxIsolationCallBack (
+ VOID
+ );
+
+/**
+ Register dispatch function to handle GPIO pads Sx isolation
+
+ @param[in] None
+
+ @retval None
+
+**/
+VOID
+InitializeGpioSxIsolationSmm (
+ VOID
+ );
+
+/**
+ Entry point for Sc Bios Write Protect driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallScBiosWriteProtect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.inf
new file mode 100644
index 0000000000..30d01b60e1
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScInitSmm.inf
@@ -0,0 +1,81 @@
+## @file
+# PchInitSmm driver.
+#
+# Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ScInitSmm
+ FILE_GUID = D7B10D4E-67E6-4C74-83E9-F9AF0ACC33CC
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = ScInitSmmEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ ScInitSmm.c
+ ScPcieSmm.c
+ ScInitSmm.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ DxeServicesTableLib
+ IoLib
+ DebugLib
+ BaseLib
+ BaseMemoryLib
+ S3BootScriptLib
+ PeiDxeSmmScPciExpressHelpersLib
+ SmmServicesTableLib
+ MmPciLib
+ HobLib
+ ReportStatusCodeLib
+ DevicePathLib
+ ScPlatformLib
+ TimerLib
+ ConfigBlockLib
+
+[Guids]
+ gSiPolicyHobGuid ## UNDEFINED
+ gScDeviceTableHobGuid ## UNDEFINED
+ gScPolicyHobGuid ## UNDEFINED
+ gPcieRpConfigGuid
+
+[Protocols]
+ gEfiSmmSwDispatch2ProtocolGuid ## CONSUMES
+ gEfiSmmSxDispatch2ProtocolGuid ## CONSUMES
+ gScSmmIoTrapControlGuid ## CONSUMES
+ gEfiSmmCpuProtocolGuid ## CONSUMES
+ gScNvsAreaProtocolGuid ## CONSUMES
+ gScPcieSmiDispatchProtocolGuid ## CONSUMES
+
+[Depex]
+ gEfiSmmBase2ProtocolGuid AND
+ gEfiSmmSwDispatch2ProtocolGuid AND
+ gEfiSmmSxDispatch2ProtocolGuid AND
+ gEfiSmmCpuProtocolGuid
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## SOMETIMES_CONSUMES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScPcieSmm.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScPcieSmm.c
new file mode 100644
index 0000000000..afc455b0f7
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/ScInit/Smm/ScPcieSmm.c
@@ -0,0 +1,328 @@
+/** @file
+ PCH Pcie SMM Driver Entry.
+
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScInitSmm.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED SC_PCIE_DEVICE_OVERRIDE *mDevAspmOverride;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mNumOfDevAspmOverride;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPolicyRevision;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchBusNumber;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mTempRootPortBusNumMin;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mTempRootPortBusNumMax;
+GLOBAL_REMOVE_IF_UNREFERENCED SC_PCIE_ROOT_PORT_CONFIG mPcieRootPortConfig[PCIE_MAX_ROOT_PORTS];
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mLtrNonSupportRpBitMap;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mPciePmSwSmiExecuted = FALSE;
+
+extern EFI_GUID gScDeviceTableHobGuid;
+
+/**
+ PCIE Link Active State Change Hotplug SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+
+ @retval None
+
+**/
+VOID
+EFIAPI
+ScPcieLinkActiveStateChange (
+ IN EFI_HANDLE DispatchHandle,
+ IN SC_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ return;
+}
+
+
+/**
+ PCIE Link Equalization Request SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+
+ @retval None
+
+**/
+VOID
+EFIAPI
+ScPcieLinkEqHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN SC_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ return;
+}
+
+
+/**
+ An IoTrap callback to config PCIE power management settings
+
+ @param[in] None
+
+ @retval None
+
+**/
+VOID
+ScPciePmIoTrapSmiCallback (
+ VOID
+ )
+{
+ UINT8 PortIndex;
+ UINTN RpBase;
+ UINTN RpDevice;
+ UINTN RpFunction;
+ BOOLEAN L1SubstatesSupportedPerPort;
+ UINT16 AspmVal;
+ BOOLEAN ClkreqPerPortSupported;
+ BOOLEAN ClkreqSupportedInAllEnabledPorts;
+ BOOLEAN L1SupportedInAllEnabledPorts;
+ BOOLEAN FirstRPToSetPm;
+ BOOLEAN LtrSupported;
+ BOOLEAN IsAnyRootPortEnabled;
+ UINT8 MaxPciePortNum;
+
+ AspmVal = 0;
+ L1SubstatesSupportedPerPort = FALSE;
+ ClkreqPerPortSupported = FALSE;
+ ClkreqSupportedInAllEnabledPorts = TRUE;
+ L1SupportedInAllEnabledPorts = TRUE;
+ FirstRPToSetPm = TRUE;
+ LtrSupported = TRUE;
+ IsAnyRootPortEnabled = FALSE;
+ MaxPciePortNum = GetScMaxPciePortNum ();
+
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
+ GetScPcieRpDevFun (PortIndex, &RpDevice, &RpFunction);
+ RpBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_SC, (UINT32) RpDevice, (UINT32) RpFunction);
+
+ if ((MmioRead16 (RpBase) != 0xFFFF) &&
+ ((MmioRead16 (RpBase + R_PCH_PCIE_SLSTS) & B_PCIE_SLSTS_PDS) != 0)) {
+ PcieCheckPmConfig (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ (UINT8) RpDevice,
+ (UINT8) RpFunction,
+ mNumOfDevAspmOverride,
+ mDevAspmOverride,
+ mTempRootPortBusNumMin,
+ mTempRootPortBusNumMax,
+ &mPcieRootPortConfig[PortIndex],
+ &L1SubstatesSupportedPerPort,
+ mPolicyRevision,
+ &AspmVal,
+ &ClkreqPerPortSupported,
+ &LtrSupported
+ );
+
+ if ((AspmVal & V_PCIE_LCTL_ASPM_L1) != V_PCIE_LCTL_ASPM_L1) {
+ L1SupportedInAllEnabledPorts = FALSE;
+ }
+
+ if (ClkreqPerPortSupported == FALSE) {
+ ClkreqSupportedInAllEnabledPorts = FALSE;
+ }
+
+ if (!LtrSupported) {
+ mLtrNonSupportRpBitMap |= 1<<PortIndex;
+ }
+
+ IsAnyRootPortEnabled = TRUE;
+ }
+ }
+
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
+ GetScPcieRpDevFun (PortIndex, &RpDevice, &RpFunction);
+ RpBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_SC, (UINT32) RpDevice, (UINT32) RpFunction);
+
+ if (MmioRead16 (RpBase) != 0xFFFF) {
+ PcieSetPm (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ (UINT8) RpDevice,
+ (UINT8) RpFunction,
+ mNumOfDevAspmOverride,
+ mDevAspmOverride,
+ mTempRootPortBusNumMin,
+ mTempRootPortBusNumMax,
+ &mPcieRootPortConfig[PortIndex],
+ &L1SubstatesSupportedPerPort,
+ mPolicyRevision,
+ FirstRPToSetPm,
+ L1SupportedInAllEnabledPorts,
+ ClkreqSupportedInAllEnabledPorts,
+ &LtrSupported,
+ TRUE
+ );
+
+ FirstRPToSetPm = FALSE;
+ }
+ }
+}
+
+
+/**
+ The SW SMI callback to config PCIE power management settings
+
+ @param[in] DispatchHandle The handle of this callback, obtained when registering
+ @param[in] CallbackContext Pointer to the EFI_SMM_SW_REGISTER_CONTEXT
+ @param[in, out] CommBuffer Point to the CommBuffer structure
+ @param[in, out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+ScPciePmSwSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_REGISTER_CONTEXT *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ if (DispatchContext->SwSmiInputValue == mPcieRpConfig->AspmSwSmiNumber) {
+ if (mPciePmSwSmiExecuted == FALSE) {
+ ScPciePmIoTrapSmiCallback ();
+ mPciePmSwSmiExecuted = TRUE;
+ }
+ } else {
+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+ }
+}
+
+
+/**
+ This function clear the Io trap executed flag before enter S3
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+ @param[in, out] CommBuffer Point to the CommBuffer structure
+ @param[in, out] CommBufferSize Point to the Size of CommBuffer structure
+
+ @retval EFI_SUCCESS PCH register saved
+
+**/
+EFI_STATUS
+EFIAPI
+ScPcieS3EntryCallBack (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ mPciePmSwSmiExecuted = FALSE;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+InitializeScPcieSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE* Hob;
+ UINT32 DevTableSize;
+ EFI_HANDLE SwDispatchHandle;
+ EFI_SMM_SW_REGISTER_CONTEXT SwDispatchContext;
+ EFI_HANDLE SxDispatchHandle;
+ EFI_SMM_SX_REGISTER_CONTEXT SxDispatchContext;
+ UINT8 MaxPciePortNum;
+ SI_POLICY_HOB *SiPolicyHob;
+
+ DEBUG ((DEBUG_INFO, "InitializeScPcieSmm () Start\n"));
+
+ MaxPciePortNum = GetScMaxPciePortNum ();
+
+ //
+ // Get Silicon Policy data HOB
+ //
+ Hob = GetFirstGuidHob (&gSiPolicyHobGuid);
+ if (Hob == NULL) {
+ ASSERT (Hob != NULL);
+ return EFI_NOT_FOUND;
+ }
+
+ SiPolicyHob = GET_GUID_HOB_DATA (Hob);
+ mPolicyRevision = mScPolicy->TableHeader.Header.Revision;
+ mPchBusNumber = DEFAULT_PCI_BUS_NUMBER_SC;
+ mTempRootPortBusNumMin = SiPolicyHob->TempPciBusMin;
+ mTempRootPortBusNumMax = SiPolicyHob->TempPciBusMax;
+
+ ASSERT (sizeof (mPcieRootPortConfig) == sizeof (mPcieRpConfig->RootPort));
+ CopyMem (
+ mPcieRootPortConfig,
+ &(mPcieRpConfig->RootPort),
+ sizeof (mPcieRootPortConfig)
+ );
+
+ mDevAspmOverride = NULL;
+ mNumOfDevAspmOverride = 0;
+ mLtrNonSupportRpBitMap = 0;
+
+ Hob = GetFirstGuidHob (&gScDeviceTableHobGuid);
+ if (Hob != NULL) {
+ DevTableSize = GET_GUID_HOB_DATA_SIZE (Hob);
+ ASSERT ((DevTableSize % sizeof (SC_PCIE_DEVICE_OVERRIDE)) == 0);
+ mNumOfDevAspmOverride = DevTableSize / sizeof (SC_PCIE_DEVICE_OVERRIDE);
+ DEBUG ((DEBUG_INFO, "Found PcieDeviceTable HOB (%d entries)\n", mNumOfDevAspmOverride));
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ DevTableSize,
+ (VOID **) &mDevAspmOverride
+ );
+ CopyMem (mDevAspmOverride, GET_GUID_HOB_DATA (Hob), DevTableSize);
+ }
+
+ //
+ // Register PCIe ASPM SW SMI handler
+ //
+ SwDispatchHandle = NULL;
+ SwDispatchContext.SwSmiInputValue = mPcieRpConfig->AspmSwSmiNumber;
+ Status = mSwDispatch->Register (
+ mSwDispatch,
+ (EFI_SMM_HANDLER_ENTRY_POINT2) ScPciePmSwSmiCallback,
+ &SwDispatchContext,
+ &SwDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register the callback for S3 entry
+ //
+ SxDispatchContext.Type = SxS3;
+ SxDispatchContext.Phase = SxEntry;
+ Status = mSxDispatch->Register (
+ mSxDispatch,
+ ScPcieS3EntryCallBack,
+ &SxDispatchContext,
+ &SxDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "InitializeScPcieSmm () End\n"));
+
+ return EFI_SUCCESS;
+}
+