/** @file
  This file is PeiPchPolicy library.

Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/
#include "PeiPchPolicyLibrary.h"

/**
  mDevIntConfig[] table contains data on INTx and IRQ for each device.
  IRQ value for devices which use ITSS INTx->PIRQx mapping need to be set in a way
  that for each multifunctional Dxx:Fy same interrupt pins must map to the same IRQ.
  Those IRQ values will be used to update ITSS.PIRx register.
  In APIC relationship between PIRQs and IRQs is:
  PIRQA -> IRQ16
  PIRQB -> IRQ17
  PIRQC -> IRQ18
  PIRQD -> IRQ19
  PIRQE -> IRQ20
  PIRQF -> IRQ21
  PIRQG -> IRQ22
  PIRQH -> IRQ23

  Devices which use INTx->PIRQy mapping are: cAVS(in PCI mode), SMBus, GbE, TraceHub, PCIe,
  SATA, HECI, IDE-R, KT Redirection, xHCI, Thermal Subsystem, Camera IO Host Controller

  PCI Express Root Ports mapping should be programmed only with values as in below table (D27/28/29)
  otherwise _PRT methods in ACPI for RootPorts would require additional patching as
  PCIe Endpoint Device Interrupt is further subjected to INTx to PIRQy Mapping

  Configured IRQ values are not used if an OS chooses to be in PIC instead of APIC mode
**/
GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG mDevIntConfig[] = {
//  {31, 0, PchNoInt, 0}, // LPC/eSPI Interface, doesn't use interrupts
//  {31, 1, PchNoInt, 0}, // P2SB, doesn't use interrupts
//  {31, 2, PchNoInt, 0}, // PMC , doesn't use interrupts
  {31, 3, PchIntA, 16}, // cAVS(Audio, Voice, Speach), INTA is default, programmed in PciCfgSpace 3Dh
  {31, 4, PchIntA, 16}, // SMBus Controller, no default value, programmed in PciCfgSpace 3Dh
//  {31, 5, PchNoInt, 0}, // SPI , doesn't use interrupts
  {31, 6, PchIntA, 16}, // GbE Controller, INTA is default, programmed in PciCfgSpace 3Dh
  {31, 7, PchIntA, 16}, // TraceHub, INTA is default, RO register
  {30, 0, PchIntA, 20}, // SerialIo: UART #0, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[7]
  {30, 1, PchIntB, 21}, // SerialIo: UART #1, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[8]
  {30, 2, PchIntC, 22}, // SerialIo: SPI #0, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[10]
  {30, 3, PchIntD, 23}, // SerialIo: SPI #1, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[11]
  {30, 4, PchIntB, 21}, // SCS: eMMC (SKL PCH-LP Only)
  {30, 5, PchIntC, 22}, // SCS: SDIO (SKL PCH-LP Only)
  {30, 6, PchIntD, 23}, // SCS: SDCard (SKL PCH-LP Only)
  {29, 0, PchIntA, 16}, // PCI Express Port 9, INT is default, programmed in PciCfgSpace + FCh
  {29, 1, PchIntB, 17}, // PCI Express Port 10, INT is default, programmed in PciCfgSpace + FCh
  {29, 2, PchIntC, 18}, // PCI Express Port 11, INT is default, programmed in PciCfgSpace + FCh
  {29, 3, PchIntD, 19}, // PCI Express Port 12, INT is default, programmed in PciCfgSpace + FCh
  {29, 4, PchIntA, 16}, // PCI Express Port 13 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {29, 5, PchIntB, 17}, // PCI Express Port 14 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {29, 6, PchIntC, 18}, // PCI Express Port 15 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {29, 7, PchIntD, 19}, // PCI Express Port 16 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {28, 0, PchIntA, 16}, // PCI Express Port 1, INT is default, programmed in PciCfgSpace + FCh
  {28, 1, PchIntB, 17}, // PCI Express Port 2, INT is default, programmed in PciCfgSpace + FCh
  {28, 2, PchIntC, 18}, // PCI Express Port 3, INT is default, programmed in PciCfgSpace + FCh
  {28, 3, PchIntD, 19}, // PCI Express Port 4, INT is default, programmed in PciCfgSpace + FCh
  {28, 4, PchIntA, 16}, // PCI Express Port 5, INT is default, programmed in PciCfgSpace + FCh
  {28, 5, PchIntB, 17}, // PCI Express Port 6, INT is default, programmed in PciCfgSpace + FCh
  {28, 6, PchIntC, 18}, // PCI Express Port 7, INT is default, programmed in PciCfgSpace + FCh
  {28, 7, PchIntD, 19}, // PCI Express Port 8, INT is default, programmed in PciCfgSpace + FCh
  {27, 0, PchIntA, 16}, // PCI Express Port 17 (PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {27, 1, PchIntB, 17}, // PCI Express Port 18 (PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {27, 2, PchIntC, 18}, // PCI Express Port 19 (PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {27, 3, PchIntD, 19}, // PCI Express Port 20 (PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {27, 4, PchIntA, 16}, // PCI Express Port 21 (KBL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {27, 5, PchIntB, 17}, // PCI Express Port 22 (KBL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {27, 6, PchIntC, 18}, // PCI Express Port 23 (KBL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {27, 7, PchIntD, 19}, // PCI Express Port 24 (KBL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
  {25, 0, PchIntA, 32}, // SerialIo UART Controller #2, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[9]
//  {24, 0, 0, 0}, // Reserved (used by RST PCIe Storage Cycle Router)
  {23, 0, PchIntA, 16}, // SATA Controller, INTA is default, programmed in PciCfgSpace + 3Dh
  {22, 0, PchIntA, 16}, // CSME: HECI #1
  {22, 1, PchIntB, 17}, // CSME: HECI #2
  {22, 2, PchIntC, 18}, // CSME: IDE-Redirection (IDE-R)
  {22, 3, PchIntD, 19}, // CSME: Keyboard and Text (KT) Redirection
  {22, 4, PchIntA, 16}, // CSME: HECI #3
//  {22, 7, PchNoInt, 0}, // CSME: WLAN
  {21, 0, PchIntA, 16}, // SerialIo I2C Controller #0, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[1]
  {21, 1, PchIntB, 17}, // SerialIo I2C Controller #1, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[2]
  {21, 2, PchIntC, 18}, // SerialIo I2C Controller #2, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[3]
  {21, 3, PchIntD, 19}, // SerialIo I2C Controller #3, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[4]
  {20, 0, PchIntA, 16}, // USB 3.0 xHCI Controller, no default value, programmed in PciCfgSpace 3Dh
  {20, 1, PchIntB, 17}, // USB Device Controller (OTG)
  {20, 2, PchIntC, 18}, // Thermal Subsystem
  {20, 3, PchIntA, 16}, // Camera IO Host Controller
//  {20, 4, 0, 0}, // TraceHub Phantom (ACPI) Function
  {19, 0, PchIntA, 20}, // Integrated Sensor Hub
//  {18, 0, PchNoInt, 0}, // CSME: KVMcc,  doesn't use interrupts
//  {18, 1, PchNoInt, 0}, // CSME: Clink,  doesn't use interrupts
//  {18, 2, PchNoInt, 0}, // CSME: PMT,  doesn't use interrupts
//  {18, 3, 0, 0}, // CSME: CSE UMA
//  {18, 4, 0, 0}  // CSME: fTPM DMA
};

//
// mLpOnlyDevIntConfig[] table contains data on INTx and IRQ for devices that exist on SPT-LP but not on SPT-H.
//
GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG mLpOnlyDevIntConfig[] = {
  {25, 1, PchIntB, 33}, // SerialIo I2C Controller #5, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[6]
  {25, 2, PchIntC, 34}  // SerialIo I2C Controller #4, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[5]
};
/**
  mPxRcConfig[] table contains data for 8259 routing (how PIRQx is mapped to IRQy).
  This information is used by systems which choose to use legacy PIC
  interrupt controller. Only IRQ3-7,9-12,14,15 are valid. Values from this table
  will be programmed into ITSS.PxRC registers.
**/
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPxRcConfig[] = {
  11,  // PARC: PIRQA -> IRQ11
  10,  // PBRC: PIRQB -> IRQ10
  11,  // PCRC: PIRQC -> IRQ11
  11,  // PDRC: PIRQD -> IRQ11
  11,  // PERC: PIRQE -> IRQ11
  11,  // PFRC: PIRQF -> IRQ11
  11,  // PGRC: PIRQG -> IRQ11
  11   // PHRC: PIRQH -> IRQ11
};

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadPchGeneralConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_GENERAL_CONFIG  *PchGeneralConfig;
  PchGeneralConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "PchGeneralConfig->Header.GuidHob.Name = %g\n", &PchGeneralConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "PchGeneralConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PchGeneralConfig->Header.GuidHob.Header.HobLength));

  /********************************
    PCH general configuration
  ********************************/
  //
  // Default SVID SDID configuration
  //
  PchGeneralConfig->SubSystemVendorId = V_PCH_INTEL_VENDOR_ID;
  PchGeneralConfig->SubSystemId       = V_PCH_DEFAULT_SID;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadPcieRpConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  UINTN            PortIndex;
  PCH_SERIES       PchSeries;
  PCH_PCIE_CONFIG  *PcieRpConfig;

  PcieRpConfig = ConfigBlockPointer;
  PchSeries = GetPchSeries ();

  DEBUG ((DEBUG_INFO, "PcieRpConfig->Header.GuidHob.Name = %g\n", &PcieRpConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "PcieRpConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PcieRpConfig->Header.GuidHob.Header.HobLength));

  /********************************
    PCI Express related settings
  ********************************/
  PcieRpConfig->RpFunctionSwap = TRUE;

  for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) {
    PcieRpConfig->RootPort[PortIndex].Aspm                 = PchPcieAspmAutoConfig;
    PcieRpConfig->RootPort[PortIndex].PmSci                = TRUE;
    PcieRpConfig->RootPort[PortIndex].AcsEnabled           = TRUE;
    PcieRpConfig->RootPort[PortIndex].MaxPayload           = PchPcieMaxPayload256;
    PcieRpConfig->RootPort[PortIndex].EnableHotplugSmi     = TRUE;
    PcieRpConfig->RootPort[PortIndex].PhysicalSlotNumber   = (UINT8) PortIndex;
    PcieRpConfig->RootPort[PortIndex].L1Substates          = PchPcieL1SubstatesL1_1_2;
    PcieRpConfig->RootPort[PortIndex].EnableCpm            = TRUE;

    //
    // PCIe LTR Configuration.
    //
    PcieRpConfig->RootPort[PortIndex].LtrEnable             = TRUE;
    if (PchSeries == PchLp) {
      PcieRpConfig->RootPort[PortIndex].LtrMaxSnoopLatency               = 0x1003;
      PcieRpConfig->RootPort[PortIndex].LtrMaxNoSnoopLatency             = 0x1003;
    }
    if (PchSeries == PchH) {
      PcieRpConfig->RootPort[PortIndex].LtrMaxSnoopLatency               = 0x0846;
      PcieRpConfig->RootPort[PortIndex].LtrMaxNoSnoopLatency             = 0x0846;
    }
    PcieRpConfig->RootPort[PortIndex].SnoopLatencyOverrideMode           = 2;
    PcieRpConfig->RootPort[PortIndex].SnoopLatencyOverrideMultiplier     = 2;
    PcieRpConfig->RootPort[PortIndex].SnoopLatencyOverrideValue          = 60;
    PcieRpConfig->RootPort[PortIndex].NonSnoopLatencyOverrideMode        = 2;
    PcieRpConfig->RootPort[PortIndex].NonSnoopLatencyOverrideMultiplier  = 2;
    PcieRpConfig->RootPort[PortIndex].NonSnoopLatencyOverrideValue       = 60;

    PcieRpConfig->RootPort[PortIndex].Uptp                               = 5;
    PcieRpConfig->RootPort[PortIndex].Dptp                               = 7;

    PcieRpConfig->EqPh3LaneParam[PortIndex].Cm                           = 6;
    PcieRpConfig->EqPh3LaneParam[PortIndex].Cp                           = 2;
  }

  PcieRpConfig->SwEqCoeffList[0].Cm = 6;
  PcieRpConfig->SwEqCoeffList[0].Cp = 2;
  PcieRpConfig->SwEqCoeffList[1].Cm = 4;
  PcieRpConfig->SwEqCoeffList[1].Cp = 2;
  PcieRpConfig->SwEqCoeffList[2].Cm = 8;
  PcieRpConfig->SwEqCoeffList[2].Cp = 2;
  PcieRpConfig->SwEqCoeffList[3].Cm = 2;
  PcieRpConfig->SwEqCoeffList[3].Cp = 2;
  PcieRpConfig->SwEqCoeffList[4].Cm = 10;
  PcieRpConfig->SwEqCoeffList[4].Cp = 2;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadSataConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  UINTN            PortIndex;
  UINTN            Index;
  PCH_SATA_CONFIG  *SataConfig;
  SataConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "SataConfig->Header.GuidHob.Name = %g\n", &SataConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "SataConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SataConfig->Header.GuidHob.Header.HobLength));

  /********************************
    SATA related settings
  ********************************/
  SataConfig->Enable               = TRUE;
  SataConfig->SalpSupport          = TRUE;
  SataConfig->SataMode             = PchSataModeAhci;

  for (PortIndex = 0; PortIndex < GetPchMaxSataPortNum (); PortIndex++) {
    SataConfig->PortSettings[PortIndex].Enable           = TRUE;
    SataConfig->PortSettings[PortIndex].DmVal            = 15;
    SataConfig->PortSettings[PortIndex].DitoVal          = 625;
  }

  SataConfig->Rst.Raid0            = TRUE;
  SataConfig->Rst.Raid1            = TRUE;
  SataConfig->Rst.Raid10           = TRUE;
  SataConfig->Rst.Raid5            = TRUE;
  SataConfig->Rst.Irrt             = TRUE;
  SataConfig->Rst.OromUiBanner     = TRUE;
  SataConfig->Rst.OromUiDelay      = PchSataOromDelay2sec;
  SataConfig->Rst.HddUnlock        = TRUE;
  SataConfig->Rst.LedLocate        = TRUE;
  SataConfig->Rst.IrrtOnly         = TRUE;
  SataConfig->Rst.SmartStorage     = TRUE;
  SataConfig->Rst.OptaneMemory     = TRUE;

  for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
    SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay             = 100;
  }

  SataConfig->PwrOptEnable     = TRUE;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadIoApicConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_IOAPIC_CONFIG  *IoApicConfig;
  IoApicConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "IoApicConfig->Header.GuidHob.Name = %g\n", &IoApicConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "IoApicConfig->Header.GuidHob.Header.HobLength = 0x%x\n", IoApicConfig->Header.GuidHob.Header.HobLength));

  /********************************
    Io Apic configuration
  ********************************/
  IoApicConfig->IoApicId           = 0x02;
  IoApicConfig->IoApicEntry24_119  = TRUE;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadCio2ConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_CIO2_CONFIG  *Cio2Config;
  Cio2Config = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "Cio2Config->Header.GuidHob.Name = %g\n", &Cio2Config->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "Cio2Config->Header.GuidHob.Header.HobLength = 0x%x\n", Cio2Config->Header.GuidHob.Header.HobLength));

  /********************************
    Initialize CIO2 Config and FLS config
  ********************************/
  Cio2Config->DeviceEnable         = TRUE;
  Cio2Config->PortATrimEnable      = TRUE;
  Cio2Config->PortBTrimEnable      = TRUE;
  Cio2Config->PortCTrimEnable      = TRUE;
  Cio2Config->PortDTrimEnable      = TRUE;
  Cio2Config->PortACtleEnable      = TRUE;
  Cio2Config->PortBCtleEnable      = TRUE;
  Cio2Config->PortCDCtleEnable     = TRUE;
  Cio2Config->PortACtleCapValue    = 0xE;
  Cio2Config->PortBCtleCapValue    = 0xE;
  Cio2Config->PortCDCtleCapValue   = 0xE;
  Cio2Config->PortACtleResValue    = 0xD;
  Cio2Config->PortBCtleResValue    = 0xD;
  Cio2Config->PortCDCtleResValue   = 0xD;
  Cio2Config->PortAClkTrimValue    = 0xA;
  Cio2Config->PortBClkTrimValue    = 0xA;
  Cio2Config->PortCClkTrimValue    = 0x9;
  Cio2Config->PortDClkTrimValue    = 0xA;
  Cio2Config->PortADataTrimValue   = 0xBBBB;
  Cio2Config->PortBDataTrimValue   = 0xBBBB;
  Cio2Config->PortCDDataTrimValue  = 0xCCCC;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadDmiConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_DMI_CONFIG  *DmiConfig;
  DmiConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "DmiConfig->Header.GuidHob.Name = %g\n", &DmiConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "DmiConfig->Header.GuidHob.Header.HobLength = 0x%x\n", DmiConfig->Header.GuidHob.Header.HobLength));

  /********************************
    DMI related settings
  ********************************/
  DmiConfig->DmiAspm = TRUE;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadFlashProtectionConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_FLASH_PROTECTION_CONFIG  *FlashProtectionConfig;
  FlashProtectionConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.GuidHob.Name = %g\n", &FlashProtectionConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.GuidHob.Header.HobLength = 0x%x\n", FlashProtectionConfig->Header.GuidHob.Header.HobLength));
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadHdAudioConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_HDAUDIO_CONFIG  *HdaAudioConfig;
  HdaAudioConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "HdaAudioConfig->Header.GuidHob.Name = %g\n", &HdaAudioConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "HdaAudioConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HdaAudioConfig->Header.GuidHob.Header.HobLength));

  /********************************
    HD-Audio configuration
  ********************************/
  HdaAudioConfig->Enable               = PCH_HDAUDIO_AUTO;
  HdaAudioConfig->DspEnable            = TRUE;
  HdaAudioConfig->HdAudioLinkFrequency = PchHdaLinkFreq24MHz;
  HdaAudioConfig->IDispLinkFrequency   = PchHdaLinkFreq96MHz;
  HdaAudioConfig->ResetWaitTimer       = 600; // Must be at least 521us (25 frames)
  HdaAudioConfig->DspEndpointDmic      = PchHdaDmic4chArray;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadInterruptConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  UINT8                 IntConfigTableEntries;
  PCH_INTERRUPT_CONFIG  *InterruptConfig;
  InterruptConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "InterruptConfig->Header.GuidHob.Name = %g\n", &InterruptConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "InterruptConfig->Header.GuidHob.Header.HobLength = 0x%x\n", InterruptConfig->Header.GuidHob.Header.HobLength));

  /********************************
    Interrupt Configuration
  ********************************/
  IntConfigTableEntries = sizeof (mDevIntConfig) / sizeof (PCH_DEVICE_INTERRUPT_CONFIG);
  ASSERT (IntConfigTableEntries <= PCH_MAX_DEVICE_INTERRUPT_CONFIG);
  InterruptConfig->NumOfDevIntConfig = IntConfigTableEntries;
  CopyMem (
    InterruptConfig->DevIntConfig,
    mDevIntConfig,
    sizeof (mDevIntConfig)
    );
  if (GetPchSeries () == PchLp) {
    CopyMem (
      &(InterruptConfig->DevIntConfig[IntConfigTableEntries]),
      mLpOnlyDevIntConfig,
      sizeof (mLpOnlyDevIntConfig)
      );
    InterruptConfig->NumOfDevIntConfig += (sizeof (mLpOnlyDevIntConfig) / sizeof (PCH_DEVICE_INTERRUPT_CONFIG));
  }

  ASSERT ((sizeof (mPxRcConfig) / sizeof (UINT8)) <= PCH_MAX_PXRC_CONFIG);
  CopyMem (
    InterruptConfig->PxRcConfig,
    mPxRcConfig,
    sizeof (mPxRcConfig)
    );

  InterruptConfig->GpioIrqRoute = 14;
  InterruptConfig->SciIrqSelect = 9;
  InterruptConfig->TcoIrqSelect = 9;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadIshConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_ISH_CONFIG  *IshConfig;
  IshConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "IshConfig->Header.GuidHob.Name = %g\n", &IshConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "IshConfig->Header.GuidHob.Header.HobLength = 0x%x\n", IshConfig->Header.GuidHob.Header.HobLength));

  /********************************
    ISH Configuration
  ********************************/
  IshConfig->Enable            = TRUE;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadLanConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_LAN_CONFIG  *LanConfig;
  LanConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "LanConfig->Header.GuidHob.Name = %g\n", &LanConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "LanConfig->Header.GuidHob.Header.HobLength = 0x%x\n", LanConfig->Header.GuidHob.Header.HobLength));

  /********************************
    Lan configuration
  ********************************/
  LanConfig->Enable               = TRUE;
  LanConfig->LtrEnable            = TRUE;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadLockDownConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_LOCK_DOWN_CONFIG  *LockDownConfig;
  LockDownConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "LockDownConfig->Header.GuidHob.Name = %g\n", &LockDownConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "LockDownConfig->Header.GuidHob.Header.HobLength = 0x%x\n", LockDownConfig->Header.GuidHob.Header.HobLength));

  /********************************
    Lockdown configuration
  ********************************/
  LockDownConfig->GlobalSmi       = TRUE;
  //
  // PCH BIOS Spec Flash Security Recommendations,
  // Intel strongly recommends that BIOS sets the BIOS Interface Lock Down bit. Enabling this bit
  // will mitigate malicious software attempts to replace the system BIOS option ROM with its own code.
  // Here we always enable this as a Policy.
  //
  LockDownConfig->BiosInterface   = TRUE;
  LockDownConfig->RtcLock         = TRUE;

  //
  // Enable BIOS region lock in SPI
  //
  LockDownConfig->BiosLock        = TRUE;
  LockDownConfig->SpiEiss         = TRUE;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadP2sbConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_P2SB_CONFIG  *P2sbConfig;
  P2sbConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "P2sbConfig->Header.GuidHob.Name = %g\n", &P2sbConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "P2sbConfig->Header.GuidHob.Header.HobLength = 0x%x\n", P2sbConfig->Header.GuidHob.Header.HobLength));
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadPmConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_PM_CONFIG  *PmConfig;
  PmConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "PmConfig->Header.GuidHob.Name = %g\n", &PmConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "PmConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PmConfig->Header.GuidHob.Header.HobLength));

  /********************************
    MiscPm Configuration
  ********************************/
  PmConfig->MeWakeSts                            = TRUE;
  PmConfig->WolOvrWkSts                          = TRUE;

  PmConfig->WakeConfig.WolEnableOverride         = TRUE;
  PmConfig->WakeConfig.LanWakeFromDeepSx         = TRUE;

  PmConfig->PchSlpS3MinAssert                    = PchSlpS350ms;
  PmConfig->PchSlpS4MinAssert                    = PchSlpS44s;
  PmConfig->PchSlpSusMinAssert                   = PchSlpSus4s;
  PmConfig->PchSlpAMinAssert                     = PchSlpA2s;

  PmConfig->PmcReadDisable                       = TRUE;
  PmConfig->SlpLanLowDc                          = TRUE;
  PmConfig->LpcClockRun                          = TRUE;
  PmConfig->SlpS0Enable                          = TRUE;
  PmConfig->SlpS0VmEnable                        = TRUE;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadPort61ConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_PORT61H_SMM_CONFIG  *Port61Config;
  Port61Config = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "Port61Config->Header.GuidHob.Name = %g\n", &Port61Config->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "Port61Config->Header.GuidHob.Header.HobLength = 0x%x\n", Port61Config->Header.GuidHob.Header.HobLength));

  /********************************
    Port 61h emulation
  ********************************/
  Port61Config->Enable   = TRUE;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadScsConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_SCS_CONFIG  *ScsConfig;
  ScsConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "ScsConfig->Header.GuidHob.Name = %g\n", &ScsConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "ScsConfig->Header.GuidHob.Header.HobLength = 0x%x\n", ScsConfig->Header.GuidHob.Header.HobLength));

  /********************************
    SCS Configuration
  ********************************/
  ScsConfig->ScsEmmcEnabled             = TRUE;
  ScsConfig->ScsSdSwitch                = PchScsSdcardMode;
  ScsConfig->ScsEmmcHs400DriverStrength = DriverStrength40Ohm;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadSerialIoConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  UINTN                 Index;
  PCH_SERIAL_IO_CONFIG  *SerialIoConfig;
  SerialIoConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "SerialIoConfig->Header.GuidHob.Name = %g\n", &SerialIoConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "SerialIoConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SerialIoConfig->Header.GuidHob.Header.HobLength));

  /********************************
    SerialIo Configuration
  ********************************/
  for (Index = 0; Index < PCH_SERIALIO_MAX_CONTROLLERS; Index++) {
    SerialIoConfig->DevMode[Index]        = PchSerialIoPci;
  }
  SerialIoConfig->Gpio                     = TRUE;
  SerialIoConfig->DebugUartNumber          = PcdGet8 (PcdSerialIoUartNumber);
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadSerialIrqConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_LPC_SIRQ_CONFIG  *SerialIrqConfig;
  SerialIrqConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.GuidHob.Name = %g\n", &SerialIrqConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SerialIrqConfig->Header.GuidHob.Header.HobLength));

  /********************************
    Serial IRQ Configuration
  ********************************/
  SerialIrqConfig->SirqEnable       = TRUE;
  SerialIrqConfig->SirqMode         = PchQuietMode;
  SerialIrqConfig->StartFramePulse  = PchSfpw4Clk;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadSpiConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_SPI_CONFIG  *SpiConfig;
  SpiConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "SpiConfig->Header.GuidHob.Name = %g\n", &SpiConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "SpiConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SpiConfig->Header.GuidHob.Header.HobLength));
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadThermalConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_THERMAL_CONFIG  *ThermalConfig;
  ThermalConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "ThermalConfig->Header.GuidHob.Name = %g\n", &ThermalConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "ThermalConfig->Header.GuidHob.Header.HobLength = 0x%x\n", ThermalConfig->Header.GuidHob.Header.HobLength));

  /********************************
    Thermal configuration.
  ********************************/
  ThermalConfig->ThermalDeviceEnable         = 1;
  ThermalConfig->TsmicLock                   = TRUE;
  ThermalConfig->TTLevels.SuggestedSetting   = TRUE;
  ThermalConfig->TTLevels.PchCrossThrottling = TRUE;
  ThermalConfig->DmiHaAWC.SuggestedSetting   = TRUE;
  ThermalConfig->SataTT.SuggestedSetting     = TRUE;
  ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioC].PmsyncEnable     = TRUE;
  ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioC].C0TransmitEnable = TRUE;
  ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioD].PmsyncEnable     = TRUE;
  ThermalConfig->MemoryThrottling.TsGpioPinSetting[TsGpioD].C0TransmitEnable = TRUE;
}

/**
  Load Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadUsbConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  UINTN           PortIndex;
  PCH_USB_CONFIG  *UsbConfig;
  UsbConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "UsbConfig->Header.GuidHob.Name = %g\n", &UsbConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "UsbConfig->Header.GuidHob.Header.HobLength = 0x%x\n", UsbConfig->Header.GuidHob.Header.HobLength));

  /********************************
    USB related configuration
  ********************************/
  for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb2PortNum (); PortIndex++) {
    UsbConfig->PortUsb20[PortIndex].Enable  = TRUE;
  }

  for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb3PortNum (); PortIndex++) {
    UsbConfig->PortUsb30[PortIndex].Enable  = TRUE;
  }
  //
  // USB Port Over Current Pins mapping, please set as per board layout.
  // Default is PchUsbOverCurrentPin0(0)
  //
  UsbConfig->PortUsb20[ 2].OverCurrentPin = PchUsbOverCurrentPin1;
  UsbConfig->PortUsb20[ 3].OverCurrentPin = PchUsbOverCurrentPin1;
  UsbConfig->PortUsb20[ 4].OverCurrentPin = PchUsbOverCurrentPin2;
  UsbConfig->PortUsb20[ 5].OverCurrentPin = PchUsbOverCurrentPin2;
  UsbConfig->PortUsb20[ 6].OverCurrentPin = PchUsbOverCurrentPin3;
  UsbConfig->PortUsb20[ 7].OverCurrentPin = PchUsbOverCurrentPin3;
  UsbConfig->PortUsb20[ 8].OverCurrentPin = PchUsbOverCurrentPin4;
  UsbConfig->PortUsb20[ 9].OverCurrentPin = PchUsbOverCurrentPin4;
  UsbConfig->PortUsb20[10].OverCurrentPin = PchUsbOverCurrentPin5;
  UsbConfig->PortUsb20[11].OverCurrentPin = PchUsbOverCurrentPin5;
  UsbConfig->PortUsb20[12].OverCurrentPin = PchUsbOverCurrentPin6;
  UsbConfig->PortUsb20[13].OverCurrentPin = PchUsbOverCurrentPin6;

  UsbConfig->PortUsb30[2].OverCurrentPin  = PchUsbOverCurrentPin1;
  UsbConfig->PortUsb30[3].OverCurrentPin  = PchUsbOverCurrentPin1;
  UsbConfig->PortUsb30[4].OverCurrentPin  = PchUsbOverCurrentPin2;
  UsbConfig->PortUsb30[5].OverCurrentPin  = PchUsbOverCurrentPin2;

  //
  // Default values of USB2 AFE settings.
  //
  for (PortIndex = 0; PortIndex < PCH_H_XHCI_MAX_USB2_PORTS; PortIndex++) {
    UsbConfig->PortUsb20[PortIndex].Afe.Petxiset  = 3;
    UsbConfig->PortUsb20[PortIndex].Afe.Txiset    = 2;
    UsbConfig->PortUsb20[PortIndex].Afe.Predeemp  = 1;
    UsbConfig->PortUsb20[PortIndex].Afe.Pehalfbit = 1;
  }

  //
  // Enable/Disable SSIC support in the setup menu
  //
  for (PortIndex = 0; PortIndex < PCH_XHCI_MAX_SSIC_PORT_COUNT; PortIndex++) {
    UsbConfig->SsicConfig.SsicPort[PortIndex].Enable   = FALSE;
  }

  //
  // xDCI configuration
  //
  UsbConfig->XdciConfig.Enable = FALSE;
}

/**
  Load Espi Config block default

  @param[in] ConfigBlockPointer         Pointer to config block
**/
VOID
LoadEspiConfigDefault (
  IN VOID          *ConfigBlockPointer
  )
{
  PCH_ESPI_CONFIG  *EspiConfig;
  EspiConfig = ConfigBlockPointer;

  DEBUG ((DEBUG_INFO, "EspiConfig->Header.GuidHob.Name = %g\n", &EspiConfig->Header.GuidHob.Name));
  DEBUG ((DEBUG_INFO, "EspiConfig->Header.GuidHob.Header.HobLength = 0x%x\n", EspiConfig->Header.GuidHob.Header.HobLength));

  /********************************
    Espi configuration.
  ********************************/
  EspiConfig->BmeMasterSlaveEnabled = TRUE;
}

static COMPONENT_BLOCK_ENTRY  mPchIpBlocks [] = {
  {&gPchGeneralConfigGuid,       sizeof (PCH_GENERAL_CONFIG),           PCH_GENERAL_CONFIG_REVISION,       LoadPchGeneralConfigDefault},
  {&gPcieRpConfigGuid,           sizeof (PCH_PCIE_CONFIG),              PCIE_RP_CONFIG_REVISION,           LoadPcieRpConfigDefault},
  {&gSataConfigGuid,             sizeof (PCH_SATA_CONFIG),              SATA_CONFIG_REVISION,              LoadSataConfigDefault},
  {&gIoApicConfigGuid,           sizeof (PCH_IOAPIC_CONFIG),            IOAPIC_CONFIG_REVISION,            LoadIoApicConfigDefault},
  {&gCio2ConfigGuid,             sizeof (PCH_CIO2_CONFIG),              CIO2_CONFIG_REVISION,              LoadCio2ConfigDefault},
  {&gDmiConfigGuid,              sizeof (PCH_DMI_CONFIG),               DMI_CONFIG_REVISION,               LoadDmiConfigDefault},
  {&gFlashProtectionConfigGuid,  sizeof (PCH_FLASH_PROTECTION_CONFIG),  FLASH_PROTECTION_CONFIG_REVISION,  LoadFlashProtectionConfigDefault},
  {&gHdAudioConfigGuid,          sizeof (PCH_HDAUDIO_CONFIG),           HDAUDIO_CONFIG_REVISION,           LoadHdAudioConfigDefault},
  {&gInterruptConfigGuid,        sizeof (PCH_INTERRUPT_CONFIG),         INTERRUPT_CONFIG_REVISION,         LoadInterruptConfigDefault},
  {&gIshConfigGuid,              sizeof (PCH_ISH_CONFIG),               ISH_CONFIG_REVISION,               LoadIshConfigDefault},
  {&gLanConfigGuid,              sizeof (PCH_LAN_CONFIG),               LAN_CONFIG_REVISION,               LoadLanConfigDefault},
  {&gLockDownConfigGuid,         sizeof (PCH_LOCK_DOWN_CONFIG),         LOCK_DOWN_CONFIG_REVISION,         LoadLockDownConfigDefault},
  {&gP2sbConfigGuid,             sizeof (PCH_P2SB_CONFIG),              P2SB_CONFIG_REVISION,              LoadP2sbConfigDefault},
  {&gPmConfigGuid,               sizeof (PCH_PM_CONFIG),                PM_CONFIG_REVISION,                LoadPmConfigDefault},
  {&gPort61ConfigGuid,           sizeof (PCH_PORT61H_SMM_CONFIG),       PORT_61_CONFIG_REVISION,           LoadPort61ConfigDefault},
  {&gScsConfigGuid,              sizeof (PCH_SCS_CONFIG),               SCS_CONFIG_REVISION,               LoadScsConfigDefault},
  {&gSerialIoConfigGuid,         sizeof (PCH_SERIAL_IO_CONFIG),         SERIAL_IO_CONFIG_REVISION,         LoadSerialIoConfigDefault},
  {&gSerialIrqConfigGuid,        sizeof (PCH_LPC_SIRQ_CONFIG),          SERIAL_IRQ_CONFIG_REVISION,        LoadSerialIrqConfigDefault},
  {&gSpiConfigGuid,              sizeof (PCH_SPI_CONFIG),               SPI_CONFIG_REVISION,               LoadSpiConfigDefault},
  {&gThermalConfigGuid,          sizeof (PCH_THERMAL_CONFIG),           THERMAL_CONFIG_REVISION,           LoadThermalConfigDefault},
  {&gUsbConfigGuid,              sizeof (PCH_USB_CONFIG),               USB_CONFIG_REVISION,               LoadUsbConfigDefault},
  {&gEspiConfigGuid,             sizeof (PCH_ESPI_CONFIG),              ESPI_CONFIG_REVISION,              LoadEspiConfigDefault}


};

/**
  Get PCH config block table total size.

  @retval                               Size of PCH config block table
**/
UINT16
EFIAPI
PchGetConfigBlockTotalSize (
  VOID
  )
{
  return GetComponentConfigBlockTotalSize (&mPchIpBlocks[0], sizeof (mPchIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
}

/**
  PchAddConfigBlocks add all PCH config blocks.

  @param[in] ConfigBlockTableAddress    The pointer to add PCH config blocks

  @retval EFI_SUCCESS                   The policy default is initialized.
  @retval EFI_OUT_OF_RESOURCES          Insufficient resources to create buffer
**/
EFI_STATUS
EFIAPI
PchAddConfigBlocks (
  IN     VOID      *ConfigBlockTableAddress
  )
{
  DEBUG ((DEBUG_INFO, "PCH AddConfigBlocks\n"));

  return AddComponentConfigBlocks (ConfigBlockTableAddress, &mPchIpBlocks[0], sizeof (mPchIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
}
