summaryrefslogtreecommitdiff
path: root/Silicon/Intel/KabylakeSiliconPkg/Pch
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/Intel/KabylakeSiliconPkg/Pch')
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioAcpiDefines.h791
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLib.asl849
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLibObjects.asl230
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/IrqLink.asl616
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/Pch.asl1156
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchAcpiTables.inf40
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHda.asl213
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHeci.asl43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchIsh.asl42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchNvs.asl240
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchPcie.asl214
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchRstPcieStorage.asl186
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSata.asl154
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchScs.asl247
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSerialIo.asl749
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXdci.asl310
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXhci.asl558
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/TraceHubDebug.asl144
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/usbsbd.asl70
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Cio2Config.h72
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DciConfig.h53
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DmiConfig.h53
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/EspiConfig.h41
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HdAudioConfig.h180
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HpetConfig.h47
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h45
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h76
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h71
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/InterruptConfig.h63
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IoApicConfig.h61
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IshConfig.h48
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LanConfig.h44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h67
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h39
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/P2sbConfig.h50
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h60
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PcieRpConfig.h435
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PmConfig.h215
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Port61Config.h34
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SataConfig.h193
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ScsConfig.h61
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIoConfig.h56
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIrqConfig.h48
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SmbusConfig.h56
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SpiConfig.h38
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ThermalConfig.h176
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/TraceHubConfig.h35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/UsbConfig.h233
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/WatchDogConfig.h38
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioConfig.h338
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklH.h248
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklLp.h207
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioLib.h707
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioNativeLib.h225
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/OcWdtLib.h37
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h345
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchEspiLib.h102
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchGbeLib.h64
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchHsioLib.h114
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchInfoLib.h260
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchP2sbLib.h160
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcieRpLib.h110
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcrLib.h196
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPmcLib.h50
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPolicyLib.h113
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPsfLib.h170
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchResetLib.h30
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSbiAccessLib.h162
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoLib.h219
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoUartLib.h98
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSmmControlLib.h28
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchWdtCommonLib.h113
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SecPchLib.h27
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SpiFlashCommonLib.h104
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/TraceHubInitLib.h49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchAccess.h71
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchLimits.h101
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPcieStorageDetectHob.h54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPolicyCommon.h54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h65
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchReservedResources.h62
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h28
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/PchReset.h98
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Spi.h32
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Wdt.h33
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h141
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEmmcTuning.h74
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h151
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchGpioUnlockSmiDispatch.h115
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchInfo.h57
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h137
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchReset.h121
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h139
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h72
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h72
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h157
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/SerialGpio.h126
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Spi.h299
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Wdt.h118
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsCam.h151
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDci.h50
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDmi.h214
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsFia.h123
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsGpio.h529
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHda.h201
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHsio.h185
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsIsh.h74
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsItss.h94
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLan.h148
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h610
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsP2sb.h138
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcie.h524
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcr.h111
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPmc.h652
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h364
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h72
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSata.h720
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsScs.h202
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSerialIo.h325
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSmbus.h149
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSpi.h309
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsThermal.h107
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsTraceHub.h140
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsUsb.h490
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/DxePchHdaNhlt.h128
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/GpioPrivateLib.h212
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/I2cMasterCommonLib.h290
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchHdaLib.h62
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchInitCommonLib.h191
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPciExpressHelpersLib.h284
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPsfPrivateLib.h401
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSmbusCommonLib.h166
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSpiCommonLib.h401
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PeiI2cMasterLib.h49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/RstPrivateLib.h91
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h298
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchHdaEndpoints.h129
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvs.h33
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h243
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c161
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf46
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.c996
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.inf46
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.c325
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.inf56
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.c367
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf58
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c505
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c2691
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h327
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.c685
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PchSklGpioData.c190
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf51
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c1137
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c146
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c928
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c514
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c334
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c338
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c268
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c458
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c136
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PchPsfLib.c448
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PeiDxeSmmPchPsfLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c385
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c527
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf45
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c225
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c138
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf43
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.c41
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.inf32
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPrintPolicy.c311
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy.c783
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePolicyLib.c223
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePreMemPolicyLib.c80
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c892
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf93
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h32
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c306
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c194
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLib.inf48
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c286
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf54
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLibFsp.inf58
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf59
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c202
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c60
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c1058
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf51
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c318
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c842
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c336
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c545
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c305
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c318
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c200
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c519
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c127
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c1933
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h45
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf52
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c1169
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf47
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c652
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c216
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c465
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchCio2Acpi.c57
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c247
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c504
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h320
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c699
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.inf101
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFsp.inf80
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c169
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchRstPcieStorage.c286
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c125
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchScs.c1869
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c112
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c130
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchGpioSxIsolationSmm.c48
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c308
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h344
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf107
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c415
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c464
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPort61hSmm.c160
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c74
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchXhciSxSmm.c73
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c913
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h193
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c2497
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf113
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h949
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c952
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c1385
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h337
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c333
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h162
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c702
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c96
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c169
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c235
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c232
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c790
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h114
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf61
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c400
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h148
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.c254
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.h30
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf54
272 files changed, 70100 insertions, 0 deletions
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioAcpiDefines.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioAcpiDefines.h
new file mode 100644
index 0000000000..9cde7e862d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioAcpiDefines.h
@@ -0,0 +1,791 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+
+//
+// Definition for GPIO groups and pads
+//
+#ifndef GPIO_DEFINE_ASL
+#define GPIO_DEFINE_ASL
+
+#include "GpioPinsSklLp.h"
+#include "GpioPinsSklH.h"
+#include "Register/PchRegsGpio.h"
+
+//
+// SKL-PCH GPIO Community address
+//
+#define PCH_GPIO_COM0 0x00af0000 // PID_GPIOCOM0 = 0xAF
+#define PCH_GPIO_COM1 0x00ae0000 // PID_GPIOCOM1 = 0xAE
+#define PCH_GPIO_COM2 0x00ad0000 // PID_GPIOCOM2 = 0xAD
+#define PCH_GPIO_COM3 0x00ac0000 // PID_GPIOCOM3 = 0xAC
+
+//
+// SKL-PCH-LP GPIO pin list for driver usage
+//
+#define GPIO_SKL_LP_DRIVER_GPP_A_00 0
+#define GPIO_SKL_LP_DRIVER_GPP_A_01 1
+#define GPIO_SKL_LP_DRIVER_GPP_A_02 2
+#define GPIO_SKL_LP_DRIVER_GPP_A_03 3
+#define GPIO_SKL_LP_DRIVER_GPP_A_04 4
+#define GPIO_SKL_LP_DRIVER_GPP_A_05 5
+#define GPIO_SKL_LP_DRIVER_GPP_A_06 6
+#define GPIO_SKL_LP_DRIVER_GPP_A_07 7
+#define GPIO_SKL_LP_DRIVER_GPP_A_08 8
+#define GPIO_SKL_LP_DRIVER_GPP_A_09 9
+#define GPIO_SKL_LP_DRIVER_GPP_A_10 10
+#define GPIO_SKL_LP_DRIVER_GPP_A_11 11
+#define GPIO_SKL_LP_DRIVER_GPP_A_12 12
+#define GPIO_SKL_LP_DRIVER_GPP_A_13 13
+#define GPIO_SKL_LP_DRIVER_GPP_A_14 14
+#define GPIO_SKL_LP_DRIVER_GPP_A_15 15
+#define GPIO_SKL_LP_DRIVER_GPP_A_16 16
+#define GPIO_SKL_LP_DRIVER_GPP_A_17 17
+#define GPIO_SKL_LP_DRIVER_GPP_A_18 18
+#define GPIO_SKL_LP_DRIVER_GPP_A_19 19
+#define GPIO_SKL_LP_DRIVER_GPP_A_20 20
+#define GPIO_SKL_LP_DRIVER_GPP_A_21 21
+#define GPIO_SKL_LP_DRIVER_GPP_A_22 22
+#define GPIO_SKL_LP_DRIVER_GPP_A_23 23
+
+#define GPIO_SKL_LP_DRIVER_GPP_B_00 24
+#define GPIO_SKL_LP_DRIVER_GPP_B_01 25
+#define GPIO_SKL_LP_DRIVER_GPP_B_02 26
+#define GPIO_SKL_LP_DRIVER_GPP_B_03 27
+#define GPIO_SKL_LP_DRIVER_GPP_B_04 28
+#define GPIO_SKL_LP_DRIVER_GPP_B_05 29
+#define GPIO_SKL_LP_DRIVER_GPP_B_06 30
+#define GPIO_SKL_LP_DRIVER_GPP_B_07 31
+#define GPIO_SKL_LP_DRIVER_GPP_B_08 32
+#define GPIO_SKL_LP_DRIVER_GPP_B_09 33
+#define GPIO_SKL_LP_DRIVER_GPP_B_10 34
+#define GPIO_SKL_LP_DRIVER_GPP_B_11 35
+#define GPIO_SKL_LP_DRIVER_GPP_B_12 36
+#define GPIO_SKL_LP_DRIVER_GPP_B_13 37
+#define GPIO_SKL_LP_DRIVER_GPP_B_14 38
+#define GPIO_SKL_LP_DRIVER_GPP_B_15 39
+#define GPIO_SKL_LP_DRIVER_GPP_B_16 40
+#define GPIO_SKL_LP_DRIVER_GPP_B_17 41
+#define GPIO_SKL_LP_DRIVER_GPP_B_18 42
+#define GPIO_SKL_LP_DRIVER_GPP_B_19 43
+#define GPIO_SKL_LP_DRIVER_GPP_B_20 44
+#define GPIO_SKL_LP_DRIVER_GPP_B_21 45
+#define GPIO_SKL_LP_DRIVER_GPP_B_22 46
+#define GPIO_SKL_LP_DRIVER_GPP_B_23 47
+
+#define GPIO_SKL_LP_DRIVER_GPP_C_00 48
+#define GPIO_SKL_LP_DRIVER_GPP_C_01 49
+#define GPIO_SKL_LP_DRIVER_GPP_C_02 50
+#define GPIO_SKL_LP_DRIVER_GPP_C_03 51
+#define GPIO_SKL_LP_DRIVER_GPP_C_04 52
+#define GPIO_SKL_LP_DRIVER_GPP_C_05 53
+#define GPIO_SKL_LP_DRIVER_GPP_C_06 54
+#define GPIO_SKL_LP_DRIVER_GPP_C_07 55
+#define GPIO_SKL_LP_DRIVER_GPP_C_08 56
+#define GPIO_SKL_LP_DRIVER_GPP_C_09 57
+#define GPIO_SKL_LP_DRIVER_GPP_C_10 58
+#define GPIO_SKL_LP_DRIVER_GPP_C_11 59
+#define GPIO_SKL_LP_DRIVER_GPP_C_12 60
+#define GPIO_SKL_LP_DRIVER_GPP_C_13 61
+#define GPIO_SKL_LP_DRIVER_GPP_C_14 62
+#define GPIO_SKL_LP_DRIVER_GPP_C_15 63
+#define GPIO_SKL_LP_DRIVER_GPP_C_16 64
+#define GPIO_SKL_LP_DRIVER_GPP_C_17 65
+#define GPIO_SKL_LP_DRIVER_GPP_C_18 66
+#define GPIO_SKL_LP_DRIVER_GPP_C_19 67
+#define GPIO_SKL_LP_DRIVER_GPP_C_20 68
+#define GPIO_SKL_LP_DRIVER_GPP_C_21 69
+#define GPIO_SKL_LP_DRIVER_GPP_C_22 70
+#define GPIO_SKL_LP_DRIVER_GPP_C_23 71
+
+#define GPIO_SKL_LP_DRIVER_GPP_D_00 72
+#define GPIO_SKL_LP_DRIVER_GPP_D_01 73
+#define GPIO_SKL_LP_DRIVER_GPP_D_02 74
+#define GPIO_SKL_LP_DRIVER_GPP_D_03 75
+#define GPIO_SKL_LP_DRIVER_GPP_D_04 76
+#define GPIO_SKL_LP_DRIVER_GPP_D_05 77
+#define GPIO_SKL_LP_DRIVER_GPP_D_06 78
+#define GPIO_SKL_LP_DRIVER_GPP_D_07 79
+#define GPIO_SKL_LP_DRIVER_GPP_D_08 80
+#define GPIO_SKL_LP_DRIVER_GPP_D_09 81
+#define GPIO_SKL_LP_DRIVER_GPP_D_10 82
+#define GPIO_SKL_LP_DRIVER_GPP_D_11 83
+#define GPIO_SKL_LP_DRIVER_GPP_D_12 84
+#define GPIO_SKL_LP_DRIVER_GPP_D_13 85
+#define GPIO_SKL_LP_DRIVER_GPP_D_14 86
+#define GPIO_SKL_LP_DRIVER_GPP_D_15 87
+#define GPIO_SKL_LP_DRIVER_GPP_D_16 88
+#define GPIO_SKL_LP_DRIVER_GPP_D_17 89
+#define GPIO_SKL_LP_DRIVER_GPP_D_18 90
+#define GPIO_SKL_LP_DRIVER_GPP_D_19 91
+#define GPIO_SKL_LP_DRIVER_GPP_D_20 92
+#define GPIO_SKL_LP_DRIVER_GPP_D_21 93
+#define GPIO_SKL_LP_DRIVER_GPP_D_22 94
+#define GPIO_SKL_LP_DRIVER_GPP_D_23 95
+
+#define GPIO_SKL_LP_DRIVER_GPP_E_00 96
+#define GPIO_SKL_LP_DRIVER_GPP_E_01 97
+#define GPIO_SKL_LP_DRIVER_GPP_E_02 98
+#define GPIO_SKL_LP_DRIVER_GPP_E_03 99
+#define GPIO_SKL_LP_DRIVER_GPP_E_04 100
+#define GPIO_SKL_LP_DRIVER_GPP_E_05 101
+#define GPIO_SKL_LP_DRIVER_GPP_E_06 102
+#define GPIO_SKL_LP_DRIVER_GPP_E_07 103
+#define GPIO_SKL_LP_DRIVER_GPP_E_08 104
+#define GPIO_SKL_LP_DRIVER_GPP_E_09 105
+#define GPIO_SKL_LP_DRIVER_GPP_E_10 106
+#define GPIO_SKL_LP_DRIVER_GPP_E_11 107
+#define GPIO_SKL_LP_DRIVER_GPP_E_12 108
+#define GPIO_SKL_LP_DRIVER_GPP_E_13 109
+#define GPIO_SKL_LP_DRIVER_GPP_E_14 110
+#define GPIO_SKL_LP_DRIVER_GPP_E_15 111
+#define GPIO_SKL_LP_DRIVER_GPP_E_16 112
+#define GPIO_SKL_LP_DRIVER_GPP_E_17 113
+#define GPIO_SKL_LP_DRIVER_GPP_E_18 114
+#define GPIO_SKL_LP_DRIVER_GPP_E_19 115
+#define GPIO_SKL_LP_DRIVER_GPP_E_20 116
+#define GPIO_SKL_LP_DRIVER_GPP_E_21 117
+#define GPIO_SKL_LP_DRIVER_GPP_E_22 118
+#define GPIO_SKL_LP_DRIVER_GPP_E_23 119
+
+#define GPIO_SKL_LP_DRIVER_GPP_F_00 120
+#define GPIO_SKL_LP_DRIVER_GPP_F_01 121
+#define GPIO_SKL_LP_DRIVER_GPP_F_02 122
+#define GPIO_SKL_LP_DRIVER_GPP_F_03 123
+#define GPIO_SKL_LP_DRIVER_GPP_F_04 124
+#define GPIO_SKL_LP_DRIVER_GPP_F_05 125
+#define GPIO_SKL_LP_DRIVER_GPP_F_06 126
+#define GPIO_SKL_LP_DRIVER_GPP_F_07 127
+#define GPIO_SKL_LP_DRIVER_GPP_F_08 128
+#define GPIO_SKL_LP_DRIVER_GPP_F_09 129
+#define GPIO_SKL_LP_DRIVER_GPP_F_10 130
+#define GPIO_SKL_LP_DRIVER_GPP_F_11 131
+#define GPIO_SKL_LP_DRIVER_GPP_F_12 132
+#define GPIO_SKL_LP_DRIVER_GPP_F_13 133
+#define GPIO_SKL_LP_DRIVER_GPP_F_14 134
+#define GPIO_SKL_LP_DRIVER_GPP_F_15 135
+#define GPIO_SKL_LP_DRIVER_GPP_F_16 136
+#define GPIO_SKL_LP_DRIVER_GPP_F_17 137
+#define GPIO_SKL_LP_DRIVER_GPP_F_18 138
+#define GPIO_SKL_LP_DRIVER_GPP_F_19 139
+#define GPIO_SKL_LP_DRIVER_GPP_F_20 140
+#define GPIO_SKL_LP_DRIVER_GPP_F_21 141
+#define GPIO_SKL_LP_DRIVER_GPP_F_22 142
+#define GPIO_SKL_LP_DRIVER_GPP_F_23 143
+
+#define GPIO_SKL_LP_DRIVER_GPP_G_00 144
+#define GPIO_SKL_LP_DRIVER_GPP_G_01 145
+#define GPIO_SKL_LP_DRIVER_GPP_G_02 146
+#define GPIO_SKL_LP_DRIVER_GPP_G_03 147
+#define GPIO_SKL_LP_DRIVER_GPP_G_04 148
+#define GPIO_SKL_LP_DRIVER_GPP_G_05 149
+#define GPIO_SKL_LP_DRIVER_GPP_G_06 150
+#define GPIO_SKL_LP_DRIVER_GPP_G_07 151
+
+//
+// SPT H GPIO pin list for driver usage
+//
+#define GPIO_SKL_H_DRIVER_GPP_A_00 0
+#define GPIO_SKL_H_DRIVER_GPP_A_01 1
+#define GPIO_SKL_H_DRIVER_GPP_A_02 2
+#define GPIO_SKL_H_DRIVER_GPP_A_03 3
+#define GPIO_SKL_H_DRIVER_GPP_A_04 4
+#define GPIO_SKL_H_DRIVER_GPP_A_05 5
+#define GPIO_SKL_H_DRIVER_GPP_A_06 6
+#define GPIO_SKL_H_DRIVER_GPP_A_07 7
+#define GPIO_SKL_H_DRIVER_GPP_A_08 8
+#define GPIO_SKL_H_DRIVER_GPP_A_09 9
+#define GPIO_SKL_H_DRIVER_GPP_A_10 10
+#define GPIO_SKL_H_DRIVER_GPP_A_11 11
+#define GPIO_SKL_H_DRIVER_GPP_A_12 12
+#define GPIO_SKL_H_DRIVER_GPP_A_13 13
+#define GPIO_SKL_H_DRIVER_GPP_A_14 14
+#define GPIO_SKL_H_DRIVER_GPP_A_15 15
+#define GPIO_SKL_H_DRIVER_GPP_A_16 16
+#define GPIO_SKL_H_DRIVER_GPP_A_17 17
+#define GPIO_SKL_H_DRIVER_GPP_A_18 18
+#define GPIO_SKL_H_DRIVER_GPP_A_19 19
+#define GPIO_SKL_H_DRIVER_GPP_A_20 20
+#define GPIO_SKL_H_DRIVER_GPP_A_21 21
+#define GPIO_SKL_H_DRIVER_GPP_A_22 22
+#define GPIO_SKL_H_DRIVER_GPP_A_23 23
+
+#define GPIO_SKL_H_DRIVER_GPP_B_00 24
+#define GPIO_SKL_H_DRIVER_GPP_B_01 25
+#define GPIO_SKL_H_DRIVER_GPP_B_02 26
+#define GPIO_SKL_H_DRIVER_GPP_B_03 27
+#define GPIO_SKL_H_DRIVER_GPP_B_04 28
+#define GPIO_SKL_H_DRIVER_GPP_B_05 29
+#define GPIO_SKL_H_DRIVER_GPP_B_06 30
+#define GPIO_SKL_H_DRIVER_GPP_B_07 31
+#define GPIO_SKL_H_DRIVER_GPP_B_08 32
+#define GPIO_SKL_H_DRIVER_GPP_B_09 33
+#define GPIO_SKL_H_DRIVER_GPP_B_10 34
+#define GPIO_SKL_H_DRIVER_GPP_B_11 35
+#define GPIO_SKL_H_DRIVER_GPP_B_12 36
+#define GPIO_SKL_H_DRIVER_GPP_B_13 37
+#define GPIO_SKL_H_DRIVER_GPP_B_14 38
+#define GPIO_SKL_H_DRIVER_GPP_B_15 39
+#define GPIO_SKL_H_DRIVER_GPP_B_16 40
+#define GPIO_SKL_H_DRIVER_GPP_B_17 41
+#define GPIO_SKL_H_DRIVER_GPP_B_18 42
+#define GPIO_SKL_H_DRIVER_GPP_B_19 43
+#define GPIO_SKL_H_DRIVER_GPP_B_20 44
+#define GPIO_SKL_H_DRIVER_GPP_B_21 45
+#define GPIO_SKL_H_DRIVER_GPP_B_22 46
+#define GPIO_SKL_H_DRIVER_GPP_B_23 47
+
+#define GPIO_SKL_H_DRIVER_GPP_C_00 48
+#define GPIO_SKL_H_DRIVER_GPP_C_01 49
+#define GPIO_SKL_H_DRIVER_GPP_C_02 50
+#define GPIO_SKL_H_DRIVER_GPP_C_03 51
+#define GPIO_SKL_H_DRIVER_GPP_C_04 52
+#define GPIO_SKL_H_DRIVER_GPP_C_05 53
+#define GPIO_SKL_H_DRIVER_GPP_C_06 54
+#define GPIO_SKL_H_DRIVER_GPP_C_07 55
+#define GPIO_SKL_H_DRIVER_GPP_C_08 56
+#define GPIO_SKL_H_DRIVER_GPP_C_09 57
+#define GPIO_SKL_H_DRIVER_GPP_C_10 58
+#define GPIO_SKL_H_DRIVER_GPP_C_11 59
+#define GPIO_SKL_H_DRIVER_GPP_C_12 60
+#define GPIO_SKL_H_DRIVER_GPP_C_13 61
+#define GPIO_SKL_H_DRIVER_GPP_C_14 62
+#define GPIO_SKL_H_DRIVER_GPP_C_15 63
+#define GPIO_SKL_H_DRIVER_GPP_C_16 64
+#define GPIO_SKL_H_DRIVER_GPP_C_17 65
+#define GPIO_SKL_H_DRIVER_GPP_C_18 66
+#define GPIO_SKL_H_DRIVER_GPP_C_19 67
+#define GPIO_SKL_H_DRIVER_GPP_C_20 68
+#define GPIO_SKL_H_DRIVER_GPP_C_21 69
+#define GPIO_SKL_H_DRIVER_GPP_C_22 70
+#define GPIO_SKL_H_DRIVER_GPP_C_23 71
+
+#define GPIO_SKL_H_DRIVER_GPP_D_00 72
+#define GPIO_SKL_H_DRIVER_GPP_D_01 73
+#define GPIO_SKL_H_DRIVER_GPP_D_02 74
+#define GPIO_SKL_H_DRIVER_GPP_D_03 75
+#define GPIO_SKL_H_DRIVER_GPP_D_04 76
+#define GPIO_SKL_H_DRIVER_GPP_D_05 77
+#define GPIO_SKL_H_DRIVER_GPP_D_06 78
+#define GPIO_SKL_H_DRIVER_GPP_D_07 79
+#define GPIO_SKL_H_DRIVER_GPP_D_08 80
+#define GPIO_SKL_H_DRIVER_GPP_D_09 81
+#define GPIO_SKL_H_DRIVER_GPP_D_10 82
+#define GPIO_SKL_H_DRIVER_GPP_D_11 83
+#define GPIO_SKL_H_DRIVER_GPP_D_12 84
+#define GPIO_SKL_H_DRIVER_GPP_D_13 85
+#define GPIO_SKL_H_DRIVER_GPP_D_14 86
+#define GPIO_SKL_H_DRIVER_GPP_D_15 87
+#define GPIO_SKL_H_DRIVER_GPP_D_16 88
+#define GPIO_SKL_H_DRIVER_GPP_D_17 89
+#define GPIO_SKL_H_DRIVER_GPP_D_18 90
+#define GPIO_SKL_H_DRIVER_GPP_D_19 91
+#define GPIO_SKL_H_DRIVER_GPP_D_20 92
+#define GPIO_SKL_H_DRIVER_GPP_D_21 93
+#define GPIO_SKL_H_DRIVER_GPP_D_22 94
+#define GPIO_SKL_H_DRIVER_GPP_D_23 95
+
+#define GPIO_SKL_H_DRIVER_GPP_E_00 96
+#define GPIO_SKL_H_DRIVER_GPP_E_01 97
+#define GPIO_SKL_H_DRIVER_GPP_E_02 98
+#define GPIO_SKL_H_DRIVER_GPP_E_03 99
+#define GPIO_SKL_H_DRIVER_GPP_E_04 100
+#define GPIO_SKL_H_DRIVER_GPP_E_05 101
+#define GPIO_SKL_H_DRIVER_GPP_E_06 102
+#define GPIO_SKL_H_DRIVER_GPP_E_07 103
+#define GPIO_SKL_H_DRIVER_GPP_E_08 104
+#define GPIO_SKL_H_DRIVER_GPP_E_09 105
+#define GPIO_SKL_H_DRIVER_GPP_E_10 106
+#define GPIO_SKL_H_DRIVER_GPP_E_11 107
+#define GPIO_SKL_H_DRIVER_GPP_E_12 108
+#define GPIO_SKL_H_DRIVER_GPP_E_13 109
+
+#define GPIO_SKL_H_DRIVER_GPP_F_00 120
+#define GPIO_SKL_H_DRIVER_GPP_F_01 121
+#define GPIO_SKL_H_DRIVER_GPP_F_02 122
+#define GPIO_SKL_H_DRIVER_GPP_F_03 123
+#define GPIO_SKL_H_DRIVER_GPP_F_04 124
+#define GPIO_SKL_H_DRIVER_GPP_F_05 125
+#define GPIO_SKL_H_DRIVER_GPP_F_06 126
+#define GPIO_SKL_H_DRIVER_GPP_F_07 127
+#define GPIO_SKL_H_DRIVER_GPP_F_08 128
+#define GPIO_SKL_H_DRIVER_GPP_F_09 129
+#define GPIO_SKL_H_DRIVER_GPP_F_10 130
+#define GPIO_SKL_H_DRIVER_GPP_F_11 131
+#define GPIO_SKL_H_DRIVER_GPP_F_12 132
+#define GPIO_SKL_H_DRIVER_GPP_F_13 133
+#define GPIO_SKL_H_DRIVER_GPP_F_14 134
+#define GPIO_SKL_H_DRIVER_GPP_F_15 135
+#define GPIO_SKL_H_DRIVER_GPP_F_16 136
+#define GPIO_SKL_H_DRIVER_GPP_F_17 137
+#define GPIO_SKL_H_DRIVER_GPP_F_18 138
+#define GPIO_SKL_H_DRIVER_GPP_F_19 139
+#define GPIO_SKL_H_DRIVER_GPP_F_20 140
+#define GPIO_SKL_H_DRIVER_GPP_F_21 141
+#define GPIO_SKL_H_DRIVER_GPP_F_22 142
+#define GPIO_SKL_H_DRIVER_GPP_F_23 143
+
+#define GPIO_SKL_H_DRIVER_GPP_G_00 144
+#define GPIO_SKL_H_DRIVER_GPP_G_01 145
+#define GPIO_SKL_H_DRIVER_GPP_G_02 146
+#define GPIO_SKL_H_DRIVER_GPP_G_03 147
+#define GPIO_SKL_H_DRIVER_GPP_G_04 148
+#define GPIO_SKL_H_DRIVER_GPP_G_05 149
+#define GPIO_SKL_H_DRIVER_GPP_G_06 150
+#define GPIO_SKL_H_DRIVER_GPP_G_07 151
+#define GPIO_SKL_H_DRIVER_GPP_G_08 152
+#define GPIO_SKL_H_DRIVER_GPP_G_09 153
+#define GPIO_SKL_H_DRIVER_GPP_G_10 154
+#define GPIO_SKL_H_DRIVER_GPP_G_11 155
+#define GPIO_SKL_H_DRIVER_GPP_G_12 156
+#define GPIO_SKL_H_DRIVER_GPP_G_13 157
+#define GPIO_SKL_H_DRIVER_GPP_G_14 158
+#define GPIO_SKL_H_DRIVER_GPP_G_15 159
+#define GPIO_SKL_H_DRIVER_GPP_G_16 160
+#define GPIO_SKL_H_DRIVER_GPP_G_17 161
+#define GPIO_SKL_H_DRIVER_GPP_G_18 162
+#define GPIO_SKL_H_DRIVER_GPP_G_19 163
+#define GPIO_SKL_H_DRIVER_GPP_G_20 164
+#define GPIO_SKL_H_DRIVER_GPP_G_21 165
+#define GPIO_SKL_H_DRIVER_GPP_G_22 166
+#define GPIO_SKL_H_DRIVER_GPP_G_23 167
+
+#define GPIO_SKL_H_DRIVER_GPP_H_00 168
+#define GPIO_SKL_H_DRIVER_GPP_H_01 169
+#define GPIO_SKL_H_DRIVER_GPP_H_02 170
+#define GPIO_SKL_H_DRIVER_GPP_H_03 171
+#define GPIO_SKL_H_DRIVER_GPP_H_04 172
+#define GPIO_SKL_H_DRIVER_GPP_H_05 173
+#define GPIO_SKL_H_DRIVER_GPP_H_06 174
+#define GPIO_SKL_H_DRIVER_GPP_H_07 175
+#define GPIO_SKL_H_DRIVER_GPP_H_08 176
+#define GPIO_SKL_H_DRIVER_GPP_H_09 177
+#define GPIO_SKL_H_DRIVER_GPP_H_10 178
+#define GPIO_SKL_H_DRIVER_GPP_H_11 179
+#define GPIO_SKL_H_DRIVER_GPP_H_12 180
+#define GPIO_SKL_H_DRIVER_GPP_H_13 181
+#define GPIO_SKL_H_DRIVER_GPP_H_14 182
+#define GPIO_SKL_H_DRIVER_GPP_H_15 183
+#define GPIO_SKL_H_DRIVER_GPP_H_16 184
+#define GPIO_SKL_H_DRIVER_GPP_H_17 185
+#define GPIO_SKL_H_DRIVER_GPP_H_18 186
+#define GPIO_SKL_H_DRIVER_GPP_H_19 187
+#define GPIO_SKL_H_DRIVER_GPP_H_20 188
+#define GPIO_SKL_H_DRIVER_GPP_H_21 189
+#define GPIO_SKL_H_DRIVER_GPP_H_22 190
+#define GPIO_SKL_H_DRIVER_GPP_H_23 191
+
+#define PCH_I_GPIO_DRIVER_GPP_I_00 192
+#define PCH_I_GPIO_DRIVER_GPP_I_01 193
+#define PCH_I_GPIO_DRIVER_GPP_I_02 194
+#define PCH_I_GPIO_DRIVER_GPP_I_03 195
+#define PCH_I_GPIO_DRIVER_GPP_I_04 196
+#define PCH_I_GPIO_DRIVER_GPP_I_05 197
+#define PCH_I_GPIO_DRIVER_GPP_I_06 198
+#define PCH_I_GPIO_DRIVER_GPP_I_07 199
+#define PCH_I_GPIO_DRIVER_GPP_I_08 200
+#define PCH_I_GPIO_DRIVER_GPP_I_09 201
+#define PCH_I_GPIO_DRIVER_GPP_I_10 202
+
+//
+// SPT GPIO IOxAPIC interrupts
+//
+// SPT-LP:
+#define GPIO_SKL_LP_IOAPIC_GPP_A_00 0x18
+#define GPIO_SKL_LP_IOAPIC_GPP_A_01 0x19
+#define GPIO_SKL_LP_IOAPIC_GPP_A_02 0x1a
+#define GPIO_SKL_LP_IOAPIC_GPP_A_03 0x1b
+#define GPIO_SKL_LP_IOAPIC_GPP_A_04 0x1c
+#define GPIO_SKL_LP_IOAPIC_GPP_A_05 0x1d
+#define GPIO_SKL_LP_IOAPIC_GPP_A_06 0x1e
+#define GPIO_SKL_LP_IOAPIC_GPP_A_07 0x1f
+#define GPIO_SKL_LP_IOAPIC_GPP_A_08 0x20
+#define GPIO_SKL_LP_IOAPIC_GPP_A_09 0x21
+#define GPIO_SKL_LP_IOAPIC_GPP_A_10 0x22
+#define GPIO_SKL_LP_IOAPIC_GPP_A_11 0x23
+#define GPIO_SKL_LP_IOAPIC_GPP_A_12 0x24
+#define GPIO_SKL_LP_IOAPIC_GPP_A_13 0x25
+#define GPIO_SKL_LP_IOAPIC_GPP_A_14 0x26
+#define GPIO_SKL_LP_IOAPIC_GPP_A_15 0x27
+#define GPIO_SKL_LP_IOAPIC_GPP_A_16 0x28
+#define GPIO_SKL_LP_IOAPIC_GPP_A_17 0x29
+#define GPIO_SKL_LP_IOAPIC_GPP_A_18 0x2a
+#define GPIO_SKL_LP_IOAPIC_GPP_A_19 0x2b
+#define GPIO_SKL_LP_IOAPIC_GPP_A_20 0x2c
+#define GPIO_SKL_LP_IOAPIC_GPP_A_21 0x2d
+#define GPIO_SKL_LP_IOAPIC_GPP_A_22 0x2e
+#define GPIO_SKL_LP_IOAPIC_GPP_A_23 0x2f
+
+#define GPIO_SKL_LP_IOAPIC_GPP_B_00 0x30
+#define GPIO_SKL_LP_IOAPIC_GPP_B_01 0x31
+#define GPIO_SKL_LP_IOAPIC_GPP_B_02 0x32
+#define GPIO_SKL_LP_IOAPIC_GPP_B_03 0x33
+#define GPIO_SKL_LP_IOAPIC_GPP_B_04 0x34
+#define GPIO_SKL_LP_IOAPIC_GPP_B_05 0x35
+#define GPIO_SKL_LP_IOAPIC_GPP_B_06 0x36
+#define GPIO_SKL_LP_IOAPIC_GPP_B_07 0x37
+#define GPIO_SKL_LP_IOAPIC_GPP_B_08 0x38
+#define GPIO_SKL_LP_IOAPIC_GPP_B_09 0x39
+#define GPIO_SKL_LP_IOAPIC_GPP_B_10 0x3a
+#define GPIO_SKL_LP_IOAPIC_GPP_B_11 0x3b
+#define GPIO_SKL_LP_IOAPIC_GPP_B_12 0x3c
+#define GPIO_SKL_LP_IOAPIC_GPP_B_13 0x3d
+#define GPIO_SKL_LP_IOAPIC_GPP_B_14 0x3e
+#define GPIO_SKL_LP_IOAPIC_GPP_B_15 0x3f
+#define GPIO_SKL_LP_IOAPIC_GPP_B_16 0x40
+#define GPIO_SKL_LP_IOAPIC_GPP_B_17 0x41
+#define GPIO_SKL_LP_IOAPIC_GPP_B_18 0x42
+#define GPIO_SKL_LP_IOAPIC_GPP_B_19 0x43
+#define GPIO_SKL_LP_IOAPIC_GPP_B_20 0x44
+#define GPIO_SKL_LP_IOAPIC_GPP_B_21 0x45
+#define GPIO_SKL_LP_IOAPIC_GPP_B_22 0x46
+#define GPIO_SKL_LP_IOAPIC_GPP_B_23 0x47
+
+#define GPIO_SKL_LP_IOAPIC_GPP_C_00 0x48
+#define GPIO_SKL_LP_IOAPIC_GPP_C_01 0x49
+#define GPIO_SKL_LP_IOAPIC_GPP_C_02 0x4a
+#define GPIO_SKL_LP_IOAPIC_GPP_C_03 0x4b
+#define GPIO_SKL_LP_IOAPIC_GPP_C_04 0x4c
+#define GPIO_SKL_LP_IOAPIC_GPP_C_05 0x4d
+#define GPIO_SKL_LP_IOAPIC_GPP_C_06 0x4e
+#define GPIO_SKL_LP_IOAPIC_GPP_C_07 0x4f
+#define GPIO_SKL_LP_IOAPIC_GPP_C_08 0x50
+#define GPIO_SKL_LP_IOAPIC_GPP_C_09 0x51
+#define GPIO_SKL_LP_IOAPIC_GPP_C_10 0x52
+#define GPIO_SKL_LP_IOAPIC_GPP_C_11 0x53
+#define GPIO_SKL_LP_IOAPIC_GPP_C_12 0x54
+#define GPIO_SKL_LP_IOAPIC_GPP_C_13 0x55
+#define GPIO_SKL_LP_IOAPIC_GPP_C_14 0x56
+#define GPIO_SKL_LP_IOAPIC_GPP_C_15 0x57
+#define GPIO_SKL_LP_IOAPIC_GPP_C_16 0x58
+#define GPIO_SKL_LP_IOAPIC_GPP_C_17 0x59
+#define GPIO_SKL_LP_IOAPIC_GPP_C_18 0x5a
+#define GPIO_SKL_LP_IOAPIC_GPP_C_19 0x5b
+#define GPIO_SKL_LP_IOAPIC_GPP_C_20 0x5c
+#define GPIO_SKL_LP_IOAPIC_GPP_C_21 0x5d
+#define GPIO_SKL_LP_IOAPIC_GPP_C_22 0x5e
+#define GPIO_SKL_LP_IOAPIC_GPP_C_23 0x5f
+
+#define GPIO_SKL_LP_IOAPIC_GPP_D_00 0x60
+#define GPIO_SKL_LP_IOAPIC_GPP_D_01 0x61
+#define GPIO_SKL_LP_IOAPIC_GPP_D_02 0x62
+#define GPIO_SKL_LP_IOAPIC_GPP_D_03 0x63
+#define GPIO_SKL_LP_IOAPIC_GPP_D_04 0x64
+#define GPIO_SKL_LP_IOAPIC_GPP_D_05 0x65
+#define GPIO_SKL_LP_IOAPIC_GPP_D_06 0x66
+#define GPIO_SKL_LP_IOAPIC_GPP_D_07 0x67
+#define GPIO_SKL_LP_IOAPIC_GPP_D_08 0x68
+#define GPIO_SKL_LP_IOAPIC_GPP_D_09 0x69
+#define GPIO_SKL_LP_IOAPIC_GPP_D_10 0x6a
+#define GPIO_SKL_LP_IOAPIC_GPP_D_11 0x6b
+#define GPIO_SKL_LP_IOAPIC_GPP_D_12 0x6c
+#define GPIO_SKL_LP_IOAPIC_GPP_D_13 0x6d
+#define GPIO_SKL_LP_IOAPIC_GPP_D_14 0x6e
+#define GPIO_SKL_LP_IOAPIC_GPP_D_15 0x6f
+#define GPIO_SKL_LP_IOAPIC_GPP_D_16 0x70
+#define GPIO_SKL_LP_IOAPIC_GPP_D_17 0x71
+#define GPIO_SKL_LP_IOAPIC_GPP_D_18 0x72
+#define GPIO_SKL_LP_IOAPIC_GPP_D_19 0x73
+#define GPIO_SKL_LP_IOAPIC_GPP_D_20 0x74
+#define GPIO_SKL_LP_IOAPIC_GPP_D_21 0x75
+#define GPIO_SKL_LP_IOAPIC_GPP_D_22 0x76
+#define GPIO_SKL_LP_IOAPIC_GPP_D_23 0x77
+
+#define GPIO_SKL_LP_IOAPIC_GPP_E_00 0x18
+#define GPIO_SKL_LP_IOAPIC_GPP_E_01 0x19
+#define GPIO_SKL_LP_IOAPIC_GPP_E_02 0x1a
+#define GPIO_SKL_LP_IOAPIC_GPP_E_03 0x1b
+#define GPIO_SKL_LP_IOAPIC_GPP_E_04 0x1c
+#define GPIO_SKL_LP_IOAPIC_GPP_E_05 0x1d
+#define GPIO_SKL_LP_IOAPIC_GPP_E_06 0x1e
+#define GPIO_SKL_LP_IOAPIC_GPP_E_07 0x1f
+#define GPIO_SKL_LP_IOAPIC_GPP_E_08 0x20
+#define GPIO_SKL_LP_IOAPIC_GPP_E_09 0x21
+#define GPIO_SKL_LP_IOAPIC_GPP_E_10 0x22
+#define GPIO_SKL_LP_IOAPIC_GPP_E_11 0x23
+#define GPIO_SKL_LP_IOAPIC_GPP_E_12 0x24
+#define GPIO_SKL_LP_IOAPIC_GPP_E_13 0x25
+#define GPIO_SKL_LP_IOAPIC_GPP_E_14 0x26
+#define GPIO_SKL_LP_IOAPIC_GPP_E_15 0x27
+#define GPIO_SKL_LP_IOAPIC_GPP_E_16 0x28
+#define GPIO_SKL_LP_IOAPIC_GPP_E_17 0x29
+#define GPIO_SKL_LP_IOAPIC_GPP_E_18 0x2a
+#define GPIO_SKL_LP_IOAPIC_GPP_E_19 0x2b
+#define GPIO_SKL_LP_IOAPIC_GPP_E_20 0x2c
+#define GPIO_SKL_LP_IOAPIC_GPP_E_21 0x2d
+#define GPIO_SKL_LP_IOAPIC_GPP_E_22 0x2e
+#define GPIO_SKL_LP_IOAPIC_GPP_E_23 0x2f
+
+#define GPIO_SKL_LP_IOAPIC_GPP_F_00 0x30
+#define GPIO_SKL_LP_IOAPIC_GPP_F_01 0x31
+#define GPIO_SKL_LP_IOAPIC_GPP_F_02 0x32
+#define GPIO_SKL_LP_IOAPIC_GPP_F_03 0x33
+#define GPIO_SKL_LP_IOAPIC_GPP_F_04 0x34
+#define GPIO_SKL_LP_IOAPIC_GPP_F_05 0x35
+#define GPIO_SKL_LP_IOAPIC_GPP_F_06 0x36
+#define GPIO_SKL_LP_IOAPIC_GPP_F_07 0x37
+#define GPIO_SKL_LP_IOAPIC_GPP_F_08 0x38
+#define GPIO_SKL_LP_IOAPIC_GPP_F_09 0x39
+#define GPIO_SKL_LP_IOAPIC_GPP_F_10 0x3a
+#define GPIO_SKL_LP_IOAPIC_GPP_F_11 0x3b
+#define GPIO_SKL_LP_IOAPIC_GPP_F_12 0x3c
+#define GPIO_SKL_LP_IOAPIC_GPP_F_13 0x3d
+#define GPIO_SKL_LP_IOAPIC_GPP_F_14 0x3e
+#define GPIO_SKL_LP_IOAPIC_GPP_F_15 0x3f
+#define GPIO_SKL_LP_IOAPIC_GPP_F_16 0x40
+#define GPIO_SKL_LP_IOAPIC_GPP_F_17 0x41
+#define GPIO_SKL_LP_IOAPIC_GPP_F_18 0x42
+#define GPIO_SKL_LP_IOAPIC_GPP_F_19 0x43
+#define GPIO_SKL_LP_IOAPIC_GPP_F_20 0x44
+#define GPIO_SKL_LP_IOAPIC_GPP_F_21 0x45
+#define GPIO_SKL_LP_IOAPIC_GPP_F_22 0x46
+#define GPIO_SKL_LP_IOAPIC_GPP_F_23 0x47
+
+#define GPIO_SKL_LP_IOAPIC_GPP_G_00 0x48
+#define GPIO_SKL_LP_IOAPIC_GPP_G_01 0x49
+#define GPIO_SKL_LP_IOAPIC_GPP_G_02 0x4a
+#define GPIO_SKL_LP_IOAPIC_GPP_G_03 0x4b
+#define GPIO_SKL_LP_IOAPIC_GPP_G_04 0x4c
+#define GPIO_SKL_LP_IOAPIC_GPP_G_05 0x4d
+#define GPIO_SKL_LP_IOAPIC_GPP_G_06 0x4e
+#define GPIO_SKL_LP_IOAPIC_GPP_G_07 0x4f
+
+#define GPIO_SKL_LP_IOAPIC_GPD_00 0x50
+#define GPIO_SKL_LP_IOAPIC_GPD_01 0x51
+#define GPIO_SKL_LP_IOAPIC_GPD_02 0x52
+#define GPIO_SKL_LP_IOAPIC_GPD_03 0x53
+#define GPIO_SKL_LP_IOAPIC_GPD_04 0x54
+#define GPIO_SKL_LP_IOAPIC_GPD_05 0x55
+#define GPIO_SKL_LP_IOAPIC_GPD_06 0x56
+#define GPIO_SKL_LP_IOAPIC_GPD_07 0x57
+#define GPIO_SKL_LP_IOAPIC_GPD_08 0x58
+#define GPIO_SKL_LP_IOAPIC_GPD_09 0x59
+#define GPIO_SKL_LP_IOAPIC_GPD_10 0x5a
+#define GPIO_SKL_LP_IOAPIC_GPD_11 0x5b
+
+//SPT-H:
+#define GPIO_SKL_H_IOAPIC_GPP_A_00 0x18
+#define GPIO_SKL_H_IOAPIC_GPP_A_01 0x19
+#define GPIO_SKL_H_IOAPIC_GPP_A_02 0x1a
+#define GPIO_SKL_H_IOAPIC_GPP_A_03 0x1b
+#define GPIO_SKL_H_IOAPIC_GPP_A_04 0x1c
+#define GPIO_SKL_H_IOAPIC_GPP_A_05 0x1d
+#define GPIO_SKL_H_IOAPIC_GPP_A_06 0x1e
+#define GPIO_SKL_H_IOAPIC_GPP_A_07 0x1f
+#define GPIO_SKL_H_IOAPIC_GPP_A_08 0x20
+#define GPIO_SKL_H_IOAPIC_GPP_A_09 0x21
+#define GPIO_SKL_H_IOAPIC_GPP_A_10 0x22
+#define GPIO_SKL_H_IOAPIC_GPP_A_11 0x23
+#define GPIO_SKL_H_IOAPIC_GPP_A_12 0x24
+#define GPIO_SKL_H_IOAPIC_GPP_A_13 0x25
+#define GPIO_SKL_H_IOAPIC_GPP_A_14 0x26
+#define GPIO_SKL_H_IOAPIC_GPP_A_15 0x27
+#define GPIO_SKL_H_IOAPIC_GPP_A_16 0x28
+#define GPIO_SKL_H_IOAPIC_GPP_A_17 0x29
+#define GPIO_SKL_H_IOAPIC_GPP_A_18 0x2a
+#define GPIO_SKL_H_IOAPIC_GPP_A_19 0x2b
+#define GPIO_SKL_H_IOAPIC_GPP_A_20 0x2c
+#define GPIO_SKL_H_IOAPIC_GPP_A_21 0x2d
+#define GPIO_SKL_H_IOAPIC_GPP_A_22 0x2e
+#define GPIO_SKL_H_IOAPIC_GPP_A_23 0x2f
+
+#define GPIO_SKL_H_IOAPIC_GPP_B_00 0x30
+#define GPIO_SKL_H_IOAPIC_GPP_B_01 0x31
+#define GPIO_SKL_H_IOAPIC_GPP_B_02 0x32
+#define GPIO_SKL_H_IOAPIC_GPP_B_03 0x33
+#define GPIO_SKL_H_IOAPIC_GPP_B_04 0x34
+#define GPIO_SKL_H_IOAPIC_GPP_B_05 0x35
+#define GPIO_SKL_H_IOAPIC_GPP_B_06 0x36
+#define GPIO_SKL_H_IOAPIC_GPP_B_07 0x37
+#define GPIO_SKL_H_IOAPIC_GPP_B_08 0x38
+#define GPIO_SKL_H_IOAPIC_GPP_B_09 0x39
+#define GPIO_SKL_H_IOAPIC_GPP_B_10 0x3a
+#define GPIO_SKL_H_IOAPIC_GPP_B_11 0x3b
+#define GPIO_SKL_H_IOAPIC_GPP_B_12 0x3c
+#define GPIO_SKL_H_IOAPIC_GPP_B_13 0x3d
+#define GPIO_SKL_H_IOAPIC_GPP_B_14 0x3e
+#define GPIO_SKL_H_IOAPIC_GPP_B_15 0x3f
+#define GPIO_SKL_H_IOAPIC_GPP_B_16 0x40
+#define GPIO_SKL_H_IOAPIC_GPP_B_17 0x41
+#define GPIO_SKL_H_IOAPIC_GPP_B_18 0x42
+#define GPIO_SKL_H_IOAPIC_GPP_B_19 0x43
+#define GPIO_SKL_H_IOAPIC_GPP_B_20 0x44
+#define GPIO_SKL_H_IOAPIC_GPP_B_21 0x45
+#define GPIO_SKL_H_IOAPIC_GPP_B_22 0x46
+#define GPIO_SKL_H_IOAPIC_GPP_B_23 0x47
+
+#define GPIO_SKL_H_IOAPIC_GPP_C_00 0x48
+#define GPIO_SKL_H_IOAPIC_GPP_C_01 0x49
+#define GPIO_SKL_H_IOAPIC_GPP_C_02 0x4a
+#define GPIO_SKL_H_IOAPIC_GPP_C_03 0x4b
+#define GPIO_SKL_H_IOAPIC_GPP_C_04 0x4c
+#define GPIO_SKL_H_IOAPIC_GPP_C_05 0x4d
+#define GPIO_SKL_H_IOAPIC_GPP_C_06 0x4e
+#define GPIO_SKL_H_IOAPIC_GPP_C_07 0x4f
+#define GPIO_SKL_H_IOAPIC_GPP_C_08 0x50
+#define GPIO_SKL_H_IOAPIC_GPP_C_09 0x51
+#define GPIO_SKL_H_IOAPIC_GPP_C_10 0x52
+#define GPIO_SKL_H_IOAPIC_GPP_C_11 0x53
+#define GPIO_SKL_H_IOAPIC_GPP_C_12 0x54
+#define GPIO_SKL_H_IOAPIC_GPP_C_13 0x55
+#define GPIO_SKL_H_IOAPIC_GPP_C_14 0x56
+#define GPIO_SKL_H_IOAPIC_GPP_C_15 0x57
+#define GPIO_SKL_H_IOAPIC_GPP_C_16 0x58
+#define GPIO_SKL_H_IOAPIC_GPP_C_17 0x59
+#define GPIO_SKL_H_IOAPIC_GPP_C_18 0x5a
+#define GPIO_SKL_H_IOAPIC_GPP_C_19 0x5b
+#define GPIO_SKL_H_IOAPIC_GPP_C_20 0x5c
+#define GPIO_SKL_H_IOAPIC_GPP_C_21 0x5d
+#define GPIO_SKL_H_IOAPIC_GPP_C_22 0x5e
+#define GPIO_SKL_H_IOAPIC_GPP_C_23 0x5f
+
+#define GPIO_SKL_H_IOAPIC_GPP_D_00 0x60
+#define GPIO_SKL_H_IOAPIC_GPP_D_01 0x61
+#define GPIO_SKL_H_IOAPIC_GPP_D_02 0x62
+#define GPIO_SKL_H_IOAPIC_GPP_D_03 0x63
+#define GPIO_SKL_H_IOAPIC_GPP_D_04 0x64
+#define GPIO_SKL_H_IOAPIC_GPP_D_05 0x65
+#define GPIO_SKL_H_IOAPIC_GPP_D_06 0x66
+#define GPIO_SKL_H_IOAPIC_GPP_D_07 0x67
+#define GPIO_SKL_H_IOAPIC_GPP_D_08 0x68
+#define GPIO_SKL_H_IOAPIC_GPP_D_09 0x69
+#define GPIO_SKL_H_IOAPIC_GPP_D_10 0x6a
+#define GPIO_SKL_H_IOAPIC_GPP_D_11 0x6b
+#define GPIO_SKL_H_IOAPIC_GPP_D_12 0x6c
+#define GPIO_SKL_H_IOAPIC_GPP_D_13 0x6d
+#define GPIO_SKL_H_IOAPIC_GPP_D_14 0x6e
+#define GPIO_SKL_H_IOAPIC_GPP_D_15 0x6f
+#define GPIO_SKL_H_IOAPIC_GPP_D_16 0x70
+#define GPIO_SKL_H_IOAPIC_GPP_D_17 0x71
+#define GPIO_SKL_H_IOAPIC_GPP_D_18 0x72
+#define GPIO_SKL_H_IOAPIC_GPP_D_19 0x73
+#define GPIO_SKL_H_IOAPIC_GPP_D_20 0x74
+#define GPIO_SKL_H_IOAPIC_GPP_D_21 0x75
+#define GPIO_SKL_H_IOAPIC_GPP_D_22 0x76
+#define GPIO_SKL_H_IOAPIC_GPP_D_23 0x77
+
+#define GPIO_SKL_H_IOAPIC_GPP_E_00 0x18
+#define GPIO_SKL_H_IOAPIC_GPP_E_01 0x19
+#define GPIO_SKL_H_IOAPIC_GPP_E_02 0x1a
+#define GPIO_SKL_H_IOAPIC_GPP_E_03 0x1b
+#define GPIO_SKL_H_IOAPIC_GPP_E_04 0x1c
+#define GPIO_SKL_H_IOAPIC_GPP_E_05 0x1d
+#define GPIO_SKL_H_IOAPIC_GPP_E_06 0x1e
+#define GPIO_SKL_H_IOAPIC_GPP_E_07 0x1f
+#define GPIO_SKL_H_IOAPIC_GPP_E_08 0x20
+#define GPIO_SKL_H_IOAPIC_GPP_E_09 0x21
+#define GPIO_SKL_H_IOAPIC_GPP_E_10 0x22
+#define GPIO_SKL_H_IOAPIC_GPP_E_11 0x23
+#define GPIO_SKL_H_IOAPIC_GPP_E_12 0x24
+
+#define GPIO_SKL_H_IOAPIC_GPP_F_00 0x25
+#define GPIO_SKL_H_IOAPIC_GPP_F_01 0x26
+#define GPIO_SKL_H_IOAPIC_GPP_F_02 0x27
+#define GPIO_SKL_H_IOAPIC_GPP_F_03 0x28
+#define GPIO_SKL_H_IOAPIC_GPP_F_04 0x29
+#define GPIO_SKL_H_IOAPIC_GPP_F_05 0x2a
+#define GPIO_SKL_H_IOAPIC_GPP_F_06 0x2b
+#define GPIO_SKL_H_IOAPIC_GPP_F_07 0x2c
+#define GPIO_SKL_H_IOAPIC_GPP_F_08 0x2d
+#define GPIO_SKL_H_IOAPIC_GPP_F_09 0x2e
+#define GPIO_SKL_H_IOAPIC_GPP_F_10 0x2f
+#define GPIO_SKL_H_IOAPIC_GPP_F_11 0x30
+#define GPIO_SKL_H_IOAPIC_GPP_F_12 0x31
+#define GPIO_SKL_H_IOAPIC_GPP_F_13 0x32
+#define GPIO_SKL_H_IOAPIC_GPP_F_14 0x33
+#define GPIO_SKL_H_IOAPIC_GPP_F_15 0x34
+#define GPIO_SKL_H_IOAPIC_GPP_F_16 0x35
+#define GPIO_SKL_H_IOAPIC_GPP_F_17 0x36
+#define GPIO_SKL_H_IOAPIC_GPP_F_18 0x37
+#define GPIO_SKL_H_IOAPIC_GPP_F_19 0x38
+#define GPIO_SKL_H_IOAPIC_GPP_F_20 0x39
+#define GPIO_SKL_H_IOAPIC_GPP_F_21 0x3a
+#define GPIO_SKL_H_IOAPIC_GPP_F_22 0x3b
+#define GPIO_SKL_H_IOAPIC_GPP_F_23 0x3c
+
+#define GPIO_SKL_H_IOAPIC_GPP_G_00 0x3d
+#define GPIO_SKL_H_IOAPIC_GPP_G_01 0x3e
+#define GPIO_SKL_H_IOAPIC_GPP_G_02 0x3f
+#define GPIO_SKL_H_IOAPIC_GPP_G_03 0x40
+#define GPIO_SKL_H_IOAPIC_GPP_G_04 0x41
+#define GPIO_SKL_H_IOAPIC_GPP_G_05 0x42
+#define GPIO_SKL_H_IOAPIC_GPP_G_06 0x43
+#define GPIO_SKL_H_IOAPIC_GPP_G_07 0x44
+#define GPIO_SKL_H_IOAPIC_GPP_G_08 0x45
+#define GPIO_SKL_H_IOAPIC_GPP_G_09 0x46
+#define GPIO_SKL_H_IOAPIC_GPP_G_10 0x47
+#define GPIO_SKL_H_IOAPIC_GPP_G_11 0x48
+#define GPIO_SKL_H_IOAPIC_GPP_G_12 0x49
+#define GPIO_SKL_H_IOAPIC_GPP_G_13 0x4a
+#define GPIO_SKL_H_IOAPIC_GPP_G_14 0x4b
+#define GPIO_SKL_H_IOAPIC_GPP_G_15 0x4c
+#define GPIO_SKL_H_IOAPIC_GPP_G_16 0x4d
+#define GPIO_SKL_H_IOAPIC_GPP_G_17 0x4e
+#define GPIO_SKL_H_IOAPIC_GPP_G_18 0x4f
+#define GPIO_SKL_H_IOAPIC_GPP_G_19 0x50
+#define GPIO_SKL_H_IOAPIC_GPP_G_20 0x51
+#define GPIO_SKL_H_IOAPIC_GPP_G_21 0x52
+#define GPIO_SKL_H_IOAPIC_GPP_G_22 0x53
+#define GPIO_SKL_H_IOAPIC_GPP_G_23 0x54
+
+#define GPIO_SKL_H_IOAPIC_GPP_H_00 0x55
+#define GPIO_SKL_H_IOAPIC_GPP_H_01 0x56
+#define GPIO_SKL_H_IOAPIC_GPP_H_02 0x57
+#define GPIO_SKL_H_IOAPIC_GPP_H_03 0x58
+#define GPIO_SKL_H_IOAPIC_GPP_H_04 0x59
+#define GPIO_SKL_H_IOAPIC_GPP_H_05 0x5a
+#define GPIO_SKL_H_IOAPIC_GPP_H_06 0x5b
+#define GPIO_SKL_H_IOAPIC_GPP_H_07 0x5c
+#define GPIO_SKL_H_IOAPIC_GPP_H_08 0x5d
+#define GPIO_SKL_H_IOAPIC_GPP_H_09 0x5e
+#define GPIO_SKL_H_IOAPIC_GPP_H_10 0x5f
+#define GPIO_SKL_H_IOAPIC_GPP_H_11 0x60
+#define GPIO_SKL_H_IOAPIC_GPP_H_12 0x61
+#define GPIO_SKL_H_IOAPIC_GPP_H_13 0x62
+#define GPIO_SKL_H_IOAPIC_GPP_H_14 0x63
+#define GPIO_SKL_H_IOAPIC_GPP_H_15 0x64
+#define GPIO_SKL_H_IOAPIC_GPP_H_16 0x65
+#define GPIO_SKL_H_IOAPIC_GPP_H_17 0x66
+#define GPIO_SKL_H_IOAPIC_GPP_H_18 0x67
+#define GPIO_SKL_H_IOAPIC_GPP_H_19 0x68
+#define GPIO_SKL_H_IOAPIC_GPP_H_20 0x69
+#define GPIO_SKL_H_IOAPIC_GPP_H_21 0x6a
+#define GPIO_SKL_H_IOAPIC_GPP_H_22 0x6b
+#define GPIO_SKL_H_IOAPIC_GPP_H_23 0x6c
+
+#define GPIO_SKL_H_IOAPIC_GPP_I_00 0x6d
+#define GPIO_SKL_H_IOAPIC_GPP_I_01 0x6e
+#define GPIO_SKL_H_IOAPIC_GPP_I_02 0x6f
+#define GPIO_SKL_H_IOAPIC_GPP_I_03 0x70
+#define GPIO_SKL_H_IOAPIC_GPP_I_04 0x71
+#define GPIO_SKL_H_IOAPIC_GPP_I_05 0x72
+#define GPIO_SKL_H_IOAPIC_GPP_I_06 0x73
+#define GPIO_SKL_H_IOAPIC_GPP_I_07 0x74
+#define GPIO_SKL_H_IOAPIC_GPP_I_08 0x75
+#define GPIO_SKL_H_IOAPIC_GPP_I_09 0x76
+#define GPIO_SKL_H_IOAPIC_GPP_I_10 0x77
+
+#define GPIO_SKL_H_IOAPIC_GPD_00 0x18
+#define GPIO_SKL_H_IOAPIC_GPD_01 0x19
+#define GPIO_SKL_H_IOAPIC_GPD_02 0x1a
+#define GPIO_SKL_H_IOAPIC_GPD_03 0x1b
+#define GPIO_SKL_H_IOAPIC_GPD_04 0x1c
+#define GPIO_SKL_H_IOAPIC_GPD_05 0x1d
+#define GPIO_SKL_H_IOAPIC_GPD_06 0x1e
+#define GPIO_SKL_H_IOAPIC_GPD_07 0x1f
+#define GPIO_SKL_H_IOAPIC_GPD_08 0x20
+#define GPIO_SKL_H_IOAPIC_GPD_09 0x21
+#define GPIO_SKL_H_IOAPIC_GPD_10 0x22
+#define GPIO_SKL_H_IOAPIC_GPD_11 0x23
+
+#endif // GPIO_DEFINE_ASL
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLib.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLib.asl
new file mode 100644
index 0000000000..b9809bd2ab
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLib.asl
@@ -0,0 +1,849 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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("GpioLibObjects.asl")
+
+//
+// PADCFG register is split into multiple DW registers
+// PAD_CFG_SIZE holds number of bytes used by all those registers for one pad
+//
+#define PAD_CFG_SIZE 0x08
+
+//
+// Get number of DoubleWord registers used by one group
+//
+#define TOTAL_NUMBER_OF_DW_REGS_FOR_GPIO_GROUP(GpioGroupIndex) \
+ ( \
+ Add( \
+ ShiftRight( \
+ GINF(GpioGroupIndex,GPIO_PAD_NUM_FIELD), \
+ 5), \
+ 1) \
+ )
+
+//
+// Check if group belongs to 2-Tier GPE
+//
+#define IS_GPIO_GROUP_IN_2_TIER_GPE(GpioGroupIndex) \
+ ( \
+ LEqual( \
+ And( \
+ ShiftRight( \
+ GPEM, \
+ Multiply( \
+ GpioGroupIndex, \
+ 2)), \
+ 0x3), \
+ 0x0) \
+ )
+
+//
+// Get PADCFG_DW0 GpioPad register address
+//
+#define GET_GPIO_PAD_PADCFG_REG_ADDRESS(GpioGroupIndex,GpioPadNumber) \
+ ( \
+ Add( \
+ GET_PADCFG_REG_ADDRESS(GpioGroupIndex), \
+ Multiply( \
+ GpioPadNumber, \
+ PAD_CFG_SIZE) \
+ ) \
+ )
+
+//
+// Get GPIO register address
+// If group has more DW registers for certain feature
+// below macro will return address of the first one.
+//
+#define GET_PADCFG_REG_ADDRESS(GpioGroupIndex) GADR(GpioGroupIndex,GPIO_PADCFG_REG_FIELD)
+#define GET_HOSTSW_OWN_REG_ADDRESS(GpioGroupIndex) GADR(GpioGroupIndex,GPIO_HOSTOWN_REG_FIELD)
+#define GET_PAD_OWN_REG_ADDRESS(GpioGroupIndex) GADR(GpioGroupIndex,GPIO_PADOWN_REG_FIELD)
+#define GET_GPE_STS_REG_ADDRESS(GpioGroupIndex) GADR(GpioGroupIndex,GPIO_GPE_STS_REG_FIELD)
+
+//
+// GPIO Access Library
+//
+Scope(\_SB)
+{
+ //
+ // Arg1 possible values for internal GINF function
+ //
+ #define GPIO_COM_FIELD 0
+ #define GPIO_PAD_NUM_FIELD 1
+ #define GPIO_PADCFG_REG_FIELD 2
+ #define GPIO_HOSTOWN_REG_FIELD 3
+ #define GPIO_PADOWN_REG_FIELD 4
+ #define GPIO_GPE_STS_REG_FIELD 5
+
+ //
+ // Get GPIO group information
+ // This is internal library function
+ //
+ Method(GINF, 0x2, NotSerialized)
+ {
+ //
+ // Arg0 - GPIO Group index
+ // Arg1 - GPIO field type
+ //
+ If(LEqual(PCHS, SPTL)) { // PCH-LP
+ Return (PCH_LP_GPIO_GET_FIELD(Arg0,Arg1))
+ } Else { //PCH-H
+ Return (PCH_H_GPIO_GET_FIELD(Arg0,Arg1))
+ }
+ }
+
+ //
+ // Get GPIO maximal group
+ // This is internal library function
+ //
+ Method(GMXG, 0x0, NotSerialized)
+ {
+ If(LEqual(PCHS, SPTL)) { // PCH-LP
+ Return (V_PCH_LP_GPIO_GROUP_MAX)
+ } Else { //PCH-H
+ Return (V_PCH_H_GPIO_GROUP_MAX)
+ }
+ }
+
+ //
+ // Get GPIO register address
+ // This is internal library function
+ //
+ Method(GADR, 0x2, NotSerialized)
+ {
+ //
+ // Arg0 - GPIO Group index
+ // Arg1 - GPIO register type, must match what is used by GINF method
+ //
+ //Local0 = GpioCommunityAddress
+ Store( Add(GINF(Arg0,GPIO_COM_FIELD), SBRG), Local0)
+
+ //Local1 = Register Offset
+ Store(GINF(Arg0,Arg1), Local1)
+
+ Return( Add (Local0, Local1))
+ }
+
+ //
+ // Get GPIO absolute number for selected GpioPad
+ //
+ Method(GNUM, 0x1, NotSerialized)
+ {
+ //
+ // Arg0 - GpioPad
+ //
+
+ // Local0 - Gpio pad number
+ Store (GNMB(Arg0), Local0)
+ // Local1 - Gpio group index for GpioPad
+ Store (GGRP(Arg0), Local1)
+
+ Return (Add(Local0,Multiply(Local1, 24)))
+ }
+
+ //
+ // Get interrupt number for selected GpioPad
+ //
+ Method(INUM, 0x1, NotSerialized)
+ {
+ //
+ // Arg0 - GpioPad
+ //
+ // Local1 - Gpio pad number
+ Store (GNMB(Arg0), Local1)
+ // Local2 - Gpio group index for GpioPad
+ Store (GGRP(Arg0), Local2)
+ // Local3 - Group index used in a loop
+ Store (0 , Local3)
+
+ While(LLess (Local3, Local2)) {
+ // Get Number of GpioPads for certain Group (GroupIndex - Local3) and add it to Local1
+ Add( GINF(Local3,GPIO_PAD_NUM_FIELD) ,Local1,Local1)
+
+ Increment(Local3)
+ }
+
+ return(Add(24,Mod(Local1,96)))
+ }
+
+ //
+ // Get GPIO group index for GpioPad
+ //
+ Method(GGRP,1,serialized) {
+ //
+ // Arg0 - GpioPad
+ //
+ ShiftRight( And(Arg0,0x00FF0000), 16, Local0)
+ return (Local0)
+ }
+
+ //
+ // Get GPIO pin number for GpioPad
+ //
+ Method(GNMB,1,serialized) {
+ //
+ // Arg0 - GpioPad
+ //
+ return (And(Arg0,0x0000FFFF))
+ }
+
+ //
+ // GPEM (part of PCH NVS) is an object for informing how GPIO groups are mapped to GPE.
+ // Mapping for GPP_x is evaluated from (GPEM >> (GroupNumber*2)) & 0x3
+ // Possible values for each group:
+ // 00b - 2-tier
+ // 01b - 1-tier, GPE_DW0
+ // 10b - 1-tier, GPE_DW1
+ // 11b - 1-tier, GPE_DW2
+ //
+
+ //
+ // Get GPE number for selected GpioPad
+ //
+ Method(GGPE, 0x1, NotSerialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+
+ //Local0 - GPIO group index (GPP_A - 0, GPP_B - 1 ... )
+ Store (GGRP(Arg0), Local0)
+ //Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ If (IS_GPIO_GROUP_IN_2_TIER_GPE(Local0)) {
+ //
+ // Pads mapped to 2-tier GPE will all generate GPE_111
+ //
+ Return (0x6F)
+ } Else {
+ //
+ // Get mapping for certain group
+ // Local2 = (GPEM >> (Local0*2)) & 0x3
+ //
+ Store(And(ShiftRight(GPEM,Multiply(Local0,2)),0x3),Local2)
+ //
+ // For 1-tier GPE calculate GPE number
+ // GPE number = (Local2 - 1)*32 + Local1
+ //
+ Return (Add(Multiply(Subtract(Local2,1),32),Local1))
+ }
+ }
+
+ //
+ // Get Pad Configuration DW0 register value
+ //
+ Method(GPC0, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store(GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Set Pad Configuration DW0 register value
+ //
+ Method(SPC0, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for DW0 register
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Get Pad Configuration DW1 register value
+ //
+ Method(GPC1, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE) + 0x4
+ Store( Add( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),0x4),Local2)
+ OperationRegion(PDW1, SystemMemory, Local2, 4)
+ Field(PDW1, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Set Pad Configuration DW1 register value
+ //
+ Method(SPC1, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for DW1 register
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local0 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE) + 0x4
+ Store( Add( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),0x4),Local2)
+ OperationRegion(PDW1, SystemMemory, Local2, 4)
+ Field(PDW1, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Set RX Override
+ //
+ Method(SRXO, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - 0=no override, 1=drive RX to 1 internally
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ ,28,
+ TEMP,1,
+ ,3
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Get GPI Input Value
+ //
+ Method(GGIV, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 1,
+ TEMP,1,
+ , 30
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Get GPO Output Value
+ //
+ Method(GGOV, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,1,
+ , 31
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Set GPO Output Value
+ //
+ Method(SGOV, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value of GPIO Tx State
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,1,
+ , 31
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Get GPI Input Invert Bit
+ //
+ Method(GGII, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 23,
+ TEMP,1,
+ , 8
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Set GPI Input Invert Bit
+ //
+ Method(SGII, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value of RXINV bit for selected pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 23,
+ TEMP,1,
+ , 8
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Get GPIO Pad Mode
+ //
+ Method(GPMV, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 10,
+ TEMP,3,
+ , 19
+ }
+ Return(TEMP)
+ }
+
+ //
+ // Set GPIO Pad Mode
+ //
+ Method(SPMV, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for Pad Mode for selected pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 10,
+ TEMP,3,
+ , 19
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Get GPIO Host Software Pad Ownership
+ //
+ Method(GHPO, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+ // Local3 - Register offset = HostSwOwnRegOffset + (GpioPadNumber >> 5)*0x4
+ Add (GET_HOSTSW_OWN_REG_ADDRESS(Local0), Multiply (ShiftRight(Local1,5), 0x4), Local3)
+ // Local4 - Pad bit position within register, Local4 = GpioPad & 0x1F = GpioPad % 32
+ And (Local1, 0x1F, Local4)
+
+ OperationRegion(PREG, SystemMemory, Local3, 4)
+ Field(PREG, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ // HostSwOwnValue = (TEMP >> Local4) & 0x1
+ Return( And( ShiftRight(TEMP,Local4),0x1))
+ }
+
+ //
+ // Set GPIO Host Software Pad Ownership
+ //
+ Method(SHPO, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for GPIO Host Software Pad Ownership
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+ // Local3 - Register offset = HostSwOwnRegOffset + (GpioPadNumber >> 5)*0x4
+ Add (GET_HOSTSW_OWN_REG_ADDRESS(Local0), Multiply (ShiftRight(Local1,5), 0x4), Local3)
+ // Local4 - Pad bit position within register, Local4 = GpioPad & 0x1F = GpioPad % 32
+ And (Local1, 0x1F, Local4)
+
+ OperationRegion(PREG, SystemMemory, Local3, 4)
+ Field(PREG, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+
+ If (Arg1) {
+ //TEMP = TEMP | (1 << PadBitPosition)
+ Or(TEMP, ShiftLeft(1,Local4), TEMP)
+ } Else {
+ //TEMP = TEMP & ~(1 << PadBitPosition)
+ And(TEMP, Not(ShiftLeft(1,Local4)),TEMP)
+ }
+ }
+
+ //
+ // Get GPIO Pad Ownership
+ //
+ Method(GGPO, 0x1, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = PadOwnAddress + (PadNumber >> 3) * 0x4
+ Store( Add( GET_PAD_OWN_REG_ADDRESS(Local0) , Multiply( ShiftRight(Local1,3),0x4)),Local2)
+ OperationRegion(PREG, SystemMemory, Local2, 4)
+ Field(PREG, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ TEMP,32
+ }
+ // PadOwnValue = (TEMP >> ((Local1 & 0x7) * 4)) & 0x3
+ Return( And( ShiftRight(TEMP,Multiply(And(Local1,0x7),0x4)),0x3))
+ }
+
+ //
+ // Set GPIO GPIRoutIOxAPIC value
+ //
+ Method(SGRA, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for GPIRoutIOxAPIC
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 20,
+ TEMP,1,
+ , 11
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // Set GPIO weak pull-up/down value
+ //
+ Method(SGWP, 0x2, Serialized)
+ {
+ //
+ // Arg0 - GPIO pad
+ // Arg1 - Value for weak pull-up/down
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + 0x4 + (GPIn * PAD_CFG_SIZE)
+ Store( Add( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),0x4),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 10,
+ TEMP,4,
+ , 18
+ }
+ Store(Arg1,TEMP)
+ }
+
+ //
+ // ISME and CAGS methods are used to properly handle 2-tier GPE
+ // Example:
+ /*
+ Method(_L6F, 0) // Method which is called for all 2-tier GPE, must be within _GPE scope
+ {
+ If (\_SB.ISME(GpioPad))
+ {
+ \_SB.DeviceXYZ.GPEH() // Custom function to handle GPE for certain GPIO pad
+ \_SB.CAGS(GpioPad) // Clear 2-Tier GPE status
+ }
+ }
+ */
+
+ //
+ // @deprecated method, maintained for compatibility
+ // Will be removed in future generations
+ //
+ Method(UGPS, 0x0, Serialized) {
+
+ }
+
+ //
+ // Clear all GPE status for 2-tier
+ // @deprecated method, maintained for compatibility
+ // Will be removed in future generations
+ //
+ Method(CGPS, 0x0, Serialized) {
+
+ }
+
+ //
+ // Clear all GPE status for 2-tier which are level sensitive
+ // @deprecated method, maintained for compatibility
+ // Will be removed in future generations
+ //
+ Method(CGLS, 0x0, Serialized) {
+
+ }
+
+ //
+ // Clear a particular GPE status for 2-tier
+ //
+ Method(CAGS, 0x1, Serialized) {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+ // Local4 - Additional offset to handle cases when GPIO group has more than 32 pads
+ Multiply(ShiftRight (Local1,5),4,Local4)
+
+ //Check if 2-tier
+ If (IS_GPIO_GROUP_IN_2_TIER_GPE(Local0)) {
+ //Get GPI_GPE_STS for GPP_x
+ OperationRegion(GPPX, SystemMemory, Add(GET_GPE_STS_REG_ADDRESS(Local0),Local4), 4)
+ Field(GPPX, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ STSX,32,
+ }
+ // Local2 - GpioPad bit mask within register
+ ShiftLeft(1, Mod(Local1,32), Local2)
+ // Clear GPIO status by writing 1b for a pad
+ Store(Local2, STSX)
+ }
+ }
+
+ //
+ // Check if GPIO pad was source of 2-Tier GPE event
+ //
+ Method(ISME, 0x1, NotSerialized) {
+ //
+ // Arg0 - GPIO pad
+ //
+ If (LNot(IS_GPIO_GROUP_IN_2_TIER_GPE(Arg0))) {
+ Return(0)
+ }
+
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+ // Local2 - Register offset = GpeStsRegOffset + (GpioPadNumber >> 5)*0x4
+ Add (GET_GPE_STS_REG_ADDRESS(Local0), Multiply (ShiftRight(Local1,5), 0x4), Local2)
+ // Local3 - Pad bit position within register, Local3 = GpioPad & 0x1F = GpioPad % 32
+ And (Local1, 0x1F, Local3)
+
+ OperationRegion(GPPX, SystemMemory, Local2, 0x24)
+ Field(GPPX, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ STSX,32,
+ Offset(0x20),
+ GENX,32
+ }
+
+ //Return result of GPI_GPE_EN&GPI_GPE_STS for this pad
+ Return(And(ShiftRight(And(STSX,GENX),Local3),0x1))
+ }
+
+ //
+ // Do Interrupt Pin Isolation
+ // This method should be called before power gating external device
+ // which uses Gpio pad as an interrupt
+ //
+ Method(DIPI, 0x1, Serialized) {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 9,
+ RDIS,1,
+ , 15,
+ RCFG,2,
+ , 5
+ }
+ If(LNotEqual(RCFG,2)) {
+ // Save RxEvCfg state in RXEV object:
+ // RXEV[GroupIndex][PadNumber] = RCFG
+ Store(RCFG, Index( DeRefOf(Index(RXEV,Local0)), Local1))
+ // Set RxEvCfg to 2
+ Store(2,RCFG)
+ // Set GPIORxDis to 1
+ Store(1,RDIS)
+ }
+ }
+
+ //
+ // Undo Interrupt Pin Isolation
+ // This method should be called after un-power gating external device
+ // which uses Gpio pad as an interrupt
+ //
+ Method(UIPI, 0x1, Serialized) {
+ //
+ // Arg0 - GPIO pad
+ //
+ // Local0 - GPIO group index
+ Store (GGRP(Arg0), Local0)
+ // Local1 - GPIO pad number
+ Store (GNMB(Arg0), Local1)
+
+ // Local2 = (GpioCommunityAddress + PadCfgOffset) + (GPIn * PAD_CFG_SIZE)
+ Store( GET_GPIO_PAD_PADCFG_REG_ADDRESS(Local0,Local1),Local2)
+ OperationRegion(PDW0, SystemMemory, Local2, 4)
+ Field(PDW0, AnyAcc, NoLock, Preserve) {
+ Offset(0x0),
+ , 9,
+ RDIS,1,
+ , 15,
+ RCFG,2,
+ , 5
+ }
+ // Get RxEvCfg original value from RXEV object
+ // Local3 = RXEV[GroupIndex][PadNumber]
+ Store( DeRefOf(Index( DeRefOf(Index (RXEV, Local0)), Local1)), Local3)
+
+ If(LNotEqual(Local3,2)) {
+ // Set GPIORxDis to 0
+ Store(0,RDIS)
+ // Set RxEvCfg to original value
+ Store(Local3,RCFG)
+ }
+ }
+
+} // \_SB Scope
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLibObjects.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLibObjects.asl
new file mode 100644
index 0000000000..1468aedba4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/GpioLibObjects.asl
@@ -0,0 +1,230 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+#define PCH_LP_GPIO_GET_FIELD(GpioGroupIndex,GpioFieldIndex) \
+ ( \
+ DeRefOf(Index( \
+ DeRefOf(Index( \
+ GPCL, \
+ GpioGroupIndex)), \
+ GpioFieldIndex)) \
+ )
+
+#define PCH_H_GPIO_GET_FIELD(GpioGroupIndex,GpioFieldIndex) \
+ ( \
+ DeRefOf(Index( \
+ DeRefOf(Index( \
+ GPCH, \
+ GpioGroupIndex)), \
+ GpioFieldIndex)) \
+ )
+
+//
+// GPIO Library objects
+//
+Scope(\_SB)
+{
+
+ //
+ // GPIO information data structure
+ //
+ // PCH-LP: GPCL
+ // PCH-H: GPCH
+ //
+ // GPCx[GroupIndex][Field]
+ // Field0 - Community
+ // Field1 - Pad number
+ // Field2 - PADCFG register offset
+ // Field3 - HOSTSW_OWN register offset
+ // Field4 - PAD_OWN register offset
+ // Field5 - GPI_GPE_STS register offset
+ //
+ //
+ // GPIO information data structure for PCH-LP
+ //
+ Name(GPCL, Package(){
+ Package(){ // GPP_A
+ PCH_GPIO_COM0,
+ V_PCH_GPIO_GPP_A_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_A_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS
+ },
+ Package(){ // GPP_B
+ PCH_GPIO_COM0,
+ V_PCH_GPIO_GPP_B_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_B_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS
+ },
+ Package(){ // GPP_C
+ PCH_GPIO_COM1,
+ V_PCH_GPIO_GPP_C_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_C_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS
+ },
+ Package(){ // GPP_D
+ PCH_GPIO_COM1,
+ V_PCH_GPIO_GPP_D_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_D_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS
+ },
+ Package(){ // GPP_E
+ PCH_GPIO_COM1,
+ V_PCH_LP_GPIO_GPP_E_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_E_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS
+ },
+ Package(){ // GPP_F
+ PCH_GPIO_COM3,
+ V_PCH_GPIO_GPP_F_PAD_MAX,
+ R_PCH_LP_PCR_GPIO_GPP_F_PADCFG_OFFSET,
+ R_PCH_LP_PCR_GPIO_GPP_F_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_F_PAD_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_F_GPI_GPE_STS
+ },
+ Package(){ // GPP_G
+ PCH_GPIO_COM3,
+ V_PCH_LP_GPIO_GPP_G_PAD_MAX,
+ R_PCH_LP_PCR_GPIO_GPP_G_PADCFG_OFFSET,
+ R_PCH_LP_PCR_GPIO_GPP_G_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_G_PAD_OWN,
+ R_PCH_LP_PCR_GPIO_GPP_G_GPI_GPE_STS
+ },
+ Package(){ // GPD
+ PCH_GPIO_COM2,
+ V_PCH_GPIO_GPD_PAD_MAX,
+ R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPD_HOSTSW_OWN,
+ R_PCH_LP_PCR_GPIO_GPD_PAD_OWN,
+ R_PCH_PCR_GPIO_GPD_GPI_GPE_STS
+ }
+ })
+
+ //
+ // GPIO information data structure for PCH-H
+ //
+ Name(GPCH, Package(){
+ Package(){ // GPP_A
+ PCH_GPIO_COM0,
+ V_PCH_GPIO_GPP_A_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_A_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS
+ },
+ Package(){ // GPP_B
+ PCH_GPIO_COM0,
+ V_PCH_GPIO_GPP_B_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_B_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS
+ },
+ Package(){ // GPP_C
+ PCH_GPIO_COM1,
+ V_PCH_GPIO_GPP_C_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_C_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS
+ },
+ Package(){ // GPP_D
+ PCH_GPIO_COM1,
+ V_PCH_GPIO_GPP_D_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_D_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS
+ },
+ Package(){ // GPP_E
+ PCH_GPIO_COM1,
+ V_PCH_H_GPIO_GPP_E_PAD_MAX,
+ R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_E_PAD_OWN,
+ R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS
+ },
+ Package(){ // GPP_F
+ PCH_GPIO_COM1,
+ V_PCH_GPIO_GPP_F_PAD_MAX,
+ R_PCH_H_PCR_GPIO_GPP_F_PADCFG_OFFSET,
+ R_PCH_H_PCR_GPIO_GPP_F_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_F_PAD_OWN,
+ R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_STS
+ },
+ Package(){ // GPP_G
+ PCH_GPIO_COM1,
+ V_PCH_H_GPIO_GPP_G_PAD_MAX,
+ R_PCH_H_PCR_GPIO_GPP_G_PADCFG_OFFSET,
+ R_PCH_H_PCR_GPIO_GPP_G_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_G_PAD_OWN,
+ R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_STS
+ },
+ Package(){ // GPP_H
+ PCH_GPIO_COM1,
+ V_PCH_H_GPIO_GPP_H_PAD_MAX,
+ R_PCH_H_PCR_GPIO_GPP_H_PADCFG_OFFSET,
+ R_PCH_H_PCR_GPIO_GPP_H_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_H_PAD_OWN,
+ R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_STS
+ },
+ Package(){ // GPP_I
+ PCH_GPIO_COM3,
+ V_PCH_H_GPIO_GPP_I_PAD_MAX,
+ R_PCH_H_PCR_GPIO_GPP_I_PADCFG_OFFSET,
+ R_PCH_H_PCR_GPIO_GPP_I_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPP_I_PAD_OWN,
+ R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_STS
+ },
+ Package(){ // GPD
+ PCH_GPIO_COM2,
+ V_PCH_GPIO_GPD_PAD_MAX,
+ R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET,
+ R_PCH_PCR_GPIO_GPD_HOSTSW_OWN,
+ R_PCH_H_PCR_GPIO_GPD_PAD_OWN,
+ R_PCH_PCR_GPIO_GPD_GPI_GPE_STS
+ }
+ })
+
+ //
+ // Object for storing RX Level/Edge Configuration for all pads.
+ // One fields contains data for one pad.
+ // 00b = Level
+ // 01b = Edge (RxInv=0 for rising edge; 1 for falling edge)
+ // 10b = Disabled
+ // 11b = Either rising edge or falling edge
+ //
+ // Each row has data for one group. Buffer size needs
+ // to equal to number of pads
+ Name(RXEV, Package(){
+ Buffer(V_PCH_GPIO_GPP_A_PAD_MAX){}, // GPP_A
+ Buffer(V_PCH_GPIO_GPP_B_PAD_MAX){}, // GPP_B
+ Buffer(V_PCH_GPIO_GPP_C_PAD_MAX){}, // GPP_C
+ Buffer(V_PCH_GPIO_GPP_D_PAD_MAX){}, // GPP_D
+ Buffer(V_PCH_GPIO_GPP_E_PAD_MAX){}, // GPP_E
+ Buffer(V_PCH_GPIO_GPP_F_PAD_MAX){}, // GPP_F
+ Buffer(V_PCH_GPIO_GPP_G_PAD_MAX){}, // GPP_G
+ Buffer(V_PCH_H_GPIO_GPP_H_PAD_MAX){}, // PCH-H GPP_H, PCH-LP GPD
+ Buffer(V_PCH_H_GPIO_GPP_I_PAD_MAX){}, // PCH-H GPP_I, PCH-LP not used
+ Buffer(V_PCH_GPIO_GPD_PAD_MAX){} // PCH-H GPD, PCH-LP not used
+ })
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/IrqLink.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/IrqLink.asl
new file mode 100644
index 0000000000..51d88f1e5a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/IrqLink.asl
@@ -0,0 +1,616 @@
+/** @file
+ ACPI DSDT table
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+
+
+// Use this information when determining the Possible IRQs that can be
+// used in a given system.
+//
+// The following IRQs are always in use by legacy devices:
+// 0 = System Timer
+// 2 = 8259 PIC
+// 8 = RTC
+// 9 = SCI Interrupt (It may be used, we choose not to)
+// 13 = Co-processor Error
+//
+// The following may be in use by legacy devices:
+// 1 = If using PS/2 Keyboard
+// 3 = If COMx Port Enabled and IRQ = 3
+// 4 = If COMx Port Enabled and IRQ = 4
+// 5 = If LPT Port Enabled and IRQ = 5
+// 6 = If FDC Enabled
+// 7 = If LPT Port Enabled and IRQ = 7
+// 12 = If using PS/2 Mouse
+// 14 = Primary IDE (If populated and in Compatibility Mode)
+// 15 = Secondary IDE (If populated and in Compatibility Mode)
+//
+// The following will never be in use by legacy devices:
+// 10 = Assign to PARC, PCRC, PERC, PGRC
+// 11 = Assign to PBRC, PDRC, PFRC, PHRC
+
+Device(LNKA) // PARC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F")) // PCI Interrupt Link Device
+
+ Name(_UID,1) // Unique to other Link Devices
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PARC,0x80,\_SB.PARC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSA)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLA,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLA,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PARC,0x0F),IRQ0)
+
+ Return(RTLA)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PARC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PARC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKB) // PBRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,2)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PBRC,0x80,\_SB.PBRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSB)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLB,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLB,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PBRC,0x0F),IRQ0)
+
+ Return(RTLB)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PBRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PBRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKC) // PCRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,3)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PCRC,0x80,\_SB.PCRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSC)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLC,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLC,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PCRC,0x0F),IRQ0)
+
+ Return(RTLC)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PCRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PCRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKD) // PDRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,4)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PDRC,0x80,\_SB.PDRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSD)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLD,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLD,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PDRC,0x0F),IRQ0)
+
+ Return(RTLD)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PDRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PDRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKE) // PERC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,5)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PERC,0x80,\_SB.PERC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSE)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLE,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLE,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PERC,0x0F),IRQ0)
+
+ Return(RTLE)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PERC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PERC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKF) // PFRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,6)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PFRC,0x80,\_SB.PFRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSF)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLF,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLF,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PFRC,0x0F),IRQ0)
+
+ Return(RTLF)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PFRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PFRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKG) // PGRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,7)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PGRC,0x80,\_SB.PGRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSG)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLG,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLG,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PGRC,0x0F),IRQ0)
+
+ Return(RTLG)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PGRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PGRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
+
+Device(LNKH) // PHRC Routing Resource
+{
+ Name(_HID,EISAID("PNP0C0F"))
+
+ Name(_UID,8)
+
+ // Disable the PCI IRQ.
+
+ Method(_DIS,0,Serialized)
+ {
+ Or(\_SB.PHRC,0x80,\_SB.PHRC)
+ }
+
+ // Possible IRQ Resource Setting.
+
+ Method (_PRS, 0, Serialized)
+ {
+ return (PRSH)
+ }
+
+ // Current IRQ Resource Setting.
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(RTLH,ResourceTemplate()
+ {
+ IRQ(Level,ActiveLow,Shared) {}
+ })
+
+ // Point to specific byte.
+
+ CreateWordField(RTLH,1,IRQ0)
+
+ // Zero out IRQ mask bits 0-15
+
+ Store(Zero,IRQ0)
+
+ ShiftLeft(1,And(\_SB.PHRC,0x0F),IRQ0)
+
+ Return(RTLH)
+ }
+
+ // Set IRQ Resource Setting.
+
+ Method(_SRS,1,Serialized)
+ {
+ // Point to the specific byte passed in.
+
+ CreateWordField(Arg0,1,IRQ0)
+
+ // Determine the IRQ bit to set and store it,
+
+ FindSetRightBit(IRQ0,Local0)
+ Decrement(Local0)
+ Store(Local0,\_SB.PHRC)
+ }
+
+ // PCI IRQ Status.
+
+ Method(_STA,0,Serialized)
+ {
+ If(And(\_SB.PHRC,0x80))
+ {
+ Return(0x0009)
+ }
+ Else
+ {
+ Return(0x000B)
+ }
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/Pch.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/Pch.asl
new file mode 100644
index 0000000000..34f3f6877f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/Pch.asl
@@ -0,0 +1,1156 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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 <PchAccess.h>
+
+Name (PNVB, 0xFFFF0000) // PCH NVS Base address
+Name (PNVL, 0xAA55) // PCH NVS Length
+Include ("PchNvs.asl")
+
+//
+// Include GPIO macros and access library
+//
+include("GpioAcpiDefines.h")
+include("GpioLib.asl")
+
+//
+// Trace Hub debug library
+// Include it earlier so the debug function can be used as soon as possible
+//
+Include ("TraceHubDebug.asl")
+
+Name(SPTH,1)
+Name(SPTL,2)
+Method(PCHV) {
+ If(LEqual(PCHS, 1)) { Return (SPTH) } // series=H -> SPT-H
+ If(LEqual(PCHS, 2)) { Return (SPTL) } // series=LP -> SPT-LP
+ Return (0)
+}
+
+//
+// This PME event (PCH's GPE 6Dh) is received when any PCH internal device with
+// PCI Power Management capabilities on bus 0 asserts the equivalent of the PME# signal.
+//
+Scope(\_GPE) {
+ Method(_L6D, 0, Serialized) {
+ \_SB.PCI0.XHC.GPEH()
+ \_SB.PCI0.HDAS.GPEH()
+ \_SB.PCI0.GLAN.GPEH()
+ \_SB.PCI0.XDCI.GPEH()
+ }
+}
+
+Scope (\_SB.PCI0) {
+
+ Name(TEMP,0) // scratch variable that does not cause compiler warnings as writes to Localx variables do.
+
+ //
+ // PCH reserved resource
+ //
+ Device(PRRE) {
+ Name(_HID,EISAID("PNP0C02")) // motherboard resource
+ Name(_UID,"PCHRESV")
+ Name(_STA,0x3) // device present and decodes its resources, but not to be displayed in OSPM
+
+ Method(_CRS,0,Serialized)
+ {
+ Name(BUF0,ResourceTemplate(){
+ //
+ // PCH RESERVED MMIO RANGE
+ // 0xFD000000 to 0xFE7FFFFF
+ // to skip over address range that might be claimed by the GPIO, Intel Serial IO, Thermal, TraceHub and CIO2 devices
+ // need to split this into 5 ranges
+ // The GPIO COMM0,1,3 and SerialIO ranges will be handled by SIRC device.
+ //
+ Memory32Fixed(ReadWrite,0xFD000000,0x00AC0000) // 0xFD000000 - 0xFDABFFFF
+ // Skip 0xFDAC0000 - 0xFDACFFFF for GPIO_COMM3
+ Memory32Fixed(ReadWrite,0xFDAD0000,0x00010000) // 0xFDAD0000 - 0xFDADFFFF, only cover GPIO_COMM2 range
+ // Skip 0xFDAE0000 - 0xFDAFFFFF for GPIO_COMM0 and GPIO_COMM1
+ Memory32Fixed(ReadWrite,0xFDB00000,0x00500000) // 0xFDB00000 - 0xFDFFFFFF
+ Memory32Fixed(ReadWrite,0xFE000000,0x00020000) // 0xFE000000 - 0xFE01FFFF
+ // Skip 0xFE020000 - 0xFE035FFF for Serial IO
+ Memory32Fixed(ReadWrite,0xFE036000,0x00006000) // 0xFE036000 - 0xFE03BFFF
+ // Skip 0xFE03C000 - 0xFE03CFFF for Thermal Device in ACPI mode
+ Memory32Fixed(ReadWrite,0xFE03D000,0x003C3000) // 0xFE03D000 - 0xFE3FFFFF
+ // Skip 0xFE400000 - 0xFE40FFFF for CIO2 in ACPI mode
+ Memory32Fixed(ReadWrite,0xFE410000,0x003F0000) // 0xFE410000 - 0xFE7FFFFF
+ })
+ Return(BUF0)
+ }
+ }
+ Device(IOTR) {
+ //
+ // This device claims IO range reserved for IO traps
+ // to prevent OS from reusing it for other purposes
+ //
+ Name(_HID,EISAID("PNP0C02"))
+ Name(_UID,"IoTraps")
+ Method(_CRS) {
+ Store(ResourceTemplate() { }, Local0)
+ Name(BUF0,ResourceTemplate(){ Io(Decode16,0x0,0x0,0x1,0xFF,TAG0) })
+ Name(BUF1,ResourceTemplate(){ Io(Decode16,0x0,0x0,0x1,0xFF,TAG1) })
+ Name(BUF2,ResourceTemplate(){ Io(Decode16,0x0,0x0,0x1,0xFF,TAG2) })
+ Name(BUF3,ResourceTemplate(){ Io(Decode16,0x0,0x0,0x1,0xFF,TAG3) })
+ CreateWordField(BUF0,TAG0._MIN,AMI0);CreateWordField(BUF0,TAG0._MAX,AMA0)
+ CreateWordField(BUF1,TAG1._MIN,AMI1);CreateWordField(BUF1,TAG1._MAX,AMA1)
+ CreateWordField(BUF2,TAG2._MIN,AMI2);CreateWordField(BUF2,TAG2._MAX,AMA2)
+ CreateWordField(BUF3,TAG3._MIN,AMI3);CreateWordField(BUF3,TAG3._MAX,AMA3)
+ Store(ITA0,AMI0);Store(ITA0,AMA0)
+ Store(ITA1,AMI1);Store(ITA1,AMA1)
+ Store(ITA2,AMI2);Store(ITA2,AMA2)
+ Store(ITA3,AMI3);Store(ITA3,AMA3)
+ // Win7 can't store result of ConcatenateResTemplate directly into one of its input parameters
+ if(LEqual(ITS0,1)) { ConcatenateResTemplate(Local0, BUF0, Local1); Store(Local1, Local0) }
+ if(LEqual(ITS1,1)) { ConcatenateResTemplate(Local0, BUF1, Local1); Store(Local1, Local0) }
+ if(LEqual(ITS2,1)) { ConcatenateResTemplate(Local0, BUF2, Local1); Store(Local1, Local0) }
+ if(LEqual(ITS3,1)) { ConcatenateResTemplate(Local0, BUF3, Local1); Store(Local1, Local0) }
+ return (Local0)
+ }
+ }
+
+
+ //
+ // LPC Bridge - Device 31, Function 0, this is only for PCH register Memory Region declare,
+ // it's better to be declared as early as possible since it's widely used in whole ACPI name space.
+ // Please add any code which needs to reference any register of it after this
+ //
+ Device(LPCB) {
+ Name(_ADR, 0x001F0000)
+ Method(_DSM,4,serialized){if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+
+ OperationRegion(LPC, PCI_Config, 0x00, 0x100)
+ Field(LPC, AnyAcc, NoLock, Preserve)
+ {
+ Offset(0x02),
+ CDID, 16,
+ Offset(0x08),
+ CRID, 8,
+ Offset(R_PCH_LPC_IOD), // 0x80
+ IOD0, 8,
+ IOD1, 8,
+ Offset(0xA0),
+ , 9,
+ PRBL, 1,
+ Offset(R_PCH_LPC_BC), // 0xDC
+ , 2,
+ ESPI, 1,
+ }
+ }
+
+ //
+ // PCH Power Management Controller
+ //
+ Device(PPMC) {
+ Name(_ADR, 0x001F0002)
+ Method(_DSM,4,serialized){if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ //
+ // SMBus Controller - Device 31, Function 4
+ //
+ Device(SBUS) {
+ Name(_ADR,0x001F0004)
+ Method(_DSM,4,serialized){if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+}
+
+scope(\_SB) {
+ Include ("IrqLink.asl")
+}
+
+Scope(\)
+{
+ //
+ // PCR Register Access Methods
+ //
+ // PCR Dword Read
+ // arg0: PID
+ // arg1: Offset
+ //
+ Method (PCRR, 2, Serialized) {
+ Add (ShiftLeft (arg0, 16), arg1, Local0)
+ Add (SBRG, Local0, Local0)
+ OperationRegion (PCR0, SystemMemory, Local0, 0x4)
+ Field(PCR0,DWordAcc,Lock,Preserve) {
+ Offset(0x00),
+ DAT0, 32
+ } // End Field PCR0
+ Return (DAT0)
+ } // End Method PCRR
+
+ //
+ // PCR Dword Write
+ // arg0: PID
+ // arg1: Offset
+ // arg2: write data
+ //
+ Method (PCRW, 3, Serialized) {
+ Add (ShiftLeft (arg0, 16), arg1, Local0)
+ Add (SBRG, Local0, Local0)
+ OperationRegion (PCR0, SystemMemory, Local0, 0x4)
+ Field(PCR0,DWordAcc,Lock,Preserve) {
+ Offset(0x00),
+ DAT0, 32
+ } // End Field PCR0
+ Store (arg2, DAT0)
+ // read back for PCR back to back limitation
+ Store (PCRR (PID_LPC, R_PCH_PCR_RTC_RTCDCG), local0)
+ } // End Method PCRW
+
+ //
+ // PCR Dword Or
+ // arg0: PID
+ // arg1: Offset
+ // arg2: Or data
+ //
+ Method (PCRO, 3, Serialized) {
+ Store(PCRR(arg0,arg1),Local0) // Store PCR Read data in Local0
+ Store(Or(Local0,arg2),Local1) // Or data
+ PCRW(arg0,arg1,Local1) // Write data back
+ }
+
+ //
+ // PCR Dword And
+ // arg0: PID
+ // arg1: Offset
+ // arg2: And data
+ //
+ Method (PCRA, 3, Serialized) {
+ Store(PCRR(arg0,arg1),Local0) // Store PCR Read data in Local0
+ Store(And(Local0,arg2),Local1) // And data
+ PCRW(arg0,arg1,Local1) // Write data back
+ }
+
+ //
+ // PCR Dword AndThenOr
+ // arg0: PID
+ // arg1: Offset
+ // arg2: And data
+ // arg3: Or data
+ //
+ Method (PCAO, 4, Serialized) {
+ Store(PCRR(arg0,arg1),Local0) // Store PCR Read data in Local0
+ Store(Or(And(Local0,arg2),arg3),Local1) // AndThenOr
+ PCRW(arg0,arg1,Local1) // Write data back
+ }
+
+ Name (TCBV, 0) // TCO I/O base address value
+ Method (TCBS, 0) {
+ If (LEqual(TCBV, 0)) {
+ // PCR[DMI] + 2778h[15:5]
+ Store(PCRR (PID_DMI, R_PCH_PCR_DMI_TCOBASE),Local0)
+ And(Local0,B_PCH_PCR_DMI_TCOBASE_TCOBA,TCBV)
+ }
+ Return (TCBV)
+ }
+
+ //
+ // Define PCH ACPIBASE I/O as an ACPI operating region. The base address
+ // can be found in Device 31, Function 2, Offset 40h.
+ //
+ OperationRegion(PMIO, SystemIo, PMBS, 0x60)
+ Field(PMIO, ByteAcc, NoLock, Preserve) {
+ , 8,
+ PBSS, 1, // Power Button Status
+ Offset(R_PCH_ACPI_GPE_CNTL), // 0x40, General Purpose Event Control
+ , 17,
+ GPEC, 1 // Software GPE Control
+ }
+
+ //
+ // Define PCH TCOBASE I/O
+ //
+ OperationRegion(TCBA, SystemIo, TCBS, 0x10)
+ Field(TCBA, ByteAcc, NoLock, Preserve) {
+ Offset(R_PCH_TCO1_STS), // 0x04
+ , 9,
+ CPSC, 1, // CPUSCI_STS
+ }
+
+ //
+ // PWRM register definitions
+ //
+ OperationRegion(PWMR, SystemMemory, \PWRM, 0x800)
+ Field(PWMR, AnyAcc, NoLock, Preserve) {
+ Offset(R_PCH_PWRM_CFG3), // 0xE0
+ , 16,
+ DWLE, 1, // Deep-Sx WLAN Phy Power Enable
+ HWLE, 1, // Host Wireless LAN Phy Power Enable
+ Offset(R_PCH_PWRM_31C), // 0x31C
+ , 13,
+ SLS0, 1, // SLP_S0# Low Voltage Mode Enable (SLPS0LVEN)
+ , 8,
+ XSQD, 1, // 24MHz Crystal Shutdown Qualification Disable (XTALSDQDIS)
+ }
+
+ //
+ //
+ OperationRegion(PMST, SystemMemory, PWRM, 0x80)
+ Field(PMST, DWordAcc, NoLock, Preserve) {
+ Offset(R_PCH_PWRM_CFG), // 0x18, Power Management Configuration Reg 1 (PM_CFG)
+ , 25, //
+ USBP, 1, // Allow USB2 PHY Core Power Gating (ALLOW_USB2_CORE_PG)
+ Offset(R_PCH_PWRM_PCH_PM_STS), // 0x1C, PCH Power Management Status (PCH_PM_STS)
+ , 24, //
+ PMFS, 1, // PMC Message Full Status (PMC_MSG_FULL_STS)
+ Offset(R_PCH_PWRM_MTPMC), // 0x20, Message to PMC (MTPMC)
+ MPMC, 32, // Message to PMC (MTPMC)
+ Offset(R_PCH_PWRM_PCH_PM_STS2), // 0x24, PCH Power Management Status (PCH_PM_STS2)
+ , 20, //
+ UWAB, 1, // USB2 Workaround Available Bit
+ }
+
+} //end Scope(\)
+
+Scope (\_SB.PCI0) {
+ Name(LTRZ, 0)
+ Name(OBFZ, 0)
+
+ Name(LMSL, 0)
+ Name(LNSL, 0)
+
+ //
+ // LAN Controller - Device 31, Function 6
+ //
+ Device(GLAN) { // GbE Controller
+ Name(_ADR, 0x001F0006)
+ Method(_DSM,4,serialized){if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ OperationRegion(GLBA, PCI_Config, 0,0x100)
+ Field(GLBA,AnyAcc,NoLock,Preserve)
+ {
+ DVID, 16
+ }
+ //
+ // Byte access for PMCS field to avoid race condition on device D-state
+ //
+ Field(GLBA,ByteAcc,NoLock,Preserve)
+ {
+ Offset(R_PCH_LAN_PMCS), // 0xCC
+ , 8,
+ PMEE, 1, // PME Enable
+ , 6,
+ PMES, 1 // PME Status
+ }
+
+ Method(_PRW, 0) { Return(GPRW(0x6D, 4)) } // can wakeup from S4 state
+
+ Method(_DSW, 3)
+ {
+ Store(Arg0, PMEE)
+ }
+
+ //
+ // GPE handler for GbE, this is part of _Lxx handler for bus 0 PME
+ //
+ Method(GPEH)
+ {
+ If(LEqual(DVID, 0xFFFF)) {
+ Return()
+ }
+ If(LAnd(PMEE, PMES)) {
+ Store(1, PMES) // clear PME Status
+ Notify(GLAN, 0x02)
+ }
+ }
+ } // end "GbE Controller"
+
+} //scope
+
+//
+// xHCI Controller - Device 20, Function 0
+//
+Include("PchXhci.asl")
+
+//
+// xDCI (OTG) Controller - Device 20, Function 1
+//
+include("PchXdci.asl")
+
+Scope(\_SB_.PCI0) {
+ //
+ // High Definition Audio Controller - Device 31, Function 3
+ //
+ include("PchHda.asl")
+
+ //
+ // PCIE Root Port #01
+ //
+ Device(RP01) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA1,0)) {
+ Return (RPA1)
+ } Else {
+ Return (0x001C0000)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR1, LTRZ)
+ Store (PML1, LMSL)
+ Store (PNL1, LNSL)
+ Store (OBF1, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #01"
+
+ //
+ // PCIE Root Port #02
+ //
+ Device(RP02) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA2,0)) {
+ Return (RPA2)
+ } Else {
+ Return (0x001C0001)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR2, LTRZ)
+ Store (PML2, LMSL)
+ Store (PNL2, LNSL)
+ Store (OBF2, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #02"
+
+ //
+ // PCIE Root Port #03
+ //
+ Device(RP03) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA3,0)) {
+ Return (RPA3)
+ } Else {
+ Return (0x001C0002)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR3, LTRZ)
+ Store (PML3, LMSL)
+ Store (PNL3, LNSL)
+ Store (OBF3, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) }// APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #03"
+
+ //
+ // PCIE Root Port #04
+ //
+ Device(RP04) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA4,0)) {
+ Return (RPA4)
+ } Else {
+ Return (0x001C0003)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR4, LTRZ)
+ Store (PML4, LMSL)
+ Store (PNL4, LNSL)
+ Store (OBF4, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #04"
+
+ //
+ // PCIE Root Port #05
+ //
+ Device(RP05) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA5,0)) {
+ Return (RPA5)
+ } Else {
+ Return (0x001C0004)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR5, LTRZ)
+ Store (PML5, LMSL)
+ Store (PNL5, LNSL)
+ Store (OBF5, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #05"
+
+ //
+ // PCIE Root Port #06
+ //
+ Device(RP06) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA6,0)) {
+ Return (RPA6)
+ } Else {
+ Return (0x001C0005)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR6, LTRZ)
+ Store (PML6, LMSL)
+ Store (PNL6, LNSL)
+ Store (OBF6, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #06"
+
+ //
+ // PCIE Root Port #07
+ //
+ Device(RP07) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA7,0)) {
+ Return (RPA7)
+ } Else {
+ Return (0x001C0006)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR7, LTRZ)
+ Store (PML7, LMSL)
+ Store (PNL7, LNSL)
+ Store (OBF7, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) } // APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #07"
+
+ //
+ // PCIE Root Port #08
+ //
+ Device(RP08) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA8,0)) {
+ Return (RPA8)
+ } Else {
+ Return (0x001C0007)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR8, LTRZ)
+ Store (PML8, LMSL)
+ Store (PNL8, LNSL)
+ Store (OBF8, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #08"
+
+ //
+ // PCIE Root Port #09
+ //
+ Device(RP09) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPA9,0)) {
+ Return (RPA9)
+ } Else {
+ Return (0x001D0000)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTR9, LTRZ)
+ Store (PML9, LMSL)
+ Store (PNL9, LNSL)
+ Store (OBF9, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #09"
+
+ //
+ // PCIE Root Port #10
+ //
+ Device(RP10) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAA,0)) {
+ Return (RPAA)
+ } Else {
+ Return (0x001D0001)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRA, LTRZ)
+ Store (PMLA, LMSL)
+ Store (PNLA, LNSL)
+ Store (OBFA, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #10"
+
+ //
+ // PCIE Root Port #11
+ //
+ Device(RP11) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAB,0)) {
+ Return (RPAB)
+ } Else {
+ Return (0x001D0002)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRB, LTRZ)
+ Store (PMLB, LMSL)
+ Store (PNLB, LNSL)
+ Store (OBFB, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) }// APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #11"
+
+ //
+ // PCIE Root Port #12
+ //
+ Device(RP12) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAC,0)) {
+ Return (RPAC)
+ } Else {
+ Return (0x001D0003)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRC, LTRZ)
+ Store (PMLC, LMSL)
+ Store (PNLC, LNSL)
+ Store (OBFC, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #12"
+
+ //
+ // PCIE Root Port #13
+ //
+ Device(RP13) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAD,0)) {
+ Return (RPAD)
+ } Else {
+ Return (0x001D0004)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRD, LTRZ)
+ Store (PMLD, LMSL)
+ Store (PNLD, LNSL)
+ Store (OBFD, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #13"
+
+ //
+ // PCIE Root Port #14
+ //
+ Device(RP14) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAE,0)) {
+ Return (RPAE)
+ } Else {
+ Return (0x001D0005)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRE, LTRZ)
+ Store (PMLE, LMSL)
+ Store (PNLE, LNSL)
+ Store (OBFE, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #14"
+
+ //
+ // PCIE Root Port #15
+ //
+ Device(RP15) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAF,0)) {
+ Return (RPAF)
+ } Else {
+ Return (0x001D0006)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRF, LTRZ)
+ Store (PMLF, LMSL)
+ Store (PNLF, LNSL)
+ Store (OBFF, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) }// APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #15"
+
+ //
+ // PCIE Root Port #16
+ //
+ Device(RP16) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAG,0)) {
+ Return (RPAG)
+ } Else {
+ Return (0x001D0007)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRG, LTRZ)
+ Store (PMLG, LMSL)
+ Store (PNLG, LNSL)
+ Store (OBFG, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #16"
+
+ //
+ // PCIE Root Port #17
+ //
+ Device(RP17) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAH,0)) {
+ Return (RPAH)
+ } Else {
+ Return (0x001B0000)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRH, LTRZ)
+ Store (PMLH, LMSL)
+ Store (PNLH, LNSL)
+ Store (OBFH, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #17"
+
+ //
+ // PCIE Root Port #18
+ //
+ Device(RP18) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAI,0)) {
+ Return (RPAI)
+ } Else {
+ Return (0x001B0001)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRI, LTRZ)
+ Store (PMLI, LMSL)
+ Store (PNLI, LNSL)
+ Store (OBFI, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #18"
+
+ //
+ // PCIE Root Port #19
+ //
+ Device(RP19) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAJ,0)) {
+ Return (RPAJ)
+ } Else {
+ Return (0x001B0002)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRJ, LTRZ)
+ Store (PMLJ, LMSL)
+ Store (PNLJ, LNSL)
+ Store (OBFJ, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) }// APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #19"
+
+ //
+ // PCIE Root Port #20
+ //
+ Device(RP20) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAK,0)) {
+ Return (RPAK)
+ } Else {
+ Return (0x001B0003)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRK, LTRZ)
+ Store (PMLK, LMSL)
+ Store (PNLK, LNSL)
+ Store (OBFK, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #20"
+
+ //
+ // PCIE Root Port #21
+ //
+ Device(RP21) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAL,0)) {
+ Return (RPAL)
+ } Else {
+ Return (0x001B0004)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRL, LTRZ)
+ Store (PMLL, LMSL)
+ Store (PNLL, LNSL)
+ Store (OBFL, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR04) }// APIC mode
+ Return (PR04) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #21"
+
+ //
+ // PCIE Root Port #21
+ //
+ Device(RP22) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAM,0)) {
+ Return (RPAM)
+ } Else {
+ Return (0x001B0005)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRM, LTRZ)
+ Store (PMLM, LMSL)
+ Store (PNLM, LNSL)
+ Store (OBFM, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR05) }// APIC mode
+ Return (PR05) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #22"
+
+ //
+ // PCIE Root Port #22
+ //
+ Device(RP23) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAN,0)) {
+ Return (RPAN)
+ } Else {
+ Return (0x001B0006)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRN, LTRZ)
+ Store (PMLN, LMSL)
+ Store (PNLN, LNSL)
+ Store (OBFN, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR06) }// APIC mode
+ Return (PR06) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #23"
+
+ //
+ // PCIE Root Port #21
+ //
+ Device(RP24) {
+ Method (_ADR, 0) {
+ If (LNotEqual(RPAO,0)) {
+ Return (RPAO)
+ } Else {
+ Return (0x001B0007)
+ }
+ }
+ //
+ // Pass LTRx to LTRZ so PchPcie.asl can be reused for PCIes.
+ //
+ Method(_INI)
+ {
+ Store (LTRO, LTRZ)
+ Store (PMLO, LMSL)
+ Store (PNLO, LNSL)
+ Store (OBFO, OBFZ)
+ }
+ Include("PchPcie.asl")
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ Method(_PRT, 0) {
+ If(PICM) { Return(AR07) }// APIC mode
+ Return (PR07) // PIC Mode
+ } // end _PRT
+ } // end "PCIE Root Port #24"
+
+ //
+ // Serial ATA Host Controller - Device 31, Function 2
+ //
+ Include ("PchSata.asl")
+
+ //
+ // CIO2 ACPI device - Device 20, Function 3
+ //
+ Device (CIO2) {
+ Method (_STA) {
+ If (LEqual(CIOE,1)){ Return (0x0F) }
+ Else { Return (0x00) }
+ }
+ Name(_HID, "INT343E")
+ Method(_CRS, 0, NotSerialized) {
+ Name(CBUF, ResourceTemplate () {
+ Interrupt(ResourceConsumer, Level, ActiveLow, Shared,,,CIOD) {0x10}
+ Memory32Fixed (ReadWrite, PCH_CIO2_BASE_ADDRESS, PCH_CIO2_MMIO_SIZE)
+ })
+ CreateDWordField(CBUF,CIOD._INT,CIOV)
+ Store(CIOI, CIOV)
+ Return (CBUF)
+ }
+ }
+
+ //
+ // Thermal Device
+ //
+ Device(TERM) {
+ Name (_HID, "INT343D")
+ Name (_UID, 1)
+
+ Method (_CRS, 0x0, NotSerialized) {
+ Name (RBUF, ResourceTemplate () {
+ Memory32Fixed (ReadWrite, PCH_THERMAL_BASE_ADDRESS, PCH_THERMAL_MMIO_SIZE, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , IRQ) { 18 }
+ })
+
+ CreateDWordField(RBUF,IRQ._INT,IRQN)
+
+ Store(TIRQ, IRQN)
+
+ Return (RBUF)
+ }
+
+ Method (_STA, 0x0, NotSerialized)
+ {
+ If(LEqual(TAEN, 0)) { Return(0x0) } // device not enabled in ACPI mode
+ If(LEqual(TIRQ, 0)) { Return(0x0) } // IRQ number not updated
+ Return(0xF)
+ }
+ }
+}
+
+
+//
+// Serial IO Controllers definitions
+//
+#define SERIAL_SCOPE \_SB.PCI0
+Include ("PchSerialIo.asl")
+
+//
+// Storage and Communication Subsystems definitions
+//
+Include ("PchScs.asl")
+
+//
+// Integrated Sensor Hub definition
+//
+Include ("PchIsh.asl")
+
+//
+// MEI 1 definition
+//
+Include ("PchHeci.asl")
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchAcpiTables.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchAcpiTables.inf
new file mode 100644
index 0000000000..ec99fb847a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchAcpiTables.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for the PCH ACPI tables
+#
+# Copyright (c) 2017, 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 = PchAcpiTables
+FILE_GUID = 31401EE7-1600-437c-A11C-B1035D8E6070
+MODULE_TYPE = USER_DEFINED
+VERSION_STRING = 1.0
+
+[Sources]
+ Pch.asl
+ PchNvs.asl
+ PchHda.asl
+ PchSerialIo.asl
+ PchPcie.asl
+ PchSata.asl
+ PchRstPcieStorage.asl
+ UsbSbd.asl
+ PchXhci.asl
+ PchXdci.asl
+ IrqLink.asl
+ GpioLib.asl
+ TraceHubDebug.asl
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHda.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHda.asl
new file mode 100644
index 0000000000..151ee1fdd8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHda.asl
@@ -0,0 +1,213 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+External(\_SB.PCI0.HDAS.PS0X, MethodObj)
+External(\_SB.PCI0.HDAS.PS3X, MethodObj)
+External(\_SB.PCI0.HDAS.PPMS, MethodObj)
+External(HIDW, MethodObj)
+External(HIWC, MethodObj)
+
+//
+// High Definition Audio Controller - Device 31, Function 3
+//
+Device(HDAS)
+{
+ Name(_ADR, 0x001F0003)
+
+ //
+ // Define a Memory Region that will allow access to the HDA PCI Configuration Space
+ //
+ OperationRegion(HDAR, PCI_Config, 0x00, 0x100)
+ Field(HDAR,WordAcc,NoLock,Preserve) {
+ VDID,32 // 0x00, VID DID
+ }
+ //
+ // Byte access for PMCS field to avoid race condition on device D-state
+ //
+ Field(HDAR,ByteAcc,NoLock,Preserve) {
+ Offset(R_PCH_HDA_PCS), // 0x54, Power Management Control and Status Register
+ ,8,
+ PMEE,1, // PME Enable
+ ,6,
+ PMES,1 // PME Status
+ }
+
+ Name(_S0W, 3) // Device can wake itself from D3 in S0
+
+ Method(_DSW, 3) { Store(Arg0, PMEE) } // Device wake enable
+
+ Method(_PRW, 0) { Return(GPRW(0x6D, 4)) } // Can wakeup from S4 state
+
+ // GPE handler for HDA, this is part of _Lxx handler for bus 0 PME
+ Method(GPEH) {
+ If(LEqual(VDID, 0xFFFFFFFF)) {
+ Return()
+ }
+
+ If(LAnd(PMEE, PMES)) {
+ ADBG("HDAS GPEH")
+ Store(1, PMES) // clear PME Status
+ Notify(HDAS, 0x02)
+ }
+ }
+
+ // D0 Method for HD-A Controller
+ Method(_PS0, 0, Serialized)
+ {
+
+
+ //
+ // Call platform HDAS PS0 method if present
+ //
+ If(CondRefOf(\_SB.PCI0.HDAS.PS0X)) {
+ \_SB.PCI0.HDAS.PS0X()
+ }
+ }
+
+ // D3 Method for HD-A Controller
+ Method(_PS3, 0, Serialized)
+ {
+
+
+ //
+ // Call platform HDAS PS3 method if present
+ //
+ If(CondRefOf(\_SB.PCI0.HDAS.PS3X)) {
+ \_SB.PCI0.HDAS.PS3X()
+ }
+ }
+
+ // NHLT Table memory descriptor, returned from _DSM
+ Name(NBUF, ResourceTemplate () {
+ // NHLT table address (_MIN = NHLT 64bit pointer, _MAX = _MIN + _LEN - 1) and length (_LEN)
+ QWordMemory (ResourceConsumer, , MinNotFixed, MaxNotFixed, NonCacheable, ReadOnly,
+ 0x1, // AddressGranularity
+ 0x0000000000000000, // AddressMinimum _MIN
+ 0x0000000000000000, // AddressMaximum _MAX
+ 0x0,
+ 0x0, // RangeLength _LEN
+ , , NHLT, AddressRangeACPI,)
+ })
+ Method(_INI) {
+ // Update resource according to NVS
+ ADBG("HDAS _INI")
+
+ // Set NHLT base address and length
+ CreateQWordField(NBUF, ^NHLT._MIN, NBAS)
+ CreateQWordField(NBUF, ^NHLT._MAX, NMAS)
+ CreateQWordField(NBUF, ^NHLT._LEN, NLEN)
+ Store(NHLA, NBAS)
+ Add(NHLA, Subtract(NHLL, 1), NMAS)
+ Store(NHLL, NLEN)
+
+ }
+
+ Method(_DSM, 0x4, NotSerialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+ // Arg0 - UUID: A69F886E-6CEB-4594-A41F-7B5DCE24C553 (Buffer)
+ // Arg1 - Revision ID: 0x01 (Integer)
+ // Arg2 - Function Index: 0x0 - 0x3 (Integer) - See below for details.
+ // Arg3 - Depends on Function Index - See below for details.
+ // Return - Depends on Function Index - See below for details.
+
+ ADBG("HDAS _DSM")
+
+ if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ // Verify UUID
+ If (LEqual(Arg0, ToUUID ("A69F886E-6CEB-4594-A41F-7B5DCE24C553"))) {
+
+ Switch(ToInteger(Arg2)) {
+
+ // Function 0: Function Support Query
+ // Arg2 - Function Index: 0x00 (Integer)
+ // Arg3: Unused
+ // Return: Bitmask of functions supported. (Buffer)
+ Case(0) {
+ // Supports function 0 - 3
+ Return(Buffer(One) { 0x0F })
+ }
+
+ // Function 1: Query Non HD Audio Descriptor Table
+ // Used by the Intel Offload Engine Driver to discover the
+ // non HD Audio devices supported by the Audio DSP.
+ // Arg2 - Function Index: 0x01 (Integer)
+ // Arg3 - Unused
+ // Return - ACPI Table describing the non HD Audio links and devices supported by the ADSP (ResourceBuffer)
+ Case(1) {
+ ADBG("_DSM Fun 1 NHLT")
+ // NBUF - Memory Resource Descriptor buffer with address and length of NHLT
+ Return(NBUF)
+ }
+
+ // Function 2: Query Feature Mask
+ // Used by the Intel Offload Engine Driver to retrieve a bitmask
+ // of features allowable on this platform.
+ // Arg2 - Function Index: 0x02 (Integer)
+ // Arg3: Unused
+ // Return: Bitmask of supported features.
+ Case (2) {
+ ADBG("_DSM Fun 2 FMSK")
+ // Bit 0 == '1', WoV is supported, Bit 0 == '0', WoV not supported
+ // Bit 1 == '1', BT Sideband is supported, Bit 1 == '0', BT not supported
+ // Bit 2 == '1', codec based VAD support allowable
+ // Bit 3 - 4 Reserved
+ // Bit 5 == '1', BT Intel HFP SCO is supported
+ // Bit 6 == '1', BT Intel A2DP is supported
+ // Bit 7 == '1', DSP based speech pre-processing disabled
+ // Bit 8 == '1', Windows Voice Activation, Bit 8 == '0', Intel Wake on Voice
+ // Bit 9 - 31 Reserved, shall be set to '0'
+ // ADFM - NVS AudioDSP Feature Bit Mask updated from PchPolicy
+ Return(ADFM)
+ }
+
+ // Function 3: Query Pre/Post Processing Module Support
+ // Used by the Intel Offload Engine Driver to determine if a
+ // specified PP Module is allowed to be supported on this platform
+ // Arg2 - Function Index: 0x03 (Integer)
+ // Arg3 - UUID: Specifies the UUID of the PP module to check (Buffer)
+ // Return - TRUE if PP Module supported, else FALSE.
+ Case (3) {
+ ADBG("_DSM Fun 3 PPMS")
+
+ If(CondRefOf(\_SB.PCI0.HDAS.PPMS)) {
+ // Call platform method PPMS to check if 3rd Party IP module with given GUID (Arg3) is supported
+ Return(\_SB.PCI0.HDAS.PPMS (Arg3))
+ }
+
+ Return(0) // Is not supported
+ }
+
+ Default {
+ // Function not supported (Arg2)
+ ADBG("_DSM Fun NOK")
+ Return(Buffer(One) { 0x00 })
+ }
+ } // Switch(Arg2) End
+ } // If(Arg0, UUID) End
+
+ //-------------------------------------------
+ // HID Wake up Event solution
+ //-------------------------------------------
+ If(CondRefOf(HIWC)) {
+ If(HIWC(Arg0)) {
+ If(CondRefOf(HIDW)) {
+ Return (HIDW(Arg0, Arg1, Arg2, Arg3))
+ }
+ }
+ }
+
+ // UUID not supported (Arg0)
+ ADBG("_DSM UUID NOK")
+ Return(Buffer() {0})
+ } // _DSM End
+} // end "High Definition Audio Controller"
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHeci.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHeci.asl
new file mode 100644
index 0000000000..c79ee8d6cd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchHeci.asl
@@ -0,0 +1,43 @@
+/**@file
+ ACPI DSDT table for MEI1
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+External(HIDW, MethodObj)
+External(HIWC, MethodObj)
+
+Scope(\_SB.PCI0) {
+ //
+ // Management Engine Interface 1 - Device 22, Function 0
+ //
+ Device(HECI) {
+ Name(_ADR, 0x00160000)
+
+ Method(_DSM, 0x4, NotSerialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+ if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ //-------------------------------------------
+ // HID Wake up Event solution
+ //-------------------------------------------
+ If(CondRefOf(HIWC)) {
+ If(HIWC(Arg0)) {
+ If(CondRefOf(HIDW)) {
+ Return (HIDW(Arg0, Arg1, Arg2, Arg3))
+ }
+ }
+ }
+
+ Return(Buffer() {0})
+ } // End _DSM
+ } // Device(HECI)
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchIsh.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchIsh.asl
new file mode 100644
index 0000000000..42f12ff266
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchIsh.asl
@@ -0,0 +1,42 @@
+/**@file
+ ACPI DSDT table for ISH
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+External(HIDW, MethodObj)
+External(HIWC, MethodObj)
+
+Scope(\_SB.PCI0) {
+ //
+ // Integrated Sensor Hub (PCI Mode) - Device 19, Function 0
+ //
+ Device(ISHD) {
+ Name(_ADR, 0x00130000)
+
+ Method(_DSM, 0x4, NotSerialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+ if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ //-------------------------------------------
+ // HID Wake up Event solution
+ //-------------------------------------------
+ If(CondRefOf(HIWC)) {
+ If(HIWC(Arg0)) {
+ If(CondRefOf(HIDW)) {
+ Return (HIDW(Arg0, Arg1, Arg2, Arg3))
+ }
+ }
+ }
+
+ Return(Buffer() {0})
+ } // End _DSM
+ } // Device(ISHD)
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchNvs.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchNvs.asl
new file mode 100644
index 0000000000..7c4a0cc23c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchNvs.asl
@@ -0,0 +1,240 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+ //
+ // Define PCH NVS Area operatino region.
+ //
+
+
+
+ OperationRegion(PNVA,SystemMemory,PNVB,PNVL)
+ Field(PNVA,AnyAcc,Lock,Preserve)
+ {
+ Offset(0), PCHS, 16, // Offset(0), PCH Series
+ Offset(2), PCHG, 16, // Offset(2), PCH Generation
+ Offset(4), RPA1, 32, // Offset(4), Root Port address 1
+ Offset(8), RPA2, 32, // Offset(8), Root Port address 2
+ Offset(12), RPA3, 32, // Offset(12), Root Port address 3
+ Offset(16), RPA4, 32, // Offset(16), Root Port address 4
+ Offset(20), RPA5, 32, // Offset(20), Root Port address 5
+ Offset(24), RPA6, 32, // Offset(24), Root Port address 6
+ Offset(28), RPA7, 32, // Offset(28), Root Port address 7
+ Offset(32), RPA8, 32, // Offset(32), Root Port address 8
+ Offset(36), RPA9, 32, // Offset(36), Root Port address 9
+ Offset(40), RPAA, 32, // Offset(40), Root Port address 10
+ Offset(44), RPAB, 32, // Offset(44), Root Port address 11
+ Offset(48), RPAC, 32, // Offset(48), Root Port address 12
+ Offset(52), RPAD, 32, // Offset(52), Root Port address 13
+ Offset(56), RPAE, 32, // Offset(56), Root Port address 14
+ Offset(60), RPAF, 32, // Offset(60), Root Port address 15
+ Offset(64), RPAG, 32, // Offset(64), Root Port address 16
+ Offset(68), RPAH, 32, // Offset(68), Root Port address 17
+ Offset(72), RPAI, 32, // Offset(72), Root Port address 18
+ Offset(76), RPAJ, 32, // Offset(76), Root Port address 19
+ Offset(80), RPAK, 32, // Offset(80), Root Port address 20
+ Offset(84), RPAL, 32, // Offset(84), Root Port address 21
+ Offset(88), RPAM, 32, // Offset(88), Root Port address 22
+ Offset(92), RPAN, 32, // Offset(92), Root Port address 23
+ Offset(96), RPAO, 32, // Offset(96), Root Port address 24
+ Offset(100), NHLA, 64, // Offset(100), HD-Audio NHLT ACPI address
+ Offset(108), NHLL, 32, // Offset(108), HD-Audio NHLT ACPI length
+ Offset(112), ADFM, 32, // Offset(112), HD-Audio DSP Feature Mask
+ Offset(116), SBRG, 32, // Offset(116), SBREG_BAR
+ Offset(120), GPEM, 32, // Offset(120), GPP_X to GPE_DWX mapping
+ Offset(124), G2L0, 32, // Offset(124), GPE 2-tier level edged enabled Gpio pads (Group Index 0)
+ Offset(128), G2L1, 32, // Offset(128), GPE 2-tier level edged enabled Gpio pads (Group Index 1)
+ Offset(132), G2L2, 32, // Offset(132), GPE 2-tier level edged enabled Gpio pads (Group Index 2)
+ Offset(136), G2L3, 32, // Offset(136), GPE 2-tier level edged enabled Gpio pads (Group Index 3)
+ Offset(140), G2L4, 32, // Offset(140), GPE 2-tier level edged enabled Gpio pads (Group Index 4)
+ Offset(144), G2L5, 32, // Offset(144), GPE 2-tier level edged enabled Gpio pads (Group Index 5)
+ Offset(148), G2L6, 32, // Offset(148), GPE 2-tier level edged enabled Gpio pads (Group Index 6)
+ Offset(152), G2L7, 32, // Offset(152), GPE 2-tier level edged enabled Gpio pads (Group Index 7)
+ Offset(156), G2L8, 32, // Offset(156), GPE 2-tier level edged enabled Gpio pads (Group Index 8)
+ Offset(160), G2L9, 32, // Offset(160), GPE 2-tier level edged enabled Gpio pads (Group Index 9)
+ Offset(164), PML1, 16, // Offset(164), PCIE LTR max snoop Latency 1
+ Offset(166), PML2, 16, // Offset(166), PCIE LTR max snoop Latency 2
+ Offset(168), PML3, 16, // Offset(168), PCIE LTR max snoop Latency 3
+ Offset(170), PML4, 16, // Offset(170), PCIE LTR max snoop Latency 4
+ Offset(172), PML5, 16, // Offset(172), PCIE LTR max snoop Latency 5
+ Offset(174), PML6, 16, // Offset(174), PCIE LTR max snoop Latency 6
+ Offset(176), PML7, 16, // Offset(176), PCIE LTR max snoop Latency 7
+ Offset(178), PML8, 16, // Offset(178), PCIE LTR max snoop Latency 8
+ Offset(180), PML9, 16, // Offset(180), PCIE LTR max snoop Latency 9
+ Offset(182), PMLA, 16, // Offset(182), PCIE LTR max snoop Latency 10
+ Offset(184), PMLB, 16, // Offset(184), PCIE LTR max snoop Latency 11
+ Offset(186), PMLC, 16, // Offset(186), PCIE LTR max snoop Latency 12
+ Offset(188), PMLD, 16, // Offset(188), PCIE LTR max snoop Latency 13
+ Offset(190), PMLE, 16, // Offset(190), PCIE LTR max snoop Latency 14
+ Offset(192), PMLF, 16, // Offset(192), PCIE LTR max snoop Latency 15
+ Offset(194), PMLG, 16, // Offset(194), PCIE LTR max snoop Latency 16
+ Offset(196), PMLH, 16, // Offset(196), PCIE LTR max snoop Latency 17
+ Offset(198), PMLI, 16, // Offset(198), PCIE LTR max snoop Latency 18
+ Offset(200), PMLJ, 16, // Offset(200), PCIE LTR max snoop Latency 19
+ Offset(202), PMLK, 16, // Offset(202), PCIE LTR max snoop Latency 20
+ Offset(204), PMLL, 16, // Offset(204), PCIE LTR max snoop Latency 21
+ Offset(206), PMLM, 16, // Offset(206), PCIE LTR max snoop Latency 22
+ Offset(208), PMLN, 16, // Offset(208), PCIE LTR max snoop Latency 23
+ Offset(210), PMLO, 16, // Offset(210), PCIE LTR max snoop Latency 24
+ Offset(212), PNL1, 16, // Offset(212), PCIE LTR max no snoop Latency 1
+ Offset(214), PNL2, 16, // Offset(214), PCIE LTR max no snoop Latency 2
+ Offset(216), PNL3, 16, // Offset(216), PCIE LTR max no snoop Latency 3
+ Offset(218), PNL4, 16, // Offset(218), PCIE LTR max no snoop Latency 4
+ Offset(220), PNL5, 16, // Offset(220), PCIE LTR max no snoop Latency 5
+ Offset(222), PNL6, 16, // Offset(222), PCIE LTR max no snoop Latency 6
+ Offset(224), PNL7, 16, // Offset(224), PCIE LTR max no snoop Latency 7
+ Offset(226), PNL8, 16, // Offset(226), PCIE LTR max no snoop Latency 8
+ Offset(228), PNL9, 16, // Offset(228), PCIE LTR max no snoop Latency 9
+ Offset(230), PNLA, 16, // Offset(230), PCIE LTR max no snoop Latency 10
+ Offset(232), PNLB, 16, // Offset(232), PCIE LTR max no snoop Latency 11
+ Offset(234), PNLC, 16, // Offset(234), PCIE LTR max no snoop Latency 12
+ Offset(236), PNLD, 16, // Offset(236), PCIE LTR max no snoop Latency 13
+ Offset(238), PNLE, 16, // Offset(238), PCIE LTR max no snoop Latency 14
+ Offset(240), PNLF, 16, // Offset(240), PCIE LTR max no snoop Latency 15
+ Offset(242), PNLG, 16, // Offset(242), PCIE LTR max no snoop Latency 16
+ Offset(244), PNLH, 16, // Offset(244), PCIE LTR max no snoop Latency 17
+ Offset(246), PNLI, 16, // Offset(246), PCIE LTR max no snoop Latency 18
+ Offset(248), PNLJ, 16, // Offset(248), PCIE LTR max no snoop Latency 19
+ Offset(250), PNLK, 16, // Offset(250), PCIE LTR max no snoop Latency 20
+ Offset(252), PNLL, 16, // Offset(252), PCIE LTR max no snoop Latency 21
+ Offset(254), PNLM, 16, // Offset(254), PCIE LTR max no snoop Latency 22
+ Offset(256), PNLN, 16, // Offset(256), PCIE LTR max no snoop Latency 23
+ Offset(258), PNLO, 16, // Offset(258), PCIE LTR max no snoop Latency 24
+ Offset(260), U0C0, 32, // Offset(260), SerialIo Hidden UART0 BAR 0
+ Offset(264), U1C0, 32, // Offset(264), SerialIo Hidden UART1 BAR 0
+ Offset(268), XHPC, 8, // Offset(268), Number of HighSpeed ports implemented in XHCI controller
+ Offset(269), XRPC, 8, // Offset(269), Number of USBR ports implemented in XHCI controller
+ Offset(270), XSPC, 8, // Offset(270), Number of SuperSpeed ports implemented in XHCI controller
+ Offset(271), XSPA, 8, // Offset(271), Address of 1st SuperSpeed port
+ Offset(272), HPTB, 32, // Offset(272), HPET base address
+ Offset(276), HPTE, 8, // Offset(276), HPET enable
+ //SerialIo block
+ Offset(277), SMD0, 8, // Offset(277), SerialIo controller 0 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(278), SMD1, 8, // Offset(278), SerialIo controller 1 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(279), SMD2, 8, // Offset(279), SerialIo controller 2 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(280), SMD3, 8, // Offset(280), SerialIo controller 3 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(281), SMD4, 8, // Offset(281), SerialIo controller 4 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(282), SMD5, 8, // Offset(282), SerialIo controller 5 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(283), SMD6, 8, // Offset(283), SerialIo controller 6 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(284), SMD7, 8, // Offset(284), SerialIo controller 7 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(285), SMD8, 8, // Offset(285), SerialIo controller 8 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(286), SMD9, 8, // Offset(286), SerialIo controller 9 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(287), SMDA, 8, // Offset(287), SerialIo controller A mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ Offset(288), SIR0, 8, // Offset(288), SerialIo controller 0 irq number
+ Offset(289), SIR1, 8, // Offset(289), SerialIo controller 1 irq number
+ Offset(290), SIR2, 8, // Offset(290), SerialIo controller 2 irq number
+ Offset(291), SIR3, 8, // Offset(291), SerialIo controller 3 irq number
+ Offset(292), SIR4, 8, // Offset(292), SerialIo controller 4 irq number
+ Offset(293), SIR5, 8, // Offset(293), SerialIo controller 5 irq number
+ Offset(294), SIR6, 8, // Offset(294), SerialIo controller 6 irq number
+ Offset(295), SIR7, 8, // Offset(295), SerialIo controller 7 irq number
+ Offset(296), SIR8, 8, // Offset(296), SerialIo controller 8 irq number
+ Offset(297), SIR9, 8, // Offset(297), SerialIo controller 9 irq number
+ Offset(298), SIRA, 8, // Offset(298), SerialIo controller A irq number
+ Offset(299), SB00, 64, // Offset(299), SerialIo controller 0 BAR0
+ Offset(307), SB01, 64, // Offset(307), SerialIo controller 1 BAR0
+ Offset(315), SB02, 64, // Offset(315), SerialIo controller 2 BAR0
+ Offset(323), SB03, 64, // Offset(323), SerialIo controller 3 BAR0
+ Offset(331), SB04, 64, // Offset(331), SerialIo controller 4 BAR0
+ Offset(339), SB05, 64, // Offset(339), SerialIo controller 5 BAR0
+ Offset(347), SB06, 64, // Offset(347), SerialIo controller 6 BAR0
+ Offset(355), SB07, 64, // Offset(355), SerialIo controller 7 BAR0
+ Offset(363), SB08, 64, // Offset(363), SerialIo controller 8 BAR0
+ Offset(371), SB09, 64, // Offset(371), SerialIo controller 9 BAR0
+ Offset(379), SB0A, 64, // Offset(379), SerialIo controller A BAR0
+ Offset(387), SB10, 64, // Offset(387), SerialIo controller 0 BAR1
+ Offset(395), SB11, 64, // Offset(395), SerialIo controller 1 BAR1
+ Offset(403), SB12, 64, // Offset(403), SerialIo controller 2 BAR1
+ Offset(411), SB13, 64, // Offset(411), SerialIo controller 3 BAR1
+ Offset(419), SB14, 64, // Offset(419), SerialIo controller 4 BAR1
+ Offset(427), SB15, 64, // Offset(427), SerialIo controller 5 BAR1
+ Offset(435), SB16, 64, // Offset(435), SerialIo controller 6 BAR1
+ Offset(443), SB17, 64, // Offset(443), SerialIo controller 7 BAR1
+ Offset(451), SB18, 64, // Offset(451), SerialIo controller 8 BAR1
+ Offset(459), SB19, 64, // Offset(459), SerialIo controller 9 BAR1
+ Offset(467), SB1A, 64, // Offset(467), SerialIo controller A BAR1
+ //end of SerialIo block
+ Offset(475), GPEN, 8, // Offset(475), GPIO enabled
+ Offset(476), SGIR, 8, // Offset(476), GPIO IRQ
+ Offset(477), NIT1, 8, // Offset(477), RST PCIe Storage Cycle Router#1 Interface Type
+ Offset(478), NIT2, 8, // Offset(478), RST PCIe Storage Cycle Router#2 Interface Type
+ Offset(479), NIT3, 8, // Offset(479), RST PCIe Storage Cycle Router#3 Interface Type
+ Offset(480), NPM1, 8, // Offset(480), RST PCIe Storage Cycle Router#1 Power Management Capability Pointer
+ Offset(481), NPM2, 8, // Offset(481), RST PCIe Storage Cycle Router#2 Power Management Capability Pointer
+ Offset(482), NPM3, 8, // Offset(482), RST PCIe Storage Cycle Router#3 Power Management Capability Pointer
+ Offset(483), NPC1, 8, // Offset(483), RST PCIe Storage Cycle Router#1 PCIe Capabilities Pointer
+ Offset(484), NPC2, 8, // Offset(484), RST PCIe Storage Cycle Router#2 PCIe Capabilities Pointer
+ Offset(485), NPC3, 8, // Offset(485), RST PCIe Storage Cycle Router#3 PCIe Capabilities Pointer
+ Offset(486), NL11, 16, // Offset(486), RST PCIe Storage Cycle Router#1 L1SS Capability Pointer
+ Offset(488), NL12, 16, // Offset(488), RST PCIe Storage Cycle Router#2 L1SS Capability Pointer
+ Offset(490), NL13, 16, // Offset(490), RST PCIe Storage Cycle Router#3 L1SS Capability Pointer
+ Offset(492), ND21, 8, // Offset(492), RST PCIe Storage Cycle Router#1 Endpoint L1SS Control Data2
+ Offset(493), ND22, 8, // Offset(493), RST PCIe Storage Cycle Router#2 Endpoint L1SS Control Data2
+ Offset(494), ND23, 8, // Offset(494), RST PCIe Storage Cycle Router#3 Endpoint L1SS Control Data2
+ Offset(495), ND11, 32, // Offset(495), RST PCIe Storage Cycle Router#1 Endpoint L1SS Control Data1
+ Offset(499), ND12, 32, // Offset(499), RST PCIe Storage Cycle Router#2 Endpoint L1SS Control Data1
+ Offset(503), ND13, 32, // Offset(503), RST PCIe Storage Cycle Router#3 Endpoint L1SS Control Data1
+ Offset(507), NLR1, 16, // Offset(507), RST PCIe Storage Cycle Router#1 LTR Capability Pointer
+ Offset(509), NLR2, 16, // Offset(509), RST PCIe Storage Cycle Router#2 LTR Capability Pointer
+ Offset(511), NLR3, 16, // Offset(511), RST PCIe Storage Cycle Router#3 LTR Capability Pointer
+ Offset(513), NLD1, 32, // Offset(513), RST PCIe Storage Cycle Router#1 Endpoint LTR Data
+ Offset(517), NLD2, 32, // Offset(517), RST PCIe Storage Cycle Router#2 Endpoint LTR Data
+ Offset(521), NLD3, 32, // Offset(521), RST PCIe Storage Cycle Router#3 Endpoint LTR Data
+ Offset(525), NEA1, 16, // Offset(525), RST PCIe Storage Cycle Router#1 Endpoint LCTL Data
+ Offset(527), NEA2, 16, // Offset(527), RST PCIe Storage Cycle Router#2 Endpoint LCTL Data
+ Offset(529), NEA3, 16, // Offset(529), RST PCIe Storage Cycle Router#3 Endpoint LCTL Data
+ Offset(531), NEB1, 16, // Offset(531), RST PCIe Storage Cycle Router#1 Endpoint DCTL Data
+ Offset(533), NEB2, 16, // Offset(533), RST PCIe Storage Cycle Router#2 Endpoint DCTL Data
+ Offset(535), NEB3, 16, // Offset(535), RST PCIe Storage Cycle Router#3 Endpoint DCTL Data
+ Offset(537), NEC1, 16, // Offset(537), RST PCIe Storage Cycle Router#1 Endpoint DCTL2 Data
+ Offset(539), NEC2, 16, // Offset(539), RST PCIe Storage Cycle Router#2 Endpoint DCTL2 Data
+ Offset(541), NEC3, 16, // Offset(541), RST PCIe Storage Cycle Router#3 Endpoint DCTL2 Data
+ Offset(543), NRA1, 16, // Offset(543), RST PCIe Storage Cycle Router#1 RootPort DCTL2 Data
+ Offset(545), NRA2, 16, // Offset(545), RST PCIe Storage Cycle Router#2 RootPort DCTL2 Data
+ Offset(547), NRA3, 16, // Offset(547), RST PCIe Storage Cycle Router#3 RootPort DCTL2 Data
+ Offset(549), NMB1, 32, // Offset(549), RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X Table BAR
+ Offset(553), NMB2, 32, // Offset(553), RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X Table BAR
+ Offset(557), NMB3, 32, // Offset(557), RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X Table BAR
+ Offset(561), NMV1, 32, // Offset(561), RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X Table BAR value
+ Offset(565), NMV2, 32, // Offset(565), RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X Table BAR value
+ Offset(569), NMV3, 32, // Offset(569), RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X Table BAR value
+ Offset(573), NPB1, 32, // Offset(573), RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X PBA BAR
+ Offset(577), NPB2, 32, // Offset(577), RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X PBA BAR
+ Offset(581), NPB3, 32, // Offset(581), RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X PBA BAR
+ Offset(585), NPV1, 32, // Offset(585), RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X PBA BAR value
+ Offset(589), NPV2, 32, // Offset(589), RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X PBA BAR value
+ Offset(593), NPV3, 32, // Offset(593), RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X PBA BAR value
+ Offset(597), NRP1, 32, // Offset(597), RST PCIe Storage Cycle Router#1 Root Port number
+ Offset(601), NRP2, 32, // Offset(601), RST PCIe Storage Cycle Router#2 Root Port number
+ Offset(605), NRP3, 32, // Offset(605), RST PCIe Storage Cycle Router#3 Root Port number
+ Offset(609), , 8, // Offset(609), Flag indicating Exit Boot Service, to inform SMM
+ Offset(610), SXRB, 32, // Offset(610), Sx handler reserved MMIO base
+ Offset(614), SXRS, 32, // Offset(614), Sx handler reserved MMIO size
+ Offset(618), CIOE, 8, // Offset(618), Cio2 Device Enabled as ACPI device
+ Offset(619), CIOI, 8, // Offset(619), Cio2 Interrupt Number
+ Offset(620), TAEN, 8, // Offset(620), Thermal Device Acpi mode enabled
+ Offset(621), TIRQ, 8, // Offset(621), Thermal Device IRQ number
+ Offset(622), XWMB, 32, // Offset(622), XHCI memory base address
+ Offset(626), EMH4, 8, // Offset(626), eMMC HS400 mode enabled
+ Offset(627), EMDS, 8, // Offset(627), eMMC Driver Strength
+ Offset(628), CSKU, 8, // Offset(628), CPU SKU
+ Offset(629), ITA0, 16, // Offset(629),
+ Offset(631), ITA1, 16, // Offset(631),
+ Offset(633), ITA2, 16, // Offset(633),
+ Offset(635), ITA3, 16, // Offset(635),
+ Offset(637), ITS0, 8, // Offset(637),
+ Offset(638), ITS1, 8, // Offset(638),
+ Offset(639), ITS2, 8, // Offset(639),
+ Offset(640), ITS3, 8, // Offset(640),
+ Offset(641), PMBS, 16, // Offset(641), ACPI IO BASE address
+ Offset(643), PWRM, 32, // Offset(643), PWRM MEM BASE address
+ }
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchPcie.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchPcie.asl
new file mode 100644
index 0000000000..8628735184
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchPcie.asl
@@ -0,0 +1,214 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+
+
+ OperationRegion(PXCS,PCI_Config,0x00,0x480)
+ Field(PXCS,AnyAcc, NoLock, Preserve)
+ {
+ Offset(0),
+ VDID, 32,
+ Offset(0x50), // LCTL - Link Control Register
+ L0SE, 1, // 0, L0s Entry Enabled
+ , 3,
+ LDIS, 1,
+ , 3,
+ Offset(0x52), // LSTS - Link Status Register
+ , 13,
+ LASX, 1, // 0, Link Active Status
+ Offset(0x5A), // SLSTS[7:0] - Slot Status Register
+ ABPX, 1, // 0, Attention Button Pressed
+ , 2,
+ PDCX, 1, // 3, Presence Detect Changed
+ , 2,
+ PDSX, 1, // 6, Presence Detect State
+ , 1,
+ Offset(0x60), // RSTS - Root Status Register
+ , 16,
+ PSPX, 1, // 16, PME Status
+ Offset(0xA4),
+ D3HT, 2, // Power State
+ Offset(R_PCH_PCIE_MPC), // 0xD8, MPC - Miscellaneous Port Configuration Register
+ , 30,
+ HPEX, 1, // 30, Hot Plug SCI Enable
+ PMEX, 1, // 31, Power Management SCI Enable
+ Offset(R_PCH_PCIE_PCIEDBG), // 0x324
+ , 3,
+ LEDM, 1, // PCIEDBG.DMIL1EDM
+ }
+ Field(PXCS,AnyAcc, NoLock, WriteAsZeros)
+ {
+ Offset(R_PCH_PCIE_SMSCS), // 0xDC, SMSCS - SMI/SCI Status Register
+ , 30,
+ HPSX, 1, // 30, Hot Plug SCI Status
+ PMSX, 1 // 31, Power Management SCI Status
+ }
+
+
+ Name(LTRV, Package(){0,0,0,0})
+
+ //
+ // _DSM Device Specific Method
+ //
+ // Arg0: UUID Unique function identifier
+ // Arg1: Integer Revision Level
+ // Arg2: Integer Function Index (0 = Return Supported Functions)
+ // Arg3: Package Parameters
+ Method(_DSM, 4, Serialized) {
+ //
+ // Switch based on which unique function identifier was passed in
+ //
+ If (LEqual(Arg0, ToUUID ("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
+ //
+ // _DSM Definitions for Latency Tolerance Reporting
+ //
+ // Arguments:
+ // Arg0: UUID: E5C937D0-3553-4d7a-9117-EA4D19C3434D
+ // Arg1: Revision ID: 2
+ // Arg2: Function Index: 1, 4 or 6
+ // Arg3: Empty Package
+ //
+ // Return:
+ // A Package of four integers corresponding with the LTR encoding defined
+ // in the PCI Express Base Specification, as follows:
+ // Integer 0: Maximum Snoop Latency Scale
+ // Integer 1: Maximum Snoop Latency Value
+ // Integer 2: Maximum No-Snoop Latency Scale
+ // Integer 3: Maximum No-Snoop Latency Value
+ // These values correspond directly to the LTR Extended Capability Structure
+ // fields described in the PCI Express Base Specification.
+ //
+ //
+ // Switch by function index
+ //
+ Switch(ToInteger(Arg2)) {
+ //
+ // Function Index:0
+ // Standard query - A bitmask of functions supported
+ //
+ Case (0) {
+ Name(OPTS,Buffer(2){0,0})
+ CreateBitField(OPTS,0,FUN0)
+ CreateBitField(OPTS,4,FUN4)
+ CreateBitField(OPTS,6,FUN6)
+ CreateBitField(OPTS,8,FUN8)
+ CreateBitField(OPTS,9,FUN9)
+
+ if (LGreaterEqual(Arg1, 2)){ // test Arg1 for Revision ID: 2
+ Store(1,FUN0)
+ if (LTRE){
+ Store(1,Fun6)
+ }
+ if (OBFF){
+ Store(1,Fun4)
+ }
+ if(LEqual(ECR1,1)){
+ if (LGreaterEqual(Arg1, 3)){ // test Arg1 for Revision ID: 3
+ Store(1,Fun8)
+ Store(1,Fun9)
+ }
+ }
+ }
+ Return (OPTS)
+ }
+ //
+ // Function Index: 4
+ //
+ Case(4) {
+ if (LGreaterEqual(Arg1, 2)){ // test Arg1 for Revision ID: 2
+ if (OBFZ){
+ Return (Buffer () {0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0}) // OBFF capable, offset 4[08h]
+ } else {
+ Return (Buffer () {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})
+ }
+ }
+ }
+ //
+ // Function Index: 5
+ // PCI FIRMWARE SPECIFICATION, REV. 3.2
+ // 4.6.5. _DSM for Ignoring PCI Boot Configurations
+ //
+ Case(5) {
+ If (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ return(1)
+ }
+ }
+ //
+ // Function Index: 6
+ // LTR Extended Capability Structure
+ //
+ Case(6) {
+ if (LGreaterEqual(Arg1, 2)){ // test Arg1 for Revision ID: 2
+ if (LTRZ){
+ if (LOr(LEqual(LMSL, 0),LEqual(LNSL, 0)))
+ {
+ if (LEqual (PCHS, SPTH)) {
+ Store (0x0846, LMSL)
+ Store (0x0846, LNSL)
+ } elseif (LEqual (PCHS, SPTL)) {
+ Store (0x1003, LMSL)
+ Store (0x1003, LNSL)
+ }
+ }
+ Store(And(ShiftRight(LMSL,10),7), Index(LTRV, 0))
+ Store(And(LMSL,0x3FF), Index(LTRV, 1))
+ Store(And(ShiftRight(LNSL,10),7), Index(LTRV, 2))
+ Store(And(LNSL,0x3FF), Index(LTRV, 3))
+
+ Return (LTRV)
+ } else {
+ Return (0)
+ }
+ }
+ }
+ Case(8) { //ECR ACPI additions for FW latency optimizations, DSM for Avoiding Power-On Reset Delay Duplication on Sx Resume
+ if(LEqual(ECR1,1)){
+ if (LGreaterEqual(Arg1, 3)) { // test Arg1 for Revision ID: 3
+ return (1)
+ }
+ }
+ }
+ Case(9) { //ECR ACPI additions for FW latency optimizations, DSM for Specifying Device Readiness Durations
+ if(LEqual(ECR1,1)){
+ if (LGreaterEqual(Arg1, 3)) { // test Arg1 for Revision ID: 3
+ return(Package(5){50000,Ones,Ones,50000,Ones})
+ }
+ }
+ }
+ } // End of switch(Arg2)
+ } // End of if
+ return (Buffer() {0x00})
+ } // End of _DSM
+
+ Device(PXSX)
+ {
+ Name(_ADR, 0x00000000)
+
+ // NOTE: Any PCIE Hot-Plug dependency for this port is
+ // specific to the CRB. Please modify the code based on
+ // your platform requirements.
+
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ }
+
+ //
+ // PCI_EXP_STS Handler for PCIE Root Port
+ //
+ Method(HPME,0,Serialized) {
+ If(LAnd(LNotEqual(VDID,0xFFFFFFFF), LEqual(PMSX,1))) { //if port exists and has PME SCI Status set...
+ Notify (PXSX, 0x2) //notify child device; this will cause its driver to clear PME_Status from device
+ Store(1,PMSX) // clear rootport's PME SCI status
+ Store(1,PSPX) // consume one pending PME notification to prevent it from blocking the queue
+ }
+ }
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchRstPcieStorage.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchRstPcieStorage.asl
new file mode 100644
index 0000000000..701cf6891a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchRstPcieStorage.asl
@@ -0,0 +1,186 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+#define PCI_CARD_BASE_ADDR0 0x10
+#define PCI_CARD_BASE_ADDR1 0x14
+#define PCI_CARD_BASE_ADDR2 0x18
+#define PCI_CARD_BASE_ADDR3 0x1C
+#define PCI_CARD_BASE_ADDR4 0x20
+#define PCI_CARD_BASE_ADDR5 0x24
+
+#define VDID_OFFSET 0x0 // 32bit value
+#define LEDM_OFFSET 0x324 // bit 3 - DMI L1 Entry Disable Mask (DMIL1EDM)
+#define LDIS_OFFSET 0x50 //bit 4 - Link Disable (LD)
+#define DPGE_OFFSET 0x420 // bit 30 - Disabled, Detect, L23_Rdy State and Un-Configured PHY Lane Power Gating Enable (DLSULPPGE)
+#define LASX_OFFSET 0x52 // bit 13 - Link Active (LA)
+
+#define ROOTPORT_READ 0
+#define ROOTPORT_WRITE 1
+#define ENDPOINT_READ 2
+#define ENDPOINT_WRITE 3
+
+ //RST Pcie Storage Remapped Base Address Index Value
+ Name(PRBI, 0)
+
+ //RST Pcie Storage Remapped Base Address Data Value
+ Name(PRBD, 0)
+
+ //RST Pcie Storage Endpoint Command Data
+ Name(PCMD, 0)
+
+ Name(RSTG, Package() { 0, 0, 0, 0 })
+ Name(PWRG, Package() { 0, 0, 0, 0 })
+ Name(SCLK, Package() { 0, 0, 0 })
+ //RST Pcie Storage Cycle Router
+ Name(NCRN, 0)
+
+ //
+ // Variables list to store corresponding value for different NVM device
+ //
+ Name(NITV, 0) // Interface Type
+ Name(NPMV, 0) // Power Management Capability Pointer
+ Name(NPCV, 0) // PCIe Capabilities Pointer
+ Name(NL1V, 0) // L1SS Capability Pointer
+ Name(ND2V, 0) // Endpoint L1SS Control Data2
+ Name(ND1V, 0) // Endpoint L1SS Control Data1
+ Name(NLRV, 0) // LTR Capability Pointer
+ Name(NLDV, 0) // Endpoint LTR Data
+ Name(NEAV, 0) // Endpoint LCTL Data
+ Name(NEBV, 0) // Endpoint DCTL Data
+ Name(NECV, 0) // Endpoint DCTL2 Data
+ Name(NRAV, 0) // RootPort DCTL2 Data
+ Name(NMBV, 0) // Endpoint unique MSI-X Table BAR
+ Name(NMVV, 0) // Endpoint unique MSI-X Table BAR value
+ Name(NPBV, 0) // Endpoint unique MSI-X PBA BAR
+ Name(NPVV, 0) // Endpoint unique MSI-X PBA BAR value
+ Name(NRPN, 0) // Assigned Root Port number
+
+ Name(MXIE, 0)
+
+ Name(ISD3, 0) // Is device in D3 state
+
+
+
+ //
+ // Restore of Remapped Device and Hidden Root Port
+ // This method is called after the endpoint is to be power ungated (D3-cold to D0 unitialized)
+ //
+ Method(CNRS, 0, Serialized)
+ {
+ Store("[ACPI RST] Restore Remapped Device and Hidden RP context |start", Debug)
+ ADBG(Concatenate("CNRSs ", ToDecimalString(Timer())))
+ //
+ // Return if RST Pcie Storage Remapping is disabled
+ //
+ If(LEqual(NITV,0))
+ {
+ Return()
+ }
+
+ //
+ // Clear all BARs in Remapped Device
+ //
+ RDCA(NCRN,PCI_CARD_BASE_ADDR0,0x0,0x0,ENDPOINT_WRITE)
+ RDCA(NCRN,PCI_CARD_BASE_ADDR1,0x0,0x0,ENDPOINT_WRITE)
+ RDCA(NCRN,PCI_CARD_BASE_ADDR2,0x0,0x0,ENDPOINT_WRITE)
+ RDCA(NCRN,PCI_CARD_BASE_ADDR3,0x0,0x0,ENDPOINT_WRITE)
+ RDCA(NCRN,PCI_CARD_BASE_ADDR4,0x0,0x0,ENDPOINT_WRITE)
+ RDCA(NCRN,PCI_CARD_BASE_ADDR5,0x0,0x0,ENDPOINT_WRITE)
+
+ //
+ // Restore remapped BAR and Endpoint CMD
+ //
+ RDCA(NCRN,PRBI,0x0,PRBD,ENDPOINT_WRITE)
+ RDCA(NCRN,0x4,0xFFFFFFF8,PCMD,ENDPOINT_WRITE)
+
+ //
+ // Restore of Remapped Device L1 Substate if this Capability is supported
+ //
+ If(LNotEqual(NL1V,0))
+ {
+ RDCA(NCRN,Add(NL1V,0x0C),0xFFFFFF00,ND2V,ENDPOINT_WRITE)
+ RDCA(NCRN,Add(NL1V,0x08),0x0000000F,And(ND1V,0xFFFFFFF0),ENDPOINT_WRITE)
+ RDCA(NCRN,Add(NL1V,0x08),0xFFFFFFFF,ND1V,ENDPOINT_WRITE)
+ }
+
+ //
+ // Restore of Remapped Device LTR if this Capability is supported
+ //
+ If(LNotEqual(NLRV,0))
+ {
+ RDCA(NCRN,Add(NLRV,0x04),0xFFFFFFFF,NLDV,ENDPOINT_WRITE)
+ }
+
+ //
+ // Restore of Remapped Device Link Control's "Enable Clock Power Management" field and "Common Clock Configuration" field
+ //
+ RDCA(NCRN,Add(NPCV,0x10),0xFFFFFEBF,And(NEAV,0xFFFC),ENDPOINT_WRITE)
+
+ //
+ // Restore of Remapped Device Device Control 2 field
+ //
+ RDCA(NCRN,Add(NPCV,0x28),0xFFFFFBFF,NECV,ENDPOINT_WRITE)
+
+ //
+ // Restore of Remapped Device Device Control field
+ //
+ RDCA(NCRN,Add(NPCV,0x8),0xFFFFFF1F,NEBV,ENDPOINT_WRITE)
+
+ //
+ // Restore of Hidden Root Port field
+ //
+ RDCA(NCRN,0x68,0xFFFFFBFF,NRAV,ROOTPORT_WRITE)
+
+ //
+ // Check CCC bit
+ // If this bit is 1, perform link retrain by setting the "Retrain Link" bit
+ //
+ If(LEqual(And(NEAV,0x40),0x40))
+ {
+ RDCA(NCRN,0x50,0xFFFFFFDF,0x20,ROOTPORT_WRITE)
+ //
+ // Poll PCIe Link Active status till it is active
+ //
+ ADBG(Concatenate("CNRSw ", ToDecimalString(Timer())))
+ while(LEqual(And(RDCA(NCRN,0x52,0x0,0x0,ROOTPORT_READ),0x2000),0))
+ {
+ Stall(10)
+ }
+ }
+ ADBG(Concatenate("CNRSx ", ToDecimalString(Timer())))
+
+ //
+ // Restore of Remapped Device Link Control's "Active State Link PM Control" field
+ //
+ RDCA(NCRN,Add(NPCV,0x10),0xFFFFFFFC,And(NEAV,0x0003),ENDPOINT_WRITE)
+
+ //
+ // Restore of Remapped Device related device BAR for the MSI-X Table BAR if the device supports unique MSI-X Table BAR
+ //
+ If(LNotEqual(NMVV,0))
+ {
+ RDCA(NCRN,NMBV,0x0,NMVV,ENDPOINT_WRITE)
+ }
+
+ //
+ // Restore of Remapped Device related device BAR for the MSI-X PBA BAR if the device supports unique MSI-X PBA BAR
+ //
+ If(LNotEqual(NPVV,0))
+ {
+ RDCA(NCRN,NPBV,0x0,NPVV,ENDPOINT_WRITE)
+ }
+
+ ADBG(Concatenate("CNRSe ", ToDecimalString(Timer())))
+ Store("[ACPI RST] Restore Remapped Device and Hidden RP context |complete", Debug)
+ }
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSata.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSata.asl
new file mode 100644
index 0000000000..d7f51f2b9b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSata.asl
@@ -0,0 +1,154 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+
+#define ROOTPORT_READ 0
+#define ROOTPORT_WRITE 1
+#define ENDPOINT_READ 2
+#define ENDPOINT_WRITE 3
+#define GPIO_NO_CONTROL 0
+#define GPIO_INTERNAL 1
+#define GPIO_EXTERNAL 2
+#define EXPANDER0 0
+#define EXPENDER1 1
+#define INDEX_CONTROL 0
+#define INDEX_EXPANDER_NR 1
+#define INDEX_PIN_NR 2
+#define INDEX_POLARITY 3
+
+
+External(\_SB.PCI0.SAT0.NVM1.RAID, MethodObj)
+External(\_SB.PCI0.SAT0.NVM1.IR3E, MethodObj)
+External(\_SB.PCI0.SAT0.NVM1.VLPM)
+External(\_SB.PCI0.SAT0.NVM2.RAID, MethodObj)
+External(\_SB.PCI0.SAT0.NVM2.IR3E, MethodObj)
+External(\_SB.PCI0.SAT0.NVM2.VLPM)
+External(\_SB.PCI0.SAT0.NVM3.RAID, MethodObj)
+External(\_SB.PCI0.SAT0.NVM3.IR3E, MethodObj)
+External(\_SB.PCI0.SAT0.NVM3.VLPM)
+
+
+//
+// SDSM is Device Specific Method supporting AHCI DEVSLP
+// It is not guaranteed to be available on every boot
+//
+External(\_SB.PCI0.SAT0.SDSM, MethodObj)
+External(\_SB.PCI0.RP05.PWRG)
+External(\_SB.PCI0.RP05.RSTG)
+External(\_SB.PCI0.RP05.SCLK)
+External(\_SB.PCI0.RP09.PWRG)
+External(\_SB.PCI0.RP09.RSTG)
+External(\_SB.PCI0.RP09.SCLK)
+External(\_SB.PCI0.RP13.PWRG)
+External(\_SB.PCI0.RP13.RSTG)
+External(\_SB.PCI0.RP13.SCLK)
+External(\_SB.PCI0.RP17.PWRG)
+External(\_SB.PCI0.RP17.RSTG)
+External(\_SB.PCI0.RP17.SCLK)
+
+ // PCH SATA Controller
+ Device (SAT0)
+ {
+ //Bus 0x00, Device 0x17, Function 0x00
+ Name(_ADR, 0x00170000)
+
+ Method(_DSM,4,serialized){
+ if(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) };
+ if(CondRefOf(\_SB.PCI0.SAT0.SDSM)) { return (\_SB.PCI0.SAT0.SDSM(Arg0,Arg1,Arg2,Arg3)) };
+ Return(Buffer() {0})
+ }
+
+ Device(PRT0)
+ {
+ Name(_ADR,0x0000FFFF) // Port 0
+ }
+
+ Device(PRT1)
+ {
+ Name(_ADR,0x0001FFFF) // Port 1
+ }
+
+ Device(PRT2)
+ {
+ Name(_ADR,0x0002FFFF) // Port 2
+ }
+
+ Device(PRT3)
+ {
+ Name(_ADR,0x0003FFFF) // Port 3
+ }
+
+ Device(PRT4)
+ {
+ Name(_ADR,0x0004FFFF) // Port 4
+ }
+
+ Device(PRT5)
+ {
+ Name(_ADR,0x0005FFFF) // Port 5
+ }
+ Device(VOL0)
+ {
+ Name(_ADR,0x0080FFFF) // RST Raid Volume 0 or SRT Cache
+ }
+ Device(VOL1)
+ {
+ Name(_ADR,0x0081FFFF) // RST Raid Volume 1
+ }
+ Device(VOL2)
+ {
+ Name(_ADR,0x0082FFFF) // RST Raid Volume 2
+ }
+ // Asign Root Port Configuration for remapped drive.
+ // 4 arguments: NRPN, PWRG, RSTG, SCLK
+ Method(ARPC, 4, Serialized,,, {FieldUnitObj, PkgObj, PkgObj, PkgObj})
+ {
+ ADBG(Concatenate("NRPN: ", ToHexString(Arg0)))
+ Switch(ToInteger(Arg0))
+ {
+ Case(4)
+ {
+ if(condrefof(\_SB.PCI0.RP05.PWRG)) {CopyObject(\_SB.PCI0.RP05.PWRG,Arg1)}
+ if(condrefof(\_SB.PCI0.RP05.RSTG)) {CopyObject(\_SB.PCI0.RP05.RSTG,Arg2)}
+ if(condrefof(\_SB.PCI0.RP05.SCLK)) {CopyObject(\_SB.PCI0.RP05.SCLK,Arg3)}
+ }
+ Case(8)
+ {
+ if(condrefof(\_SB.PCI0.RP09.PWRG)) {CopyObject(\_SB.PCI0.RP09.PWRG,Arg1)}
+ if(condrefof(\_SB.PCI0.RP09.RSTG)) {CopyObject(\_SB.PCI0.RP09.RSTG,Arg2)}
+ if(condrefof(\_SB.PCI0.RP09.SCLK)) {CopyObject(\_SB.PCI0.RP09.SCLK,Arg3)}
+
+ }
+ Case(12)
+ {
+ if(condrefof(\_SB.PCI0.RP13.PWRG)) {CopyObject(\_SB.PCI0.RP13.PWRG,Arg1)}
+ if(condrefof(\_SB.PCI0.RP13.RSTG)) {CopyObject(\_SB.PCI0.RP13.RSTG,Arg2)}
+ if(condrefof(\_SB.PCI0.RP13.SCLK)) {CopyObject(\_SB.PCI0.RP13.SCLK,Arg3)}
+ }
+ Case(16)
+ {
+ if(condrefof(\_SB.PCI0.RP17.PWRG)) {CopyObject(\_SB.PCI0.RP17.PWRG,Arg1)}
+ if(condrefof(\_SB.PCI0.RP17.RSTG)) {CopyObject(\_SB.PCI0.RP17.RSTG,Arg2)}
+ if(condrefof(\_SB.PCI0.RP17.SCLK)) {CopyObject(\_SB.PCI0.RP17.SCLK,Arg3)}
+ }
+ Default
+ {
+ ADBG(Concatenate("ERR!NRPN: ", ToHexString(Arg0)))
+ }
+ }
+ }
+
+
+
+
+ }
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchScs.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchScs.asl
new file mode 100644
index 0000000000..808c73e06c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchScs.asl
@@ -0,0 +1,247 @@
+/**@file
+ ACPI DSDT table for SCS Controllers
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+If(LEqual(PCHV(), SPTL)) { // SCS available on PCH-LP only
+
+Scope(\_SB.PCI0) {
+ //
+ // SCS eMMC (PCI Mode)
+ //
+ Device(PEMC) {
+ Name(_ADR, 0x001E0004)
+
+
+ // Memory Region to access to the eMMC PCI Configuration Space
+ OperationRegion(SCSR, PCI_Config, 0x00, 0x100)
+ Field(SCSR, WordAcc, NoLock, Preserve) {
+ Offset(R_PCH_SCS_DEV_PCS), // 0x84, PMCSR - Power Management Control and Status
+ PSTA,32,
+ Offset(R_PCH_SCS_DEV_PG_CONFIG), // 0xA2, Device PG config
+ , 2,
+ PGEN, 1 // [BIT2] PGE - PG Enable
+ }
+
+ Method(_PS0, 0, Serialized) {
+ Store(0, PGEN) // Disable PG
+ // Register address: 0xFD000000 SB offset | 0xC0<<16 PID_SCS | 0x0600 GPPRVRW1
+ PCRA(PID_SCS, R_PCH_PCR_SCS_GPPRVRW1, 0x7FFFFFBA) // Clear bits 31, 6, 2, 0
+ Sleep(2) // Wait 2ms
+ // Register address: 0xFD000000 SB offset | 0xC0<<16 PID_SCS | 0x0600 GPPRVRW1
+ PCRO(PID_SCS, R_PCH_PCR_SCS_GPPRVRW1, 0x80000045) // Set bits 31, 6, 2, 0
+
+ And(PSTA, 0xFFFFFFFC, PSTA) // Set BIT[1:0] = 00b - Power State D0
+ Store(PSTA, TEMP) // Read Back PMCSR
+ }
+
+ Method(_PS3, 0, Serialized) {
+ Store(1, PGEN) // Enable PG
+
+ Or(PSTA, 0x3, PSTA) // Set BIT[1:0] = 11b - Power State D3
+ Store(PSTA, TEMP) // Read Back PMCSR
+ }
+
+ // _DSM x86 Device Specific Method
+ // Arg0: UUID Unique function identifier
+ // Arg1: Integer Revision Level
+ // Arg2: Integer Function Index (0 = Return Supported Functions)
+ // Arg3: Package Parameters
+ Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+ If(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ ADBG(Concatenate("EMH4=",ToDecimalString(EMH4)))
+ // Check the UUID
+ If(LEqual(Arg0, ToUUID("f6c13ea5-65cd-461f-ab7a-29f7e8d5bd61"))) {
+ // Check the revision
+ If(LGreaterEqual(Arg1, Zero)) {
+ //Switch statement based on the function index.
+ Switch(ToInteger(Arg2)) {
+ //
+ // Function Index 0 the return value is a buffer containing
+ // one bit for each function index, starting with zero.
+ // Bit 0 - Indicates whether there is support for any functions other than function 0.
+ // Bit 1 - Indicates support to clear power control register
+ // Bit 2 - Indicates support to set power control register
+ // Bit 3 - Indicates support to set 1.8V signalling
+ // Bit 4 - Indicates support to set 3.3V signalling
+ // Bit 5 - Indicates support for HS200 mode
+ // Bit 6 - Indicates support for HS400 mode
+ // Bit 9 - Indicates eMMC I/O Driver Strength
+ //
+ // On SPT, for eMMC we have to support functions for
+ // HS200 and HS400 and I/O Driver Strength
+ //
+ Case(0) {
+ //
+ // The return value 0x261 (BIT6 set) for HS400 enabled and
+ // 0x221 (BIT6 not set) when HS400 is disabled in Setup menu.
+ //
+ If(LEqual(EMH4, 1)) {
+ Return(Buffer() {0x61, 0x02}) // HS400 support enabled
+ }
+ Return(Buffer() {0x21, 0x02}) // HS400 support disabled
+ }
+
+ //
+ // Function index 5 - corresponds to HS200 mode
+ // Return value from this function is used to program
+ // the UHS Mode Select bits in Host Control 2.
+ // 011b - corresponds to SDR104 and according to the
+ // SD Host Controller Spec and this value is overloaded
+ // to program the controller to select HS200 mode for eMMC.
+ //
+ Case(5) {
+ Return(Buffer() {0x3})
+ }
+
+ //
+ // Function index 6 - corresponds to HS400 mode
+ // Return value from this function is used to program
+ // the UHS Mode Select bits in Host Control 2.
+ // 101b is a reserved value according to the SD Host
+ // Controller Spec and we use this value for HS400 mode
+ // selection.
+ //
+ Case(6) {
+ Return(Buffer() {0x5})
+ }
+
+ //
+ // Function index 9 - corresponds to I/O Driver Strength
+ // Return value from this function represents the values
+ // of the Driver Strength selection
+ // (eMMC 5.01 Specification JESD84-B50.1, Table 186)
+ // that shall be programmed by the Host Driver (OS)
+ // as part of the Initialization flows.
+ //
+ Case(9) {
+ Switch(EMDS) {
+ Case(0x0) { Return(Buffer() {0x0}) } // 50 Ohm
+ Case(0x1) { Return(Buffer() {0x1}) } // 33 Ohm
+ Case(0x4) { Return(Buffer() {0x4}) } // 40 Ohm
+ }
+ }
+ } // End - Switch(Arg2)
+ }
+ } // End - UUID check
+ Return(Buffer() {0x0})
+ } // End - _DSM
+
+ Device (CARD) {
+ Name (_ADR, 0x00000008)
+ Method(_RMV, 0x0, NotSerialized) { Return (0) } // Device cannot be removed
+ }
+ } // Device(PEMC)
+
+ //
+ // SCS SD Card (PCI Mode)
+ //
+ Device(PSDC) {
+ Name(_ADR, 0x001E0006)
+
+
+ // Memory Region to access to the SDHC PCI Configuration Space
+ OperationRegion(SCSR, PCI_Config, 0x00, 0x100)
+ Field(SCSR, WordAcc, NoLock, Preserve) {
+ Offset(R_PCH_SCS_DEV_PCS), // 0x84, PMCSR - Power Management Control and Status
+ PSTA,32,
+ Offset(R_PCH_SCS_DEV_PG_CONFIG), // 0xA2, Device PG config
+ , 2,
+ PGEN, 1 // [BIT2] PGE - PG Enable
+ }
+
+ Method(_PS0, 0, Serialized) {
+ Store(0, PGEN) // Disable PG
+ // Register address: 0xFD000000 SB offset | 0xC0<<16 PID_SCS | 0x0600 GPPRVRW1
+ PCRA(PID_SCS, R_PCH_PCR_SCS_GPPRVRW1, 0xFFFFFE7A) // Clear bits 8, 7, 2, 0
+ Sleep(2) // Wait 2ms
+ // Register address: 0xFD000000 SB offset | 0xC0<<16 PID_SCS | 0x0600 GPPRVRW1
+ PCRO(PID_SCS, R_PCH_PCR_SCS_GPPRVRW1, 0x00000185) // Set bits 8, 7, 2, 0
+
+ And(PSTA, 0xFFFFFFFC, PSTA) // Set BIT[1:0] = 00b - Power State D0
+ Store(PSTA, TEMP) // Read Back PMCSR
+ }
+
+ Method(_PS3, 0, Serialized) {
+ Store(1, PGEN) // Enable PG
+
+ Or(PSTA, 0x3, PSTA) // Set BIT[1:0] = 11b - Power State D3
+ Store(PSTA, TEMP) // Read Back PMCSR
+ }
+
+ // _DSM x86 Device Specific Method
+ // Arg0: UUID Unique function identifier
+ // Arg1: Integer Revision Level
+ // Arg2: Integer Function Index (0 = Return Supported Functions)
+ // Arg3: Package Parameters
+ Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+ If(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ // Check the UUID
+ If(LEqual(Arg0, ToUUID("f6c13ea5-65cd-461f-ab7a-29f7e8d5bd61"))) {
+ // Check the revision
+ If(LGreaterEqual(Arg1, Zero)) {
+ // Switch statement based on the function index.
+ Switch(ToInteger(Arg2)) {
+ //
+ // Function Index 0 the return value is a buffer containing
+ // one bit for each function index, starting with zero.
+ // Bit 0 - Indicates whether there is support for any functions other than function 0.
+ // Bit 1 - Indicates support to clear power control register
+ // Bit 2 - Indicates support to set power control register
+ // Bit 3 - Indicates support to set 1.8V signalling
+ // Bit 4 - Indicates support to set 3.3V signalling
+ // Bit 5 - Indicates support for HS200 mode
+ // Bit 6 - Indicates support for HS400 mode
+ // Bit 9 - Indicates eMMC I/O Driver Strength
+ //
+ // On SPT, for SD we have to support functions to
+ // set 1.8V signalling and 3.3V signalling
+ //
+ Case(0) {
+ Return (Buffer() {0x19})
+ }
+
+ //
+ // Function Index 3: Set 1.8v signalling.
+ // We put a sleep of 100ms in this method to
+ // work around a known issue with detecting
+ // UHS SD card on SPT. This is to compensate
+ // for the SD VR slowness.
+ //
+ Case(3) {
+ Sleep (100) // Sleep 100ms
+ Return(Buffer(){0x00})
+ }
+
+ //
+ // Function Index 4: Set 3.3v signalling.
+ // We put a sleep of 100ms in this method to
+ // work around a known issue with detecting
+ // UHS SD card on SPT. This is to compensate
+ // for the SD VR slowness.
+ //
+ Case(4) {
+ Sleep (100) // Sleep 100ms
+ Return(Buffer(){0x00})
+ }
+ } // End - Switch(Arg2)
+ }
+ } // End - UUID check
+ Return(Buffer() {0x0})
+ } // End _DSM
+ }
+}
+
+}// End If(LEqual(PCHV(), SPTL)) - PCH-LP only
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSerialIo.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSerialIo.asl
new file mode 100644
index 0000000000..f33ee887e7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchSerialIo.asl
@@ -0,0 +1,749 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+#define SERIAL_IO_PMECTRLSTATUS 0x84
+
+#define SERIAL_IO_DISABLED 0
+#define SERIAL_IO_ACPI 1
+#define SERIAL_IO_PCI 2
+#define SERIAL_IO_ACPIHIDDEN 3
+#define SERIAL_IO_LEGACY_UART 4
+
+#define KBL_GENERATION 2
+
+#define SERIAL_IO_SPT_LP_GPIO_HID "INT344B"
+#define SERIAL_IO_SPT_H_GPIO_HID "INT345D"
+#define SERIAL_IO_KBL_H_GPIO_HID "INT3451"
+
+#define SERIAL_IO_I2C0_HID "INT3442"
+#define SERIAL_IO_I2C1_HID "INT3443"
+#define SERIAL_IO_I2C2_HID "INT3444"
+#define SERIAL_IO_I2C3_HID "INT3445"
+#define SERIAL_IO_I2C4_HID "INT3446"
+#define SERIAL_IO_I2C5_HID "INT3447"
+#define SERIAL_IO_SPI0_HID "INT3440"
+#define SERIAL_IO_SPI1_HID "INT3441"
+#define SERIAL_IO_UART0_HID "INT3448"
+#define SERIAL_IO_UART1_HID "INT3449"
+#define SERIAL_IO_UART2_HID "INT344A"
+
+#define SERIAL_IO_I2C0_ADR 0x00150000
+#define SERIAL_IO_I2C1_ADR 0x00150001
+#define SERIAL_IO_I2C2_ADR 0x00150002
+#define SERIAL_IO_I2C3_ADR 0x00150003
+#define SERIAL_IO_I2C4_ADR 0x00190002
+#define SERIAL_IO_I2C5_ADR 0x00190001
+#define SERIAL_IO_SPI0_ADR 0x001E0002
+#define SERIAL_IO_SPI1_ADR 0x001E0003
+#define SERIAL_IO_UART0_ADR 0x001E0000
+#define SERIAL_IO_UART1_ADR 0x001E0001
+#define SERIAL_IO_UART2_ADR 0x00190000
+
+Scope(\_SB.PCI0) {
+
+
+ //
+ // Common code for D3 entry for all SerialIo devices including PCI mode
+ //
+ // @param[in] Arg0 PCI calculated address or ACPI BAR1 address of device to be put in D3
+ //
+ Method (LPD3, 1, Serialized) {
+ OperationRegion(ICB1, SystemMemory, Add(Arg0,SERIAL_IO_PMECTRLSTATUS), 4)
+ Field(ICB1, DWordAcc, NoLock, Preserve) { PMEC, 32 } //Note: SerialIO Does Not Support PME
+ Store(0x3, PMEC) // Set BIT[1:0] = 11b - Power State D3
+ Store(PMEC,TEMP) // perform a read to avoid ordering and noncoherency problems
+ }
+
+ //
+ // Common code for D0 entry for all SerialIo devices including PCI mode
+ //
+ // @param[in] Arg0 PCI calculated address or ACPI BAR1 address of device to be put in D0
+ //
+ Method (LPD0, 1, Serialized) {
+ OperationRegion(ICB1, SystemMemory, Add(Arg0,SERIAL_IO_PMECTRLSTATUS), 4)
+ Field(ICB1, DWordAcc, NoLock, Preserve) { PMEC, 32 } //Note: SerialIO Does Not Support PME
+ And(PMEC, 0xFFFF7FFC, PMEC) // Set BIT[1:0] = 00b - Power State D0
+ Store(PMEC,TEMP) // perform a read to avoid ordering and noncoherency problems
+ }
+
+ //
+ // Common code for retrieving hardware revision for all SerialIo devices
+ //
+ // @param[in] Arg0 BAR1 of device
+ //
+ // @retval Hardware Revison
+ //
+ Method (LHRV, 1, Serialized) {
+ OperationRegion(ICB1, SystemMemory, Add(Arg0,0x8) , 4)
+ Field(ICB1, DWordAcc, NoLock, Preserve) { HRV, 8 }
+ Return(HRV)
+ }
+
+ //
+ // Get D state of SerialIo device - for use in _PSC method
+ //
+ // @param[in] Arg0 PCI calculated address or ACPI BAR1 of device
+ //
+ // @retval D State
+ //
+ Method (GETD, 1, Serialized) {
+ OperationRegion(ICB1, SystemMemory, Add(Arg0,SERIAL_IO_PMECTRLSTATUS) , 4)
+ Field(ICB1, DWordAcc, NoLock, Preserve) { PMEC, 32 }
+ Return (And(PMEC, 0x3))
+ }
+
+ //
+ // Common code for reporting memory and interrupt resources for all SerialIo devices
+ //
+ // @param[in] Arg0 Device mode
+ // @param[in] Arg1 Memory address
+ // @param[in] Arg2 Interrupt number
+ //
+ // @retval Resource buffer
+ //
+ Method (LCRS, 3, Serialized) {
+ Name (RBUF, ResourceTemplate () {
+ Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0)
+ Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , SIRQ) {20}
+ })
+ CreateDWordField(RBUF,BAR0._BAS,BVAL)
+ CreateDWordField(RBUF,BAR0._LEN,BLEN)
+ CreateDWordField(RBUF,SIRQ._INT,IRQN)
+ Store (Arg1, BVAL)
+ Store (Arg2, IRQN)
+ If(LEqual(Arg0,4)) {Store(8, BLEN)}
+ Return (RBUF)
+ }
+
+ //
+ // Common code for reporting status of all SerialIo devices
+ //
+ // @param[in] Arg0 Device's mode
+ //
+ // @retval 0 (do not show device) or 0xF (device is present)
+ //
+ Method (LSTA, 1, Serialized) {
+ If(LOr(LEqual(Arg0,0),LEqual(Arg0,3))) { Return(0) }
+ If(LLess(OSYS,2012)) { Return(0) } // OS older than Win8 = not supported
+ Return (0xF)
+ }
+
+ //
+ // Converts driver-visible GPIO number to interrupt number
+ //
+ // @param[in] Arg0 BAR1 of device
+ //
+ // @retval Interrupt number
+ //
+ Method (GIRQ,1,Serialized) {
+ Return (Add(24,Mod(Arg0,96)))
+ }
+
+} // END Scope(\_SB.PCI0)
+
+
+
+Scope(\_SB.PCI0) {
+ //
+ // An invisible device that claims memory resources reserved for SerialIo devices
+ // SerialIo devices in ACPI mode can't claim their BAR1 resources because these are aliases for PciCfg space
+ //
+ Device(SIRC) {
+ Name(_HID,EISAID("PNP0C02"))
+ Name(_STA,0x3) // device present and decodes its resources, but not to be displayed in OSPM
+ Name(_UID,5)
+
+ //
+ // Returns resource buffer with memory ranges used but not explicitely claimed by the device:
+ // in ACPI mode (SMDn=1) returns BAR1. In HIDDEN mode (SMDn=3) returns both BARs.
+ // In LegacyUART mode(SMDn=4) returns BAR1+ BAR0 except for first 8 bytes
+ //
+ // @param[in] Arg0 SMDn
+ // @param[in] Arg1 SB0n
+ // @param[in] Arg2 SB1n
+ //
+ // @retval Resource buffer with memory ranges
+ // if SMDn=0 (SERIAL_IO_DISABLED) or SMDn=2 (SERIAL_IO_PCI) returns an empty buffer
+ //
+ Method (ADDB, 3, Serialized) {
+
+ Name(BUFF,ResourceTemplate() { Memory32Fixed (ReadWrite, 0, 0x1000, BUF) })
+ CreateDWordField(BUFF, BUF._BAS, ADDR)
+ CreateDWordField(BUFF, BUF._LEN, LENG)
+
+ Store(ResourceTemplate() { }, Local0) // an empty buffer
+
+ If(LOr(LOr(LEqual(Arg0, SERIAL_IO_ACPI), LEqual(Arg0, SERIAL_IO_ACPIHIDDEN)), LEqual(Arg0, SERIAL_IO_LEGACY_UART))) {
+ Store(Arg2, ADDR)
+ ConcatenateResTemplate(Local0, BUFF, Local1) // add BAR1
+ Store(Local1, Local0)
+ }
+
+ If(LEqual(Arg0,SERIAL_IO_ACPIHIDDEN)) {
+ Store(Arg1,ADDR)
+ ConcatenateResTemplate(Local0, BUFF, Local1) // add BAR0
+ Store(Local1, Local0)
+ }
+
+ If(LEqual(Arg0, SERIAL_IO_LEGACY_UART)) {
+ Store(Add(8, Arg1), ADDR)
+ Store(0xFF8, LENG)
+ ConcatenateResTemplate(Local0, BUFF, Local1) // add BAR0 without 8 bytes
+ Store(Local1, Local0)
+ }
+ Return (Local0)
+ }
+
+ Method (_CRS, 0x0, Serialized) {
+ Store(ResourceTemplate() { }, Local0) // placeholder for concatenated buffers
+ //
+ // SB1[X] if device is configured as ACPI represents BAR1
+ // in case of PCI it stands for memory mapped BDF
+ //
+ ConcatenateResTemplate(Local0, ADDB(SMD0,SB00,SB10), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD1,SB01,SB11), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD2,SB02,SB12), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD3,SB03,SB13), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD4,SB04,SB14), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD5,SB05,SB15), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD6,SB06,SB16), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD7,SB07,SB17), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD8,SB08,SB18), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMD9,SB09,SB19), Local1)
+ Store(Local1, Local0)
+ ConcatenateResTemplate(Local0, ADDB(SMDA,SB0A,SB1A), Local1)
+ Store(Local1, Local0)
+ //
+ // GPIO device always exists in chipset. If it's not visible in ACPI
+ // and doesn't claim its resources, declare it here to prevent OS from reusing its mem addresses
+ //
+ If(LEqual(\_SB.PCI0.GPI0._STA(),0)) {
+ ConcatenateResTemplate(Local0, \_SB.PCI0.GPI0._CRS(), Local1)
+ Store(Local1, Local0)
+ }
+ Return (Local0)
+ } // END _CRS
+ } // END Device(SIRC)
+
+ //----------------------------
+ // Serial IO GPIO Controller
+ //----------------------------
+ Device (GPI0)
+ {
+ Method (_HID) {
+ // Return HID based on PCH Product
+ If (LEqual(PCHV, SPTH)) {
+ If (LEqual(PCHG, KBL_GENERATION)) { Return(SERIAL_IO_KBL_H_GPIO_HID) }
+ Return(SERIAL_IO_SPT_H_GPIO_HID)
+ }
+ Return(SERIAL_IO_SPT_LP_GPIO_HID)
+ }
+
+ Name (LINK,"\\_SB.PCI0.GPI0")
+
+ Method (_CRS, 0x0, NotSerialized) {
+ Name (RBUF, ResourceTemplate () {
+ Memory32Fixed (ReadWrite, 0x00000000, 0x00010000, BAR0)
+ Memory32Fixed (ReadWrite, 0x00000000, 0x00010000, BAR1)
+ Memory32Fixed (ReadWrite, 0x00000000, 0x00010000, BAR3)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , IRQ) { 14 } //Interrupt IRQ_EN
+ })
+ CreateDWordField(RBUF,BAR0._BAS,COM0)
+ CreateDWordField(RBUF,BAR1._BAS,COM1)
+ CreateDWordField(RBUF,IRQ._INT,IRQN)
+ Store( Add(SBRG,PCH_GPIO_COM0), COM0)
+ Store( Add(SBRG,PCH_GPIO_COM1), COM1)
+ CreateDWordField(RBUF,BAR3._BAS,COM3)
+ Store( Add(SBRG,PCH_GPIO_COM3), COM3)
+ Store(SGIR,IRQN)
+ Return (RBUF)
+ }
+
+ Method (_STA, 0x0, NotSerialized) {
+ If(LEqual(SBRG, 0)) { Return(0x0) } // has BAR for this device been programmed by the OS?
+ If(LEqual(GPEN, 0)) { Return(0x0) } // GPIO disabled in platform policy
+ Return(0xF)
+ }
+ }
+
+} // END Scope(\_SB.PCI0)
+
+
+//------------------------------------------
+// Serial IO I2C Controller 0 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C0) {
+ Name (LINK,"\\_SB.PCI0.I2C0") // Support for Windows 7
+ //
+ // I2C0 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB10))
+ }
+ Method (_PS0) {
+ LPD0(SB10)
+ }
+ Method (_PS3) {
+ LPD3(SB10)
+ }
+
+ //
+ // Apllies for I2C0 all modes except PCI
+ //
+ If(LNotEqual(SMD0,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C0_HID)
+ Method (_HRV) { Return (LHRV(SB10)) }
+ Method (_CRS) { Return (LCRS(SMD0,SB00,SIR0)) }
+ Method (_STA) { Return (LSTA(SMD0)) }
+ }
+
+ //
+ // Apllies for I2C0 PCI mode only
+ //
+ If(LEqual(SMD0,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C0_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C0)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO I2C Controller 1 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C1) {
+ Name (LINK,"\\_SB.PCI0.I2C1") // Support for Windows 7
+ //
+ // I2C1 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB11))
+ }
+ Method (_PS0) {
+ LPD0(SB11)
+ }
+ Method (_PS3) {
+ LPD3(SB11)
+ }
+
+ //
+ // Apllies for I2C1 all modes except PCI
+ //
+ If(LNotEqual(SMD1,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C1_HID)
+ Method (_HRV) { Return (LHRV(SB11)) }
+ Method (_CRS) { Return (LCRS(SMD1,SB01,SIR1)) }
+ Method (_STA) { Return (LSTA(SMD1)) }
+ }
+
+ //
+ // Apllies for I2C1 PCI mode only
+ //
+ If(LEqual(SMD1,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C1_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C1)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO I2C Controller 2 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C2) {
+ Name (LINK,"\\_SB.PCI0.I2C2") // Support for Windows 7
+ //
+ // I2C2 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB12))
+ }
+ Method (_PS0) {
+ LPD0(SB12)
+ }
+ Method (_PS3) {
+ LPD3(SB12)
+ }
+
+ //
+ // Apllies for I2C2 all modes except PCI
+ //
+ If(LNotEqual(SMD2,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C2_HID)
+ Method (_HRV) { Return (LHRV(SB12)) }
+ Method (_CRS) { Return (LCRS(SMD2,SB02,SIR2)) }
+ Method (_STA) { Return (LSTA(SMD2)) }
+ }
+
+ //
+ // Apllies for I2C2 PCI mode only
+ //
+ If(LEqual(SMD2,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C2_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C2)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO I2C Controller 3 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C3) {
+ Name (LINK,"\\_SB.PCI0.I2C3") // Windows 7 W/A
+ //
+ // I2C3 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB13))
+ }
+ Method (_PS0) {
+ LPD0(SB13)
+ }
+ Method (_PS3) {
+ LPD3(SB13)
+ }
+
+ //
+ // Apllies for I2C3 all modes except PCI
+ //
+ If(LNotEqual(SMD3,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C3_HID)
+ Method (_HRV) { Return (LHRV(SB13)) }
+ Method (_CRS) { Return (LCRS(SMD3,SB03,SIR3)) }
+ Method (_STA) { Return (LSTA(SMD3)) }
+ }
+
+ //
+ // Apllies for I2C3 PCI mode only
+ //
+ If(LEqual(SMD3,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C3_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C3)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO I2C Controller 4 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C4) {
+ Name (LINK,"\\_SB.PCI0.I2C4") // Support for Windows 7
+ //
+ // I2C4 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB14))
+ }
+ Method (_PS0) {
+ LPD0(SB14)
+ }
+ Method (_PS3) {
+ LPD3(SB14)
+ }
+
+ //
+ // Apllies for I2C4 all modes except PCI
+ //
+ If(LNotEqual(SMD4,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C4_HID)
+ Method (_HRV) { Return (LHRV(SB14)) }
+ Method (_CRS) { Return (LCRS(SMD4,SB04,SIR4)) }
+ Method (_STA) { Return (LSTA(SMD4)) }
+ }
+
+ //
+ // Apllies for I2C4 PCI mode only
+ //
+ If(LEqual(SMD4,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C4_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C4)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO I2C Controller 5 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (I2C5) {
+ Name (LINK,"\\_SB.PCI0.I2C5") // Support for Windows 7
+ //
+ // I2C5 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB15))
+ }
+ Method (_PS0) {
+ LPD0(SB15)
+ }
+ Method (_PS3) {
+ LPD3(SB15)
+ }
+
+ //
+ // Apllies for I2C5 all modes except PCI
+ //
+ If(LNotEqual(SMD5,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_I2C5_HID)
+ Method (_HRV) { Return (LHRV(SB15)) }
+ Method (_CRS) { Return (LCRS(SMD5,SB05,SIR5)) }
+ Method (_STA) { Return (LSTA(SMD5)) }
+ }
+
+ //
+ // Apllies for I2C5 PCI mode only
+ //
+ If(LEqual(SMD5,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_I2C5_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (I2C5)
+} // Scope(\_SB.PCI0)
+
+//-------------------------------------------
+// Serial IO SPI Controller 0 Configuration
+//-------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (SPI0) {
+ //
+ // SPI0 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD(SB16))
+ }
+ Method (_PS0) {
+ LPD0(SB16)
+ }
+ Method (_PS3) {
+ LPD3(SB16)
+ }
+
+ //
+ // Apllies for SPI0 all modes except PCI
+ //
+ If(LNotEqual(SMD6,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_SPI0_HID)
+ Method (_HRV) { Return (LHRV(SB16)) }
+ Method (_CRS) { Return (LCRS(SMD6,SB06,SIR6)) }
+ Method (_STA) { Return (LSTA(SMD6)) }
+ }
+
+ //
+ // Apllies for SPI0 PCI mode only
+ //
+ If(LEqual(SMD6,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_SPI0_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (SPI0)
+} // Scope(\_SB.PCI0)
+
+//------------------------------------------
+// Serial IO SPI Controller 1 Configuration
+//------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (SPI1) {
+ //
+ // SPI1 PCI/ACPI PS0 PS3 and PSC
+ //
+ Method (_PSC) {
+ Return (GETD (SB17))
+ }
+ Method (_PS0) {
+ LPD0(SB17)
+ }
+ Method (_PS3) {
+ LPD3(SB17)
+ }
+
+ //
+ // Apllies for SPI0 all modes except PCI
+ //
+ If(LNotEqual(SMD7,SERIAL_IO_PCI)) {
+ Name (_HID, SERIAL_IO_SPI1_HID)
+ Method (_HRV) { Return (LHRV(SB17)) }
+ Method (_CRS) { Return (LCRS(SMD7,SB07,SIR7)) }
+ Method (_STA) { Return (LSTA(SMD7)) }
+ }
+
+ //
+ // Apllies for SPI1 PCI mode only
+ //
+ If(LEqual(SMD7,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_SPI1_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ } // Device (SPI1)
+} // Scope(\_SB.PCI0)
+
+//-------------------------------------------
+// Serial IO UART Controller 0 Configuration
+//-------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (UA00) {
+
+ //
+ // Apllies for UART0 all modes except PCI
+ //
+ If(LNotEqual(SMD8,SERIAL_IO_PCI)) {
+ Method(_HID) {
+ If(LEqual(SMD8,SERIAL_IO_LEGACY_UART)) { Return (EISAID("PNP0C02")) }
+ Else { Return (SERIAL_IO_UART0_HID) }
+ }
+ Name (_UID, "SerialIoUart0")
+ Name (_DDN, "SerialIoUart0")
+ Method (_HRV) { Return (LHRV(SB18)) }
+ Method (_CRS) { Return (LCRS(SMD8,SB08,SIR8)) }
+ Method (_STA) { Return (LSTA(SMD8)) }
+ }
+
+ //
+ // Apllies for UART0 PCI mode only
+ //
+ If(LEqual(SMD8,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_UART0_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ //
+ // UART0 PCI/ACPI PS0 PS3 and PSC
+ //
+ If(LNotEqual(SMD8,SERIAL_IO_LEGACY_UART)) {
+ Method (_PSC) {
+ Return (GETD (SB18))
+ }
+ Method (_PS0) {
+ LPD0(SB18)
+ }
+ Method (_PS3) {
+ LPD3(SB18)
+ }
+ }
+
+ } // Device (UA00)
+} // Scope(\_SB.PCI0)
+
+//-------------------------------------------
+// Serial IO UART Controller 1 Configuration
+//-------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (UA01) {
+
+ //
+ // Apllies for UART1 all modes except PCI
+ //
+ If(LNotEqual(SMD9,SERIAL_IO_PCI)) {
+ Method(_HID) {
+ If(LEqual(SMD9,SERIAL_IO_LEGACY_UART)) { Return (EISAID("PNP0C02")) }
+ Else { Return (SERIAL_IO_UART1_HID) }
+ }
+ Name (_UID, "SerialIoUart1")
+ Name (_DDN, "SerialIoUart1")
+ Method (_HRV) { Return (LHRV(SB19)) }
+ Method (_CRS) { Return (LCRS(SMD9,SB09,SIR9)) }
+ Method (_STA) { Return (LSTA(SMD9)) }
+ }
+
+ //
+ // Apllies for UART1 PCI mode only
+ //
+ If(LEqual(SMD9,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_UART1_ADR)
+ Method (_DSM,4,Serialized){If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ //
+ // UART1 PCI/ACPI PS0 PS3 and PSC
+ //
+ If(LNotEqual(SMD9,SERIAL_IO_LEGACY_UART)) {
+ Method (_PSC) {
+ Return (GETD (SB19))
+ }
+ Method (_PS0) {
+ LPD0(SB19)
+ }
+ Method (_PS3) {
+ LPD3(SB19)
+ }
+ }
+
+ } // Device (UA01)
+} // Scope(\_SB.PCI0)
+
+//-------------------------------------------
+// Serial IO UART Controller 2 Configuration
+//-------------------------------------------
+Scope(\_SB.PCI0) {
+ Device (UA02) {
+
+ //
+ // Apllies for UART2 all modes except PCI
+ //
+ If(LNotEqual(SMDA,SERIAL_IO_PCI)) {
+ Method (_HID) {
+ If(LEqual(SMDA,SERIAL_IO_LEGACY_UART)) { Return (EISAID("PNP0C02")) }
+ Else { Return (SERIAL_IO_UART2_HID) }
+ }
+ Name (_UID, "SerialIoUart2")
+ Name (_DDN, "SerialIoUart2")
+ Method (_HRV) { Return (LHRV(SB1A)) }
+ Method (_CRS) { Return (LCRS(SMDA,SB0A,SIRA)) }
+ Method (_STA) { Return (LSTA(SMDA)) }
+ }
+
+ //
+ // Apllies for UART2 PCI mode only
+ //
+ If(LEqual(SMDA,SERIAL_IO_PCI)) {
+ Name (_ADR, SERIAL_IO_UART2_ADR)
+ Method (_DSM,4,Serialized){if(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }; Return(Buffer() {0})}
+ }
+
+ //
+ // UART2 PCI/ACPI PS0 PS3 and PSC excluding Legacy Uart
+ //
+ If(LNotEqual(SMDA,SERIAL_IO_LEGACY_UART)) {
+ Method (_PSC) {
+ Return (GETD(SB1A))
+ }
+ Method (_PS0) {
+ LPD0(SB1A)
+ }
+ Method (_PS3) {
+ LPD3(SB1A)
+ }
+ }
+
+ } // Device (UA02)
+} // Scope(\_SB.PCI0)
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXdci.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXdci.asl
new file mode 100644
index 0000000000..54c1242178
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXdci.asl
@@ -0,0 +1,310 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+External(\_SB.PCI0.LPCB.H_EC.XDAT, MethodObj)
+
+Scope(\_SB.PCI0)
+{
+ Device(XDCI)
+ {
+ Name (_ADR, 0x00140001) // _ADR: Address
+
+ OperationRegion (OTGD, PCI_Config, 0x0, 0x100)
+ Field (OTGD, DWordAcc, NoLock, Preserve)
+ {
+ Offset(0x0),
+ DVID, 16,
+ Offset(0x10),
+ XDCB, 64
+ }
+ //
+ // Byte access for PMCS field to avoid race condition on device D-state
+ //
+ Field (OTGD, ByteAcc, NoLock, Preserve)
+ {
+ Offset(R_PCH_XDCI_PMCSR), // 0x84, PM_CS - Power Management Control/Status
+ D0I3, 2, // PM_CS[1:0] PowerState
+ , 6,
+ PMEE, 1, // bit 8, PME Enable
+ , 6,
+ PMES, 1 // bit 15, PME Status
+ }
+
+ Method(XDBA, 0)
+ {
+ Return(And(^XDCB, 0xFFFFFFFFFFFFFF00))
+ }
+
+ //
+ // Arg0: UUID = {732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511}
+ // Arg1: Revision ID = 1
+ // Arg2: Function Index
+ // Arg3: Argument
+ //
+ Method(_DSM,4,Serialized)
+ {
+ If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+
+ If(LEqual(Arg0, ToUUID("732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"))){
+ If(Lequal(Arg1, 1)){
+ //
+ // Set PMU Power State
+ // Arg0: 0x00 PMU should enter the D0 power state.
+ // 0x03 PMU should enter the D3 power state.
+ // Arg1: 0x03 Enable PMU PME
+ // 0x00 Clear PMU PME
+ //
+ Method (SPPS,2,Serialized) {
+ OperationRegion(XDBW, SystemMemory, XDBA(), 0x110000)
+ Field(XDBW, WordAcc, NoLock, Preserve)
+ {
+ Offset(R_PCH_XDCI_APBFC_U3PMU_CFG2), // 0x10F810
+ , 8,
+ U2CP, 2, // USB2 core power state
+ U3CP, 2, // USB3 core power state
+ Offset(R_PCH_XDCI_APBFC_U3PMU_CFG4), // 0x10F818
+ PUPS, 2, // PMU power state
+ , 1,
+ PURC, 1, // Reset PMU core
+ , 12,
+ Offset(R_PCH_XDCI_APBFC_U3PMU_CFG5), // 0x10F81C
+ , 3,
+ UXPE, 2, // U2 PME EN / U3 PME EN
+ , 11,
+ }
+
+ // Local 1 is power state D0 or D3
+ Store(Arg0, Local1)
+ // Local 2 is Enable/Clear PMU PME
+ Store(Arg1, Local2)
+
+ If(LEqual(Local1, 0)){
+ // Clear PMU PME
+ // 0x10F81C BIT3: USB3 PME
+ // 0x10F81C BIT4: USB2 PME
+ Store(0, UXPE)
+ // Wait for at least 100us, currently configured to 1000us
+ Store(0, Local0)
+ While(LLess(Local0, 10)){
+ Stall(100)
+ Increment(Local0)
+ }
+ // Set PMU to D0 by writing 0 to 0x10f818 Bit 1:0
+ Store(0, PUPS)
+ // Wait 200ms for PMU to enter D0
+ // Confirm PMU being in D0 by checking 0x10f810 Bit 11:8 to be clear
+ // 0x10f810 Bit 11:10 - Current power state of USB3 core
+ // 0x10f810 Bit 9:8 - Current power state of USB2 core
+ // both should be clear
+ Store(0,Local0)
+ While(LLess(Local0,2000)){
+ Stall(100)
+ If(LAnd(LEqual(U2CP,0),LEqual(U3CP,0))){
+ break
+ }
+ Increment(Local0)
+ }
+ If(LNotEqual(U2CP, 0)){
+ // Show warning message
+ }
+ If(LNotEqual(U3CP, 0)){
+ // Show warning message
+ }
+ Return(0)
+ }
+
+ If(LEqual(Local1, 3)){
+ // PMU should be in D0 at this point
+ // 0x10f810 Bit 11:10 - current power state of USB3 core
+ // 0x10f810 Bit 9:8 - current power state of USB2 core
+ // both should be clear
+ If(LNotEqual(U2CP, 0)){
+ // Show warning message
+ }
+ If(LNotEqual(U3CP, 0)){
+ // Show warning message
+ }
+ // Set PMU to D3 by writing 3 to 0x10f818 bit 1:0
+ Store(3, PUPS)
+ // Wait 200ms for PMU to enter D3
+ // Confirm PMU being in D3 by checking 0x10f810 Bit 11:8 to be set
+ // 0x10f810 Bit 11:10 - Current power state of USB3 core
+ // 0x10f810 Bit 9:8 - Current power state of USB2 core
+ // both should be set
+ Store(0,Local0)
+ While(LLess(Local0,2000)){
+ Stall(100)
+ If(LAnd(LEqual(U2CP,3),LEqual(U3CP,3))){
+ break
+ }
+ Increment(Local0)
+ }
+ If(LNotEqual(U2CP, 3)){
+ // Show warning message
+ }
+ If(LNotEqual(U3CP, 3)){
+ // Show warning message
+ }
+ // Set/Clear PMU PME
+ // 0x10F81C BIT3: USB3 PME
+ // 0x10F81C BIT4: USB2 PME
+ Store(Local2, UXPE)
+ Return(0)
+ }
+ Return(0)
+ }
+
+ Switch(ToInteger(Arg2)) {
+ Case(0){
+ // Function 0: return Bit map to indicate Function 0,1,4,5,6,7 supported
+ Return(Buffer(){0xF3})
+ }
+ Case(1){
+ // Function 1: Attach/Detach and Port Detection Properties Method
+ // This method is called by the USB function stack to set the power state of the PMU.
+ // Bit 0 as 1: to indicate Platform support for Attach/detach notify
+ // Bit 1 as 0:HW based charging indication
+ Return(0x1)
+ }
+ Case(4){
+ // Function 4: Set PMU Power State Method, clear PMU PME
+ // Arg3: A package consisting of 1 ULONG value
+ // 0x00 PMU should enter the D0 power state.
+ // 0x03 PMU should enter the D3 power state.
+
+ // Local 1 is power state D0 or D3
+ Store(DerefOf(Index(Arg3,0)), Local1)
+
+ // Set PMU to Dx state and clear PMU PME
+ SPPS(Local1, 0)
+ }
+ Case(5){
+ // Function 5: Attach Notification Enabled Method
+ // This method is called by the USB function stack to indicate that it has enabled ACPI attach detach notifications.
+ // In response the platform may issue an notification indicating the current attach/detach state of the controller.
+
+ // If device is attached, notify XDCI with 0x80
+ // If device is detached, notify XDCI with 0x81
+
+
+ If(CondRefOf(\_SB.PCI0.LPCB.H_EC.XDAT)){
+ If(LEqual(\_SB.PCI0.LPCB.H_EC.XDAT(), 1)){
+ Notify(\_SB.PCI0.XDCI,0x80)
+ }Else{
+ Notify(\_SB.PCI0.XDCI,0x81)
+ }
+ }
+
+ Return(0)
+ }
+ Case(6){
+ // Function 6: XDCI Soft Reset Workaround
+ // Return value indicate to OS softreset should be done by OS or not
+ // Return value == 1: OS does softreset
+ // Return value == 0: platform does softreset
+
+
+ OperationRegion(XDBD, SystemMemory, XDBA(), 0x110000)
+ Field(XDBD, DwordAcc, NoLock, Preserve)
+ {
+ Offset(0xC704),
+ , 30,
+ CSFR, 1,
+ , 1,
+ }
+ OperationRegion(XDW2, SystemMemory, XDBA(), 0x110000)
+ Field(XDW2, WordAcc, NoLock, Preserve)
+ {
+ Offset(R_PCH_XDCI_APBFC_U3PMU_CFG6), // 0x10F820
+ , 13,
+ OTHC, 1, // OTG switched to host complete
+ }
+
+ If(LEqual(OTHC, 0)){
+ Store(1, CSFR)
+ // timeout is 100ms
+ Store(0, Local0)
+ While(LLess(Local0, 100)){
+ If(LEqual(CSFR, 0)){
+ Break
+ }
+ Sleep(1)
+ }
+ }
+ Return(0)
+ }
+ Case(7){
+ // Function 7: Get PMU Power State Method
+ // Return:
+ // 0: PMU is in D0 state
+ // 3: PMU is in D3 state
+
+
+ OperationRegion(XD22, SystemMemory, XDBA(), 0x110000)
+ Field(XD22, WordAcc, NoLock, Preserve)
+ {
+ Offset(R_PCH_XDCI_APBFC_U3PMU_CFG4), // 0x10F818
+ P2PS, 2, // PMU power state
+ , 14,
+ }
+ Store(P2PS, Local0)
+ Return(Local0)
+ }
+ }
+ }
+ }
+ Return(Buffer() {0})
+ }
+
+ Name (_DDN, "SPT XHCI controller") // _DDN: DOS Device Name
+ Name (_STR, Unicode ("SPT XHCI controller")) // _STR: Description String
+
+ Method(_S0W, 0)
+ { // PMEs can be generated from D3(hot)
+ Return(3)
+ }
+
+ Method (_STA, 0x0, NotSerialized)
+ {
+ If(LNotEqual(DVID, 0xFFFFFFFF)) { // device not disabled
+ Return (0xF)
+ } Else{
+ Return (0x0)
+ }
+ }
+
+ // XDCI Wake Support
+ Method(_PRW, 0)
+ {
+ Return(GPRW(0x6D,4)) // can wakeup from S4 state
+ }
+
+ Method(_DSW, 3)
+ {
+ Store(Arg0, PMEE)
+ }
+
+ Method(GPEH, 0, NotSerialized)
+ {
+ If(LEqual(DVID,0xFFFF)){
+ Return()
+ }
+ Store(PMES, Local0)
+ Store(1, PMES) // Clear PME Status
+ If(LAnd(PMEE, Local0)){
+ Notify(XDCI, 0x02)
+ }
+ }
+
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXhci.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXhci.asl
new file mode 100644
index 0000000000..873246f662
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/PchXhci.asl
@@ -0,0 +1,558 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+
+External(\_SB.PCI0.XHC.PS0X, MethodObj)
+External(\_SB.PCI0.XHC.PS3X, MethodObj)
+External(\_SB.PCI0.XHC.RHUB.PS0X, MethodObj)
+External(\_SB.PCI0.XHC.RHUB.PS2X, MethodObj)
+External(\_SB.PCI0.XHC.RHUB.PS3X, MethodObj)
+External(\_SB.PCI0.XHC.RHUB.INIR, MethodObj)
+
+Scope(\_SB_.PCI0) {
+ Device(XHC) {
+
+ Name(_ADR, 0x00140000)
+
+ OperationRegion(XPRT,PCI_Config,0x00,0x100)
+ Field(XPRT,AnyAcc,NoLock,Preserve)
+ {
+ DVID, 16,
+ Offset(0x10),
+ XADL, 32,
+ XADH, 32,
+ Offset(0x50), // XHCLKGTEN - Clock Gating
+ , 2,
+ STGE, 1, // Clock Gating Bit SSLTCGE
+ }
+ //
+ // Byte access for PMCS field to avoid race condition on device D-state
+ //
+ Field(XPRT,ByteAcc,NoLock,Preserve)
+ {
+ Offset(R_PCH_XHCI_PWR_CNTL_STS), // 0x74
+ D0D3, 2, // 0x74 BIT[1:0]
+ , 6,
+ PMEE, 1, // PME Enable
+ , 6,
+ PMES, 1, // PME Status
+ }
+
+ //
+ // Variable to store the maximum D state supported in S0.
+ //
+ Name (XFLT, 0)
+ //
+ // XHCI controller won't go into D3Hot during S0 until _DSM method is evaluated by filter driver.
+ //
+ Method(_DSM,4,serialized){
+ ADBG("_DSM")
+ ShiftLeft(XADH, 32, Local0)
+ Or (Local0, XADL, Local0)
+ And(Local0,0xFFFFFFFFFFFFFFF0,Local0)
+ OperationRegion(XMIO,SystemMemory,Local0,0x9000)
+ Field(XMIO,AnyAcc,Lock,Preserve)
+ {
+ Offset(R_PCH_LP_XHCI_PORTSC02USB3), // PORTSCXUSB3 - Port X Status and Control USB3
+ PCCS, 1, // Current Connect Status
+ , 4,
+ PPLS, 4, // Port Link Status
+ PTPP, 1, // Port Power
+ }
+
+ If(PCIC(Arg0)) { return(PCID(Arg0,Arg1,Arg2,Arg3)) }
+ //
+ // Check GUID ac340cb7-e901-45bf-b7e6-2b34ec931e23
+ //
+ If(LEqual(Arg0, Buffer(0x10) { 0xb7, 0x0c, 0x34, 0xac, 0x01, 0xe9, 0xbf, 0x45, 0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23 }))
+ {
+ //
+ // Only Supported value is "0x3"
+ //
+ If(LEqual(Arg1, 0x3))
+ {
+ Store(Arg1,XFLT)
+ }
+ }
+ Return(Buffer() {0})
+ }
+
+ Method(_S3D, 0, NotSerialized)
+ {
+ Return(3)
+ }
+ Method(_S4D, 0, NotSerialized)
+ {
+ Return(3)
+ }
+ Method(_S3W, 0, NotSerialized)
+ {
+ Return(3)
+ }
+ Method(_S4W, 0, NotSerialized)
+ {
+ Return(3)
+ }
+
+ //
+ // Once the filter driver is installed, D3 is allowed.
+ //
+ Method(_S0W, 0x0, NotSerialized)
+ {
+ If(LEqual(XFLT, Zero))
+ {
+ Return(0x0)
+ }
+ Else
+ {
+ Return(0x3)
+ }
+ }
+
+ Method(_PRW, 0)
+ {
+ Return(GPRW(0x6D, 4)) // can wakeup from S4 state
+ }
+
+ Method(_DSW, 3)
+ {
+ Store(Arg0, PMEE)
+ }
+
+ Method(_INI) {
+ If(CondRefOf(\_SB.PCI0.XHC.RHUB.INIR)) { // _INI for RTD3
+ \_SB.PCI0.XHC.RHUB.INIR()
+ }
+ }
+
+ //
+ // GPE handler for XHCI, this is part of _Lxx handler for bus 0 PME
+ //
+ Method(GPEH)
+ {
+ If(LEqual(DVID, 0xFFFF)) {
+ Return()
+ }
+ Store(PMES, Local0)
+ Store(1, PMES) // clear PME Status
+ If(LAnd(PMEE, Local0)) {
+ Notify(XHC, 0x02)
+ }
+ }
+
+ OperationRegion(XHCP, SystemMemory, Add(\_SB.PCI0.GPCB(), 0xA0000), 0x100)
+ Field(XHCP,AnyAcc,Lock,Preserve)
+ {
+ Offset(0x4),
+ PDBM, 16,
+ Offset(0x10),
+ MEMB, 64
+ }
+
+ //
+ // USRA (USbR port Address), method for calculating address of first USBR port in XHCI controller
+ //
+ Method(USRA,0,Serialized) {
+ If(LEqual(PCHV, SPTH)) { // SPT-H
+ Return (15)
+ } Else { // SPT-LP
+ Return (11)
+ }
+ }
+
+ //
+ // SSPA (SuperSpeed Port Address), method for calculating address of first SS port in XHCI controller
+ //
+ Method(SSPA,0,Serialized) {
+ If(LEqual(PCHV, SPTH)) { // SPT-H
+ Return (17)
+ } Else { // SPT-LP
+ Return (13)
+ }
+ }
+
+ Name(XRST, Zero)
+
+ Method(_PS0,0,Serialized)
+ {
+
+ If(LEqual(^DVID,0xFFFF))
+ {
+ Return()
+ }
+
+ Store(^MEMB,Local2) // Save MBAR
+ Store(^PDBM,Local1) // Save CMD
+
+ And(^PDBM,Not(0x06),^PDBM) // Clear MSE/BME
+ Store(0,STGE)
+
+ //
+ // Switch to D0
+ //
+ Store(0,^D0D3)
+
+ Store(\XWMB,^MEMB) // Set MBAR
+ Or(Local1,0x0002,^PDBM) // Set MSE
+
+ OperationRegion(MC11,SystemMemory,\XWMB,0x9000)
+ Field(MC11,DWordAcc,Lock,Preserve)
+ {
+ Offset(R_PCH_XHCI_USB2PMCTRL), // 0x81C4, USB2PMCTRL - USB2 Power Management Control
+ , 2,
+ UPSW, 2, // U2PSUSPGP
+ }
+
+ Store(0x0,UPSW)
+
+ And(^PDBM,Not(0x02),^PDBM) // Clear MSE
+
+ Store(Local2,^MEMB) // Restore MBAR
+ Store(Local1,^PDBM) // Restore CMD
+
+ //
+ // Call platform XHC PS0 method if present
+ //
+ If(CondRefOf(\_SB.PCI0.XHC.PS0X))
+ {
+ \_SB.PCI0.XHC.PS0X()
+ }
+
+ //
+ //
+ If(LAnd(UWAB,LOr(LEqual(D0D3,0),LEqual(\_SB.PCI0.XDCI.D0I3,0)))) {
+ //
+ // If the USB WA Bit is set and any XHCI or XDCI controller is in D0
+ //
+ //
+ // USB2 PHPY Power Gating - SW WA
+ //
+ // 1. BIOS writes a new command to the MTPMC register to cause the PMC to disable power gating
+ Store(1,MPMC)
+
+ // 2. BIOS waits for PCH_PM_STS.MSG_FULL_STS to be 0
+ // In parallel and in response to the previous command from BIOS, PMC FW will:
+ // * Make the USB2 force common lane PG match the BIOS policy (common lane PG disallowed)
+ // * Disable SUS power gating in XHCI
+ // * Wait for USB2 PHY side_pok to be 1
+ // * Disable core power gating in USB2 PHY
+ // * Disable common lane power gating in USB2 PHY (probably not necessary, consider removal)
+ // * Wait for USB2 SUS restoration status to be set, and do USB2 SUS power gating restoration
+ // * Get the PHY in the correct state before allowing transition to D0.
+ // * Clear MSG_FULL_STS
+ // BIOS sees MSG_FULL_STS clear and exits the method
+ //
+ While(PMFS) {
+ Sleep(10)
+ }
+ } // End If(UWAB)
+
+ }
+
+ Method(_PS3,0,Serialized)
+ {
+
+ If(LEqual(^DVID,0xFFFF))
+ {
+ Return()
+ }
+
+ Store(^MEMB,Local2) // Save MBAR
+ Store(^PDBM,Local1) // Save CMD
+
+ And(^PDBM,Not(0x06),^PDBM) // Clear MSE/BME
+
+ //
+ // Switch back to D0
+ //
+ Store(0,^D0D3)
+
+ Store(\XWMB,^MEMB) // Set MBAR
+ Or(Local1,0x0002,^PDBM) // Set MSE
+
+ OperationRegion(MC11,SystemMemory,\XWMB,0x9000)
+ Field(MC11,DWordAcc,Lock,Preserve)
+ {
+ Offset(R_PCH_XHCI_USB2PMCTRL), // 0x81C4, USB2PMCTRL - USB2 Power Management Control
+ , 2,
+ UPSW, 2, // U2PSUSPGP
+ }
+
+ Store(0x3,UPSW)
+
+ And(^PDBM,Not(0x02),^PDBM) // Clear MSE
+
+ Store(1,STGE)
+
+ //
+ // Switch back to D3
+ //
+ Store(3,^D0D3)
+
+ Store(Local2,^MEMB) // Restore MBAR
+ Store(Local1,^PDBM) // Restore CMD
+
+ //
+ // Call platform XHC PS3 method if present
+ //
+ If(CondRefOf(\_SB.PCI0.XHC.PS3X))
+ {
+ \_SB.PCI0.XHC.PS3X()
+ }
+
+ If(LAnd(UWAB,LAnd(LEqual(D0D3,3),LOr(LEqual(\_SB.PCI0.XDCI.D0I3,3),LEqual(\_SB.PCI0.XDCI.DVID,0xFFFF))))) {
+ //
+ // If the USB WA Bit is set and ((XHCI is in D3) AND ((XDCI is in D3) OR (XDCI is function disabled)))
+ //
+ // 1. BIOS writes a new command to the MTPMC register to enable power gating
+ Store(3,MPMC)
+
+ // 2. BIOS waits for PCH_PM_STS.MSG_FULL_STS to be 0
+ // In parallel and in response to the previous command from BIOS, PMC FW will:
+ // * Make the USB2 force common lane PG match the BIOS policy (common lane PG allowed)
+ // * Enable SUS power gating in XHCI
+ // * Enable core power gating in USB2 PHY
+ // * Enable common lane power gating in the USB2 PHY
+ // * Clear MSG_FULL_STS
+ // BIOS sees MSG_FULL_STS clear and exits the method
+ //
+ While(PMFS) {
+ Sleep(10)
+ }
+ } // End If(UWAB)
+ }
+
+ //
+ //
+ // Check for XHCI switch UUID
+ //
+ // Arguments:
+ // Arg0 (Buffer) : UUID
+ //
+ // Returns:
+ // 1: It's valid UUID
+ // 0: Invalid UUID
+ //
+ Method(CUID,1,Serialized) {
+ If(LEqual(Arg0,ToUUID("7c9512a9-1705-4cb4-af7d-506a2423ab71"))) {
+ Return(1)
+ }
+ Return(0)
+ }
+
+ Device(RHUB)
+ {
+ Name(_ADR, Zero)
+
+ // PS0 Method for xHCI Root Hub
+ Method(_PS0,0,Serialized)
+ {
+ If(LEqual(\_SB.PCI0.XHC.DVID,0xFFFF))
+ {
+ Return()
+ }
+ //
+ // Call platform XHC.RHUB PS0 method if present.
+ //
+ If(CondRefOf(\_SB.PCI0.XHC.RHUB.PS0X))
+ {
+ \_SB.PCI0.XHC.RHUB.PS0X()
+ }
+ }
+
+ // PS2 Method for xHCI Root Hub
+ Method(_PS2,0,Serialized)
+ {
+ If(LEqual(\_SB.PCI0.XHC.DVID,0xFFFF))
+ {
+ Return()
+ }
+ //
+ // Call platform XHC.RHUB PS2 method if present.
+ //
+ If(CondRefOf(\_SB.PCI0.XHC.RHUB.PS2X))
+ {
+ \_SB.PCI0.XHC.RHUB.PS2X()
+ }
+ }
+
+ // PS3 Method for xHCI Root Hub
+ Method(_PS3,0,Serialized)
+ {
+ If(LEqual(\_SB.PCI0.XHC.DVID,0xFFFF))
+ {
+ Return()
+ }
+ //
+ // Call platform XHC.RHUB PS3 method if present.
+ //
+ If(CondRefOf(\_SB.PCI0.XHC.RHUB.PS3X))
+ {
+ \_SB.PCI0.XHC.RHUB.PS3X()
+ }
+ }
+
+ //
+ // High Speed Ports (without USBR)
+ //
+ Device(HS01)
+ {
+ Name(_ADR, 0x01)
+ }
+
+ Device(HS02)
+ {
+ Name(_ADR, 0x02)
+ }
+
+ Device(HS03)
+ {
+ Name(_ADR, 0x03)
+ }
+
+ Device(HS04)
+ {
+ Name(_ADR, 0x04)
+ }
+
+ Device(HS05)
+ {
+ Name(_ADR, 0x05)
+ }
+
+ Device(HS06)
+ {
+ Name(_ADR, 0x06)
+ }
+
+ Device(HS07)
+ {
+ Name(_ADR, 0x07)
+ }
+
+ Device(HS08)
+ {
+ Name(_ADR, 0x08)
+ }
+
+ Device(HS09)
+ {
+ Name(_ADR, 0x09)
+ }
+
+ Device(HS10)
+ {
+ Name(_ADR, 0x0A)
+ }
+
+ //
+ // USBR port will be known as USBR instead of HS09 / HS15
+ //
+ Device(USR1)
+ {
+ Method(_ADR) { Return (Add(USRA(),0)) }
+ }
+
+ //
+ // USBR port 2 will be known as USBR instead of xxxx
+ //
+ Device(USR2)
+ {
+ Method(_ADR) { Return (Add(USRA(),1)) }
+ }
+
+ //
+ // Super Speed Ports
+ //
+ Device(SS01)
+ {
+ Method(_ADR) { Return (Add(SSPA(),0)) }
+ }
+
+ Device(SS02)
+ {
+ Method(_ADR) { Return (Add(SSPA(),1)) }
+ }
+
+ Device(SS03)
+ {
+ Method(_ADR) { Return (Add(SSPA(),2)) }
+ }
+
+ Device(SS04)
+ {
+ Method(_ADR) { Return (Add(SSPA(),3)) }
+ }
+
+ Device(SS05)
+ {
+ Method(_ADR) { Return (Add(SSPA(),4)) }
+ }
+
+ Device(SS06)
+ {
+ Method(_ADR) { Return (Add(SSPA(),5)) }
+ }
+
+ } // device rhub
+ } // device xhc
+} //scope
+
+//
+// SPT-H
+//
+If(LEqual(PCHV(),SPTH)) {
+ Scope(\_SB_.PCI0.XHC.RHUB) {
+
+ Device(HS11)
+ {
+ Name(_ADR, 0xB)
+ }
+
+ Device(HS12)
+ {
+ Name(_ADR, 0xC)
+ }
+
+ Device(HS13)
+ {
+ Name(_ADR, 0xD)
+ }
+
+ Device(HS14)
+ {
+ Name(_ADR, 0xE)
+ }
+
+ Device(SS07)
+ {
+ Method(_ADR) { Return (Add(SSPA(),6)) }
+ }
+
+ Device(SS08)
+ {
+ Method(_ADR) { Return (Add(SSPA(),7)) }
+ }
+
+ Device(SS09)
+ {
+ Method(_ADR) { Return (Add(SSPA(),8)) }
+ }
+
+ Device(SS10)
+ {
+ Method(_ADR) { Return (Add(SSPA(),9)) }
+ }
+
+ } //scope
+} // if
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/TraceHubDebug.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/TraceHubDebug.asl
new file mode 100644
index 0000000000..a8e4f0b34c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/TraceHubDebug.asl
@@ -0,0 +1,144 @@
+/**@file
+ Trace Hub debug library for ASL code.
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+#define TRACE_HUB_MASTER_NUM_ASL 32
+#define TRACE_HUB_CHANNEL_NUM_ASL 22
+
+Scope(\){
+ // Check if Trace Hub is enabled
+ Method (THEN, 0, Serialized) {
+ OperationRegion (THBA, SystemMemory, PCH_TRACE_HUB_SW_BASE_ADDRESS, 0x10)
+ Field (THBA, DWordAcc, NoLock, Preserve) {
+ Offset (0x00),
+ DO00, 32,
+ }
+ Return (LNotEqual(DO00, 0xFFFFFFFF))
+ }
+
+ // Trace Hub debug address
+ // This is internal helper runtine of THDS
+ // Arg0 : Master number
+ // Arg1 : Channel number
+ Method (THDA, 2, Serialized) {
+ // Local0 = PCH_TRACE_HUB_SW_BASE_ADDRESS + 0x40 * (V_PCH_TRACE_HUB_MTB_CHLCNT * (Master - V_PCH_TRACE_HUB_MTB_STHMSTR)) + 0x40 * Channel;
+ Store (PCH_TRACE_HUB_SW_BASE_ADDRESS, Local0)
+ Add (Local0, Multiply (0x40, Multiply (V_PCH_TRACE_HUB_MTB_CHLCNT, Subtract (Arg0, V_PCH_TRACE_HUB_MTB_STHMSTR))), Local0)
+ Add (Local0, Multiply (0x40, Arg1), Local0)
+ Return (Local0)
+ }
+
+ // String to raw data
+ // This is internal helper runtine of THDS
+ // Arg0 : string
+ // Arg1 : Index
+ // Arg2 : size
+ Method (STRD, 3, Serialized) {
+ If (LGreater (Add (Arg1, Arg2), SizeOf (Arg0))) {
+ Return (0)
+ }
+ // Local0 is return value
+ // Lccal1 is loop index
+ // Local2 is char of string
+ // Local3 is buffer of string
+ ToBuffer (Arg0, Local3)
+ Store (0, Local0)
+ Store (0, Local1)
+ While (LLess (Local1, Arg2)) {
+ Store (DeRefOf (Index (Local3, Add (Arg1, Local1))), Local2)
+ Add (Local0, ShiftLeft (Local2, Multiply (8, Local1)), Local0)
+ Increment (Local1)
+ }
+ Return (Local0)
+ }
+
+ // Trace Hub debug string
+ // Arg0 : debug string
+ Method (THDS, 1, Serialized) {
+ // TH check if enabled.
+ If (LNot (THEN())) {
+ Return
+ }
+ // Adding newline at the end of the string
+ Concatenate (Arg0, "\n", local2)
+
+ // Local0 is the length of string
+ // Local1 is the debug base address
+ // Local2 is the debug string with "\n"
+ Store (Sizeof (local2), Local0)
+ Store (THDA (TRACE_HUB_MASTER_NUM_ASL, TRACE_HUB_CHANNEL_NUM_ASL), Local1)
+ OperationRegion (THBA, SystemMemory, local1, 0x40)
+ Field (THBA, QWordAcc, NoLock, Preserve) {
+ Offset (0x00),
+ QO00, 64,
+ }
+ Field (THBA, DWordAcc, NoLock, Preserve) {
+ Offset (0x00),
+ DO00, 32,
+ Offset (0x10),
+ DO10, 32,
+ offset (0x30),
+ DO30, 32,
+ }
+ Field (THBA, WordAcc, NoLock, Preserve) {
+ Offset (0x00),
+ WO00, 16,
+ }
+ Field (THBA, ByteAcc, NoLock, Preserve) {
+ Offset (0x00),
+ BO00, 8,
+ }
+
+ // time stamp
+ Store (0x01000242, DO10)
+ // length of string
+ Store (Local0, WO00)
+ // string
+ Store (0, Local6)
+ Store (Local0, Local7)
+ while (LGreaterEqual(Local7, 8)) {
+ Store (STRD (local2, Local6, 8), QO00)
+ Add (Local6, 8, Local6)
+ Subtract (Local7, 8, Local7)
+ }
+ If (LGreaterEqual(Local7, 4)) {
+ Store (STRD (local2, Local6, 4), DO00)
+ Add (Local6, 4, Local6)
+ Subtract (Local7, 4, Local7)
+ }
+ If (LGreaterEqual(Local7, 2)) {
+ Store (STRD (local2, Local6, 2), WO00)
+ Add (Local6, 2, Local6)
+ Subtract (Local7, 2, Local7)
+ }
+ If (LGreaterEqual(Local7, 1)) {
+ Store (STRD (local2, Local6, 1), BO00)
+ Add (Local6, 1, Local6)
+ Subtract (Local7, 1, Local7)
+ }
+ // flag
+ Store (0, DO30)
+ }
+
+ // Trace Hub debug Hex string
+ // Arg0 : Integer, buffer
+ Method (THDH, 1, Serialized) {
+ THDS (ToHexString (Arg0))
+ }
+
+ // Trace Hub debug decimal string
+ // Arg0 : Integer, buffer
+ Method (THDD, 1, Serialized) {
+ THDS (ToDecimalString (Arg0))
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/usbsbd.asl b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/usbsbd.asl
new file mode 100644
index 0000000000..5036b4b771
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/AcpiTables/Dsdt/usbsbd.asl
@@ -0,0 +1,70 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+
+//
+// _DSM : Device Specific Method supporting USB Sideband Deferring function
+//
+// Arg0: UUID Unique function identifier
+// Arg1: Integer Revision Level
+// Arg2: Integer Function Index
+// Arg3: Package Parameters
+//
+Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj})
+{
+
+ If (LEqual(Arg0, ToUUID ("A5FC708F-8775-4BA6-BD0C-BA90A1EC72F8")))
+ {
+ //
+ // Switch by function index
+ //
+ Switch (ToInteger(Arg2))
+ {
+ //
+ // Standard query - A bitmask of functions supported
+ // Supports function 0-2
+ //
+ Case (0)
+ {
+ if (LEqual(Arg1, 1)){ // test Arg1 for the revision
+ Return (Buffer () {0x07})
+ } else {
+ Return (Buffer () {0})
+ }
+ }
+ //
+ // USB Sideband Deferring Support
+ // 0: USB Sideband Deferring not supported on this device
+ // 1: USB Sideband Deferring supported
+ //
+ Case (1)
+ {
+ if (LEqual(SDGV,0xFF)){ // check for valid GPE vector
+ Return (0)
+ } else {
+ Return (1)
+ }
+ }
+ //
+ // GPE Vector
+ // Return the bit offset within the GPE block of the GPIO (HOST_ALERT) driven by this device
+ //
+ Case (2)
+ {
+ Return (SDGV)
+ }
+ }
+ }
+
+ Return(Buffer() {0})
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Cio2Config.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Cio2Config.h
new file mode 100644
index 0000000000..187d4cd506
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Cio2Config.h
@@ -0,0 +1,72 @@
+/** @file
+ CIO2 policy
+
+Copyright (c) 2017, 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 that 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 _CIO2_CONFIG_H_
+#define _CIO2_CONFIG_H_
+
+#define CIO2_CONFIG_REVISION 1
+extern EFI_GUID gCio2ConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// The PCH_SKYCAM_CIO2_CONFIG block describes SkyCam CIO2 device.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ NOTE: For SKL PCH, while CIO2 is enabled,
+ RC will configure CIO2 controller as ACPI mode when PCH stepping < C0, and configure to PCI mode for C0 onwards.
+ **/
+ UINT32 DeviceEnable : 2; ///< 0: Disabled, <b>1: Enabled</b>
+
+ UINT32 SkyCamPortATermOvrEnable : 1; ///< <b>0: Disable</b>, 1: Enable - Termination override on port A
+ UINT32 SkyCamPortBTermOvrEnable : 1; ///< <b>0: Disable</b>, 1: Enable - Termination override on port B
+ UINT32 SkyCamPortCTermOvrEnable : 1; ///< <b>0: Disable</b>, 1: Enable - Termination override on port C
+ UINT32 SkyCamPortDTermOvrEnable : 1; ///< <b>0: Disable</b>, 1: Enable - Termination override on port D
+ UINT32 RsvdBits : 26;
+
+ //
+ // CIO2 FLS registers configuration.
+ //
+
+ UINT32 PortATrimEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port A Clk Trim
+ UINT32 PortBTrimEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port B Clk Trim
+ UINT32 PortCTrimEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port C Clk Trim
+ UINT32 PortDTrimEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port D Clk Trim
+ UINT32 PortACtleEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port A Ctle
+ UINT32 PortBCtleEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port B Ctle
+ UINT32 PortCDCtleEnable : 1; ///< 0: Disable, <b>1: Enable</b> - Port C/D Ctle
+ UINT32 RsvdBits0 : 25;
+
+ UINT32 PortACtleCapValue : 4; /// Port A Ctle Cap Value. Default is <b>0xE</b>
+ UINT32 PortBCtleCapValue : 4; /// Port B Ctle Cap Value. Default is <b>0xE</b>
+ UINT32 PortCDCtleCapValue : 4; /// Port C/D Ctle Cap Value. Default is <b>0xE</b>
+ UINT32 PortACtleResValue : 5; /// Port A Ctle Res Value. Default is <b>0xD</b>
+ UINT32 PortBCtleResValue : 5; /// Port B Ctle Res Value. Default is <b>0xD</b>
+ UINT32 PortCDCtleResValue : 5; /// Port C/D Ctle Res Value. Default is <b>0xD</b>
+ UINT32 RsvdBits1 : 5;
+
+ UINT32 PortAClkTrimValue : 4; /// Port A Clk Trim Value. Default is <b>0xA</b>
+ UINT32 PortBClkTrimValue : 4; /// Port B Clk Trim Value. Default is <b>0xA</b>
+ UINT32 PortCClkTrimValue : 4; /// Port C Clk Trim Value. Default is <b>0x9</b>
+ UINT32 PortDClkTrimValue : 4; /// Port D Clk Trim Value. Default is <b>0xA</b>
+ UINT32 PortADataTrimValue : 16; /// Port A Data Trim Value. Default is <b>0xBBBB</b>
+ UINT32 PortBDataTrimValue : 16; /// Port B Data Trim Value. Default is <b>0xBBBB</b>
+ UINT32 PortCDDataTrimValue : 16; /// Port C/D Data Trim Value. Default is <b>0xCCCC</b>
+
+} PCH_CIO2_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CIO2_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DciConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DciConfig.h
new file mode 100644
index 0000000000..aba0677abc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DciConfig.h
@@ -0,0 +1,53 @@
+/** @file
+ Dci policy
+
+Copyright (c) 2017, 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 that 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 _DCI_CONFIG_H_
+#define _DCI_CONFIG_H_
+
+#define DCI_PREMEM_CONFIG_REVISION 2
+extern EFI_GUID gDciPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to Direct Connection Interface (DCI).
+
+ <b>Revision 1:</b>
+ - Inital version.
+ <b>Revision 2:</b>
+ - Deprecate DciAutoDetect
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ DCI enable (HDCIEN bit)
+ when Enabled, allow DCI to be enabled. When Disabled, the host control is not enabling DCI feature.
+ BIOS provides policy to enable or disable DCI, and user would be able to use BIOS option to change this policy.
+ The user changing the setting from disable to enable, is taken as a consent from the user to enable this DCI feature.
+ <b>0:Disabled</b>; 1:Enabled
+ **/
+ UINT32 DciEn : 1;
+ /**
+ @deprecated from revision 2.
+ <b>(Test)</b> When set to Auto detect mode, it detects CCA being connected during BIOS post time.
+ This policy only applies when DciEn is disabled.
+ NOTE: this policy should not be visible to end customer.
+ 0: Disable AUTO mode, <b>1: Enable AUTO mode</b>
+ **/
+ UINT32 DciAutoDetect : 1;
+ UINT32 RsvdBits : 30; ///< Reserved bits
+} PCH_DCI_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _DCI_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DmiConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DmiConfig.h
new file mode 100644
index 0000000000..2fd5d1b171
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/DmiConfig.h
@@ -0,0 +1,53 @@
+/** @file
+ DMI policy
+
+Copyright (c) 2017, 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 that 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 _DMI_CONFIG_H_
+#define _DMI_CONFIG_H_
+
+#define DMI_CONFIG_REVISION 2
+extern EFI_GUID gDmiConfigGuid;
+
+
+#pragma pack (push,1)
+
+
+/**
+ The PCH_DMI_CONFIG block describes the expected configuration of the PCH for DMI.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Add LegacyIoLowLatency support.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ 0: Disable; <b>1: Enable</b> ASPM on PCH side of the DMI Link.
+ While DmiAspm is enabled, DMI ASPM will be set to Intel recommended value.
+ **/
+ UINT32 DmiAspm : 1;
+ UINT32 PwrOptEnable : 1; ///< <b>0: Disable</b>; 1: Enable DMI Power Optimizer on PCH side.
+ /**
+ Set to enable low latenc of legacy IO.
+ Some systems require lower IO latency irrespective of power.
+ This is a tradeoff between power and IO latency.
+ @note: Once this is enabled, DmiAspm is forced to disabled and so do Pcie DmiAspm in SystemAgent.
+ <b>0:Disable</b>, 1:Enable
+ **/
+ UINT32 LegacyIoLowLatency : 1;
+ UINT32 Rsvdbits : 29; ///< Reserved bits
+} PCH_DMI_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _DMI_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/EspiConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/EspiConfig.h
new file mode 100644
index 0000000000..c952bf9f31
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/EspiConfig.h
@@ -0,0 +1,41 @@
+/** @file
+ Espi policy
+
+Copyright (c) 2017, 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 that 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 _ESPI_CONFIG_H_
+#define _ESPI_CONFIG_H_
+
+#define ESPI_CONFIG_REVISION 1
+extern EFI_GUID gEspiConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to ESPI.
+
+ <b>Revision 1</b>:
+ - Initial version. Add BmeMasterSlaveEnabled support.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ eSPI Master and Slave BME settings.
+ When TRUE, then the BME bit enabled in eSPI Master and Slave.
+ 0: FALSE, <b>1: TRUE </b>
+ **/
+ UINT32 BmeMasterSlaveEnabled : 1;
+ UINT32 RsvdBits : 31; ///< Reserved bits
+} PCH_ESPI_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _ESPI_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h
new file mode 100644
index 0000000000..b55aaa705a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h
@@ -0,0 +1,54 @@
+/** @file
+ FlashProtection policy
+
+Copyright (c) 2017, 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 that 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 _FLASH_PROTECTION_CONFIG_H_
+#define _FLASH_PROTECTION_CONFIG_H_
+
+#define FLASH_PROTECTION_CONFIG_REVISION 1
+extern EFI_GUID gFlashProtectionConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH provides a method for blocking writes and reads to specific ranges
+ in the SPI flash when the Protected Ranges are enabled.
+ PROTECTED_RANGE is used to specify if flash protection are enabled,
+ the write protection enable bit and the read protection enable bit,
+ and to specify the upper limit and lower base for each register
+ Platform code is responsible to get the range base by PchGetSpiRegionAddresses routine,
+ and set the limit and base accordingly.
+**/
+typedef struct {
+ UINT32 WriteProtectionEnable : 1; ///< Write or erase is blocked by hardware. <b>0: Disable</b>; 1: Enable.
+ UINT32 ReadProtectionEnable : 1; ///< Read is blocked by hardware. <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits : 30; ///< Reserved
+ /**
+ The address of the upper limit of protection
+ This is a left shifted address by 12 bits with address bits 11:0 are assumed to be FFFh for limit comparison
+ **/
+ UINT16 ProtectedRangeLimit;
+ /**
+ The address of the upper limit of protection
+ This is a left shifted address by 12 bits with address bits 11:0 are assumed to be 0
+ **/
+ UINT16 ProtectedRangeBase;
+} PROTECTED_RANGE;
+
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ PROTECTED_RANGE ProtectRange[PCH_FLASH_PROTECTED_RANGES];
+} PCH_FLASH_PROTECTION_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _FLASH_PROTECTION_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HdAudioConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HdAudioConfig.h
new file mode 100644
index 0000000000..a0ebbbd84d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HdAudioConfig.h
@@ -0,0 +1,180 @@
+/** @file
+ HDAUDIO policy
+
+Copyright (c) 2017, 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 that 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 _HDAUDIO_CONFIG_H_
+#define _HDAUDIO_CONFIG_H_
+
+#define HDAUDIO_CONFIG_REVISION 2
+extern EFI_GUID gHdAudioConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// The PCH_HDAUDIO_CONFIG block describes the expected configuration of the Intel HD Audio feature.
+///
+#define PCH_HDAUDIO_AUTO 2
+
+#define HDAUDIO_VERB_TABLE_VIDDID(Vid,Did) (UINT32)((UINT16)Vid | ((UINT16)Did << 16))
+#define HDAUDIO_VERB_TABLE_RID_SDI_SIZE(Rid,Sdi,VerbTableSize) (UINT32)((UINT8)Rid | ((UINT8)Sdi << 8) | ((UINT16)VerbTableSize << 16))
+#define HDAUDIO_VERB_TABLE_CMD_SIZE(VerbTable) ((sizeof (VerbTable) - sizeof (PCH_HDA_VERB_TABLE_HEADER)) / (sizeof (UINT32)))
+
+///
+/// Use this macro to create HDAUDIO_VERB_TABLE and populate size automatically
+///
+#define HDAUDIO_VERB_TABLE_INIT(Vid,Did,Rid,Sdi,...) \
+{ \
+ { Vid, Did, Rid, Sdi, (sizeof((UINT32[]){__VA_ARGS__})/sizeof(UINT32)) }, \
+ { __VA_ARGS__ } \
+}
+
+/**
+ Azalia verb table header
+ Every verb table should contain this defined header and followed by azalia verb commands.
+**/
+typedef struct {
+ UINT16 VendorId; ///< Codec Vendor ID
+ UINT16 DeviceId; ///< Codec Device ID
+ UINT8 RevisionId; ///< Revision ID of the codec. 0xFF matches any revision.
+ UINT8 SdiNum; ///< SDI number, 0xFF matches any SDI.
+ UINT16 DataDwords; ///< Number of data DWORDs following the header.
+} PCH_HDA_VERB_TABLE_HEADER;
+
+#ifdef _MSC_VER
+//
+// Disable "zero-sized array in struct/union" extension warning.
+// Used for neater verb table definitions.
+//
+#pragma warning (push)
+#pragma warning (disable: 4200)
+#endif
+typedef struct {
+ PCH_HDA_VERB_TABLE_HEADER Header;
+ UINT32 Data[];
+} HDAUDIO_VERB_TABLE;
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+enum PCH_HDAUDIO_IO_BUFFER_OWNERSHIP {
+ PchHdaIoBufOwnerHdaLink = 0, ///< HD-Audio link owns all the I/O buffers.
+ PchHdaIoBufOwnerHdaLinkI2sPort = 1, ///< HD-Audio link owns 4 and I2S port owns 4 of the I/O buffers.
+ PchHdaIoBufOwnerI2sPort = 3 ///< I2S0 and I2S1 ports own all the I/O buffers.
+};
+
+enum PCH_HDAUDIO_IO_BUFFER_VOLTAGE {
+ PchHdaIoBuf33V = 0,
+ PchHdaIoBuf18V = 1
+};
+
+enum PCH_HDAUDIO_VC_TYPE {
+ PchHdaVc0 = 0,
+ PchHdaVc1 = 1
+};
+
+enum PCH_HDAUDIO_DMIC_TYPE {
+ PchHdaDmicDisabled = 0,
+ PchHdaDmic2chArray = 1,
+ PchHdaDmic4chArray = 2,
+ PchHdaDmic1chArray = 3
+};
+
+typedef enum {
+ PchHdaLinkFreq6MHz = 0,
+ PchHdaLinkFreq12MHz = 1,
+ PchHdaLinkFreq24MHz = 2,
+ PchHdaLinkFreq48MHz = 3,
+ PchHdaLinkFreq96MHz = 4,
+ PchHdaLinkFreqInvalid
+} PCH_HDAUDIO_LINK_FREQUENCY;
+
+typedef enum {
+ PchHdaIDispMode2T = 0,
+ PchHdaIDispMode1T = 1
+} PCH_HDAUDIO_IDISP_TMODE;
+
+/**
+ This structure contains the policies which are related to HD Audio device (cAVS).
+
+ <b>Revision 1:</b>
+ - Inital version.
+ <b>Revision 2:</b>
+ - Deprecate DspPpModuleMask: Pre/Post-processing modules (3rd Party IP) support moved to Platform Package.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ This member describes whether or not Intel HD Audio (Azalia) should be enabled.
+ If enabled (in Auto mode) and no codec exists the reference code will automatically disable
+ the HD Audio device.
+ 0: Disable, 1: Enable, <b>2: Auto (enabled if codec detected and initialized, disabled otherwise)</b>
+ **/
+ UINT32 Enable : 2;
+ UINT32 DspEnable : 1; ///< DSP enablement: 0: Disable; <b>1: Enable</b>
+ UINT32 Pme : 1; ///< Azalia wake-on-ring, <b>0: Disable</b>; 1: Enable
+ UINT32 IoBufferOwnership : 2; ///< I/O Buffer Ownership Select: <b>0: HD-A Link</b>; 1: Shared, HD-A Link and I2S Port; 3: I2S Ports
+ UINT32 IoBufferVoltage : 1; ///< I/O Buffer Voltage Mode Select: <b>0: 3.3V</b>; 1: 1.8V
+ UINT32 VcType : 1; ///< Virtual Channel Type Select: <b>0: VC0</b>, 1: VC1
+ UINT32 HdAudioLinkFrequency : 4; ///< HDA-Link frequency (PCH_HDAUDIO_LINK_FREQUENCY enum): <b>2: 24MHz</b>, 1: 12MHz, 0: 6MHz
+ UINT32 IDispLinkFrequency : 4; ///< iDisp-Link frequency (PCH_HDAUDIO_LINK_FREQUENCY enum): <b>4: 96MHz</b>, 3: 48MHz
+ UINT32 IDispLinkTmode : 1; ///< iDisp-Link T-Mode (PCH_HDAUDIO_IDISP_TMODE enum): <b>0: 2T</b>, 1: 1T
+ /**
+ Universal Audio Architecture compliance for DSP enabled system:
+ <b>0: Not-UAA Compliant (Intel SST driver supported only)</b>,
+ 1: UAA Compliant (HDA Inbox driver or SST driver supported)
+ **/
+ UINT32 DspUaaCompliance : 1;
+ UINT32 IDispCodecDisconnect : 1; ///< iDisplay Audio Codec disconnection, <b>0: Not disconnected, enumerable</b>; 1: Disconnected SDI, not enumerable
+ UINT32 RsvdBits0 : 13; ///< Reserved bits 1
+ /**
+ Bitmask of supported DSP endpoint configuration exposed via NHLT ACPI table:
+ **/
+ UINT32 DspEndpointDmic : 2; ///< DMIC Select (PCH_HDAUDIO_DMIC_TYPE enum): 0: Disable; 1: 2ch array; <b>2: 4ch array</b>; 3: 1ch array
+ UINT32 DspEndpointBluetooth : 1; ///< Bluetooth enablement: <b>0: Disable</b>; 1: Enable
+ UINT32 DspEndpointI2s : 1; ///< I2S enablement: <b>0: Disable</b>; 1: Enable
+ UINT32 RsvdBits1 : 28; ///< Reserved bits 2
+ /**
+ Bitmask of supported DSP features:
+ [BIT0] - WoV; [BIT1] - BT Sideband; [BIT2] - Codec VAD; [BIT5] - BT Intel HFP; [BIT6] - BT Intel A2DP
+ [BIT7] - DSP based speech pre-processing disabled; [BIT8] - 0: Intel WoV, 1: Windows Voice Activation
+ Default is <b>zero</b>.
+ **/
+ UINT32 DspFeatureMask;
+ /**
+ @deprecated from revision 2.
+ Bitmask of supported DSP Pre/Post-Processing Modules.
+ Specific pre/post-processing module bit position must be coherent with the ACPI implementation:
+ \_SB.PCI0.HDAS._DSM Function 3: Query Pre/Post Processing Module Support.
+ DspPpModuleMask is passed to ACPI as 'ADPM' NVS variable
+ Default is <b>zero</b>.
+ **/
+ UINT32 DspPpModuleMask;
+ UINT16 ResetWaitTimer; ///< <b>(Test)</b> The delay timer after Azalia reset, the value is number of microseconds. Default is <b>600</b>.
+ UINT8 Rsvd0; ///< Reserved bytes, align to multiple 4
+ /**
+ Number of the verb table entry defined in VerbTablePtr.
+ Each entry points to a verb table which contains HDAUDIO_VERB_TABLE structure and verb command blocks.
+ **/
+ UINT8 VerbTableEntryNum;
+ /**
+ Pointer to a verb table array.
+ This pointer points to 32bits address, and is only eligible and consumed in post mem phase.
+ Each entry points to a verb table which contains HDAUDIO_VERB_TABLE structure and verb command blocks.
+ The prototype of this is:
+ HDAUDIO_VERB_TABLE **VerbTablePtr;
+ **/
+ UINT32 VerbTablePtr;
+} PCH_HDAUDIO_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HDAUDIO_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HpetConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HpetConfig.h
new file mode 100644
index 0000000000..30928e5d08
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HpetConfig.h
@@ -0,0 +1,47 @@
+/** @file
+ HPET policy
+
+Copyright (c) 2017, 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 that 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 _HPET_CONFIG_H_
+#define _HPET_CONFIG_H_
+
+#define HPET_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gHpetPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HPET_CONFIG block passes the bus/device/function value for HPET.
+ The address resource range of HPET must be reserved in E820 and ACPI as
+ system resource.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Determines if enable HPET timer. 0: Disable; <b>1: Enable</b>.
+ The HPET timer address decode is always enabled.
+ This policy is used to configure the HPET timer count, and also the _STA of HPET device in ACPI.
+ While enabled, the HPET timer is started, else the HPET timer is halted.
+ **/
+ UINT32 Enable : 1;
+ UINT32 BdfValid : 1; ///< Whether the BDF value is valid. <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits0 : 6; ///< Reserved bits
+ UINT32 BusNumber : 8; ///< Bus Number HPETn used as Requestor / Completer ID. Default is <b>0xF0</b>.
+ UINT32 DeviceNumber : 5; ///< Device Number HPETn used as Requestor / Completer ID. Default is <b>0x1F</b>.
+ UINT32 FunctionNumber : 3; ///< Function Number HPETn used as Requestor / Completer ID. Default is <b>0x00</b>.
+ UINT32 RsvdBits1 : 8; ///< Reserved bits
+ UINT32 Base; ///< The HPET base address. Default is <b>0xFED00000</b>.
+} PCH_HPET_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HPET_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h
new file mode 100644
index 0000000000..e4973fc25e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h
@@ -0,0 +1,45 @@
+/** @file
+ HSIO policy
+
+Copyright (c) 2017, 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 that 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 _HSIO_CONFIG_H_
+#define _HSIO_CONFIG_H_
+
+#define HSIO_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gHsioPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HSIO_PREMEM_CONFIG block provides HSIO message related settings.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+
+ /**
+ <b>(Test)</b>
+ 0- Disable, disable will prevent the HSIO version check and ChipsetInit HECI message from being sent
+ <b>1- Enable</b> ChipsetInit HECI message
+ **/
+ UINT32 ChipsetInitMessage : 1;
+ /**
+ <b>(Test)</b>
+ <b>0- Disable</b>
+ 1- Enable When eanbled, this is used to bypass the reset after ChipsetInit HECI message.
+ **/
+ UINT32 BypassPhySyncReset : 1;
+ UINT32 RsvdBits : 30;
+} PCH_HSIO_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HSIO_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h
new file mode 100644
index 0000000000..cf7bd6251a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h
@@ -0,0 +1,76 @@
+/** @file
+ HSIO pcie policy
+
+Copyright (c) 2017, 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 that 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 _HSIO_PCIE_CONFIG_H_
+#define _HSIO_PCIE_CONFIG_H_
+
+#define HSIO_PCIE_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gHsioPciePreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HSIO_PCIE_LANE_CONFIG describes HSIO settings for PCIe lane
+**/
+typedef struct {
+ //
+ // HSIO Rx Eq
+ // Refer to the EDS for recommended values.
+ // Note that these setting are per-lane and not per-port
+ //
+ UINT32 HsioRxSetCtleEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 3 Set CTLE Value
+ UINT32 HsioRxSetCtle : 6; ///< PCH PCIe Gen 3 Set CTLE Value
+ UINT32 HsioTxGen1DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 1 TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen1DownscaleAmp : 6; ///< PCH PCIe Gen 1 TX Output Downscale Amplitude Adjustment value
+ UINT32 HsioTxGen2DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 2 TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen2DownscaleAmp : 6; ///< PCH PCIe Gen 2 TX Output Downscale Amplitude Adjustment value
+ UINT32 HsioTxGen3DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 3 TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen3DownscaleAmp : 6; ///< PCH PCIe Gen 3 TX Output Downscale Amplitude Adjustment value
+ UINT32 RsvdBits0 : 4; ///< Reserved Bits
+
+ UINT32 HsioTxGen1DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 1 TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen1DeEmph : 6; ///< PCH PCIe Gen 1 TX Output De-Emphasis Adjustment Setting
+ UINT32 HsioTxGen2DeEmph3p5Enable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 2 TX Output -3.5dB Mode De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen2DeEmph3p5 : 6; ///< PCH PCIe Gen 2 TX Output -3.5dB Mode De-Emphasis Adjustment Setting
+ UINT32 HsioTxGen2DeEmph6p0Enable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 2 TX Output -6.0dB Mode De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen2DeEmph6p0 : 6; ///< PCH PCIe Gen 2 TX Output -6.0dB Mode De-Emphasis Adjustment Setting
+ UINT32 RsvdBits1 : 11; ///< Reserved Bits
+} PCH_HSIO_PCIE_LANE_CONFIG;
+
+/**
+ The PCH_HSIO_PCIE_CONFIG block describes the configuration of the HSIO for PCIe lanes
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Add PciePllSsc support.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ ///
+ /// These members describe the configuration of HSIO for PCIe lanes.
+ ///
+ PCH_HSIO_PCIE_LANE_CONFIG Lane[PCH_MAX_PCIE_ROOT_PORTS];
+ /**
+ Specifies the Pcie Pll Spread Spectrum Percentage
+ The value of this policy is in 1/10th percent units.
+ Valid spread range is 0-20. A value of 0xFF is reserved for AUTO.
+ A value of 0 is SSC of 0.0%. A value of 20 is SSC of 2.0%
+ The default is <b>0xFF: AUTO - No BIOS override</b>.
+ **/
+ UINT8 PciePllSsc;
+ UINT8 Reserved[3];
+} PCH_HSIO_PCIE_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HSIO_PCIE_LANE_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h
new file mode 100644
index 0000000000..53c1a01a17
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h
@@ -0,0 +1,71 @@
+/** @file
+ Hsio Sata policy
+
+Copyright (c) 2017, 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 that 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 _HSIO_SATA_CONFIG_H_
+#define _HSIO_SATA_CONFIG_H_
+
+#define HSIO_SATA_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gHsioSataPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HSIO_SATA_PORT_LANE describes HSIO settings for SATA Port lane
+**/
+typedef struct {
+ //
+ // HSIO Rx Eq
+ //
+ UINT32 HsioRxGen1EqBoostMagEnable : 1; ///< <b>0: Disable</b>; 1: Enable Receiver Equalization Boost Magnitude Adjustment Value override
+ UINT32 HsioRxGen1EqBoostMag : 6; ///< SATA 1.5 Gb/sReceiver Equalization Boost Magnitude Adjustment value
+ UINT32 HsioRxGen2EqBoostMagEnable : 1; ///< <b>0: Disable</b>; 1: Enable Receiver Equalization Boost Magnitude Adjustment Value override
+ UINT32 HsioRxGen2EqBoostMag : 6; ///< SATA 3.0 Gb/sReceiver Equalization Boost Magnitude Adjustment value
+ UINT32 HsioRxGen3EqBoostMagEnable : 1; ///< <b>0: Disable</b>; 1: Enable Receiver Equalization Boost Magnitude Adjustment Value override
+ UINT32 HsioRxGen3EqBoostMag : 6; ///< SATA 6.0 Gb/sReceiver Equalization Boost Magnitude Adjustment value
+ //
+ // HSIO Tx Eq
+ //
+ UINT32 HsioTxGen1DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 1.5 Gb/s TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen1DownscaleAmp : 6; ///< SATA 1.5 Gb/s TX Output Downscale Amplitude Adjustment value
+ UINT32 RsvdBits0 : 4; ///< Reserved bits
+
+ UINT32 HsioTxGen2DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 3.0 Gb/s TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen2DownscaleAmp : 6; ///< SATA 3.0 Gb/s TX Output Downscale Amplitude Adjustment
+ UINT32 HsioTxGen3DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 6.0 Gb/s TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen3DownscaleAmp : 6; ///< SATA 6.0 Gb/s TX Output Downscale Amplitude Adjustment
+ UINT32 HsioTxGen1DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 1.5 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen1DeEmph : 6; ///< SATA 1.5 Gb/s TX Output De-Emphasis Adjustment Setting
+
+ UINT32 HsioTxGen2DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 3.0 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen2DeEmph : 6; ///< SATA 3.0 Gb/s TX Output De-Emphasis Adjustment Setting
+ UINT32 RsvdBits1 : 4; ///< Reserved bits
+
+ UINT32 HsioTxGen3DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 6.0 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen3DeEmph : 6; ///< SATA 6.0 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 RsvdBits2 : 25; ///< Reserved bits
+} PCH_HSIO_SATA_PORT_LANE;
+
+///
+/// The PCH_HSIO_SATA_CONFIG block describes the HSIO configuration of the SATA controller.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ ///
+ /// These members describe the configuration of HSIO for SATA lanes.
+ ///
+ PCH_HSIO_SATA_PORT_LANE PortLane[PCH_MAX_SATA_PORTS];
+} PCH_HSIO_SATA_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HSIO_SATA_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/InterruptConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/InterruptConfig.h
new file mode 100644
index 0000000000..3b8e247a31
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/InterruptConfig.h
@@ -0,0 +1,63 @@
+/** @file
+ Interrupt policy
+
+Copyright (c) 2017, 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 that 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 _INTERRUPT_CONFIG_H_
+#define _INTERRUPT_CONFIG_H_
+
+#define INTERRUPT_CONFIG_REVISION 1
+extern EFI_GUID gInterruptConfigGuid;
+
+#pragma pack (push,1)
+
+//
+// --------------------- Interrupts Config ------------------------------
+//
+typedef enum {
+ PchNoInt, ///< No Interrupt Pin
+ PchIntA,
+ PchIntB,
+ PchIntC,
+ PchIntD
+} PCH_INT_PIN;
+
+///
+/// The PCH_DEVICE_INTERRUPT_CONFIG block describes interrupt pin, IRQ and interrupt mode for PCH device.
+///
+typedef struct {
+ UINT8 Device; ///< Device number
+ UINT8 Function; ///< Device function
+ UINT8 IntX; ///< Interrupt pin: INTA-INTD (see PCH_INT_PIN)
+ UINT8 Irq; ///< IRQ to be set for device.
+} PCH_DEVICE_INTERRUPT_CONFIG;
+
+#define PCH_MAX_DEVICE_INTERRUPT_CONFIG 64 ///< Number of all PCH devices
+#define PCH_MAX_PXRC_CONFIG 8 ///< Number of PXRC registers in ITSS
+
+///
+/// The PCH_INTERRUPT_CONFIG block describes interrupt settings for PCH.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT8 NumOfDevIntConfig; ///< Number of entries in DevIntConfig table
+ UINT8 Rsvd0[3]; ///< Reserved bytes, align to multiple 4.
+ PCH_DEVICE_INTERRUPT_CONFIG DevIntConfig[PCH_MAX_DEVICE_INTERRUPT_CONFIG]; ///< Array which stores PCH devices interrupts settings
+ UINT8 PxRcConfig[PCH_MAX_PXRC_CONFIG]; ///< Array which stores interrupt routing for 8259 controller
+ UINT8 GpioIrqRoute; ///< Interrupt routing for GPIO. Default is <b>14</b>.
+ UINT8 SciIrqSelect; ///< Interrupt select for SCI. Default is <b>9</b>.
+ UINT8 TcoIrqSelect; ///< Interrupt select for TCO. Default is <b>9</b>.
+ UINT8 TcoIrqEnable; ///< Enable IRQ generation for TCO. <b>0: Disable</b>; 1: Enable.
+} PCH_INTERRUPT_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _INTERRUPT_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IoApicConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IoApicConfig.h
new file mode 100644
index 0000000000..c96e3a3a04
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IoApicConfig.h
@@ -0,0 +1,61 @@
+/** @file
+ IoApic policy
+
+Copyright (c) 2017, 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 that 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 _IOAPIC_CONFIG_H_
+#define _IOAPIC_CONFIG_H_
+
+#define IOAPIC_CONFIG_REVISION 1
+extern EFI_GUID gIoApicConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_IOAPIC_CONFIG block describes the expected configuration of the PCH
+ IO APIC, it's optional and PCH code would ignore it if the BdfValid bit is
+ not TRUE. Bus:device:function fields will be programmed to the register
+ P2SB IBDF(P2SB PCI offset R6Ch-6Dh), it's using for the following purpose:
+ As the Requester ID when initiating Interrupt Messages to the processor.
+ As the Completer ID when responding to the reads targeting the IOxAPI's
+ Memory-Mapped I/O registers.
+ This field defaults to Bus 0: Device 31: Function 0 after reset. BIOS can
+ program this field to provide a unique Bus:Device:Function number for the
+ internal IOxAPIC.
+ The address resource range of IOAPIC must be reserved in E820 and ACPI as
+ system resource.
+**/
+typedef struct {
+ /**
+ Revision 1: Init version
+ **/
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 BdfValid : 1; ///< Set to 1 if BDF value is valid, PCH code will not program these fields if this bit is not TRUE. <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits0 : 7; ///< Reserved bits
+ UINT32 BusNumber : 8; ///< Bus/Device/Function used as Requestor / Completer ID. Default is <b>0xF0</b>.
+ UINT32 DeviceNumber : 5; ///< Bus/Device/Function used as Requestor / Completer ID. Default is <b>0x1F</b>.
+ UINT32 FunctionNumber : 3; ///< Bus/Device/Function used as Requestor / Completer ID. Default is <b>0x00</b>.
+ UINT32 IoApicEntry24_119 : 1; ///< 0: Disable; <b>1: Enable</b> IOAPIC Entry 24-119
+ /**
+ Enable 8254 Static Clock Gating during early POST time. <b>0: Disable</b>, 1: Enable
+ Set 8254CGE=1 in POST time might fail to boot legacy OS which using 8254 timer.
+ Make sure it won't break legacy OS boot before enabling this.
+ **/
+ UINT32 Early8254ClockGatingEnable : 1;
+ UINT32 RsvdBits1 : 6; ///< Reserved bits
+ UINT8 IoApicId; ///< This member determines IOAPIC ID. Default is <b>0x02</b>.
+ UINT8 ApicRangeSelect; ///< Define address bits 19:12 for the IOxAPIC range. Default is <b>0</b>
+ UINT8 Rsvd0[2]; ///< Reserved bytes
+} PCH_IOAPIC_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _IOAPIC_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IshConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IshConfig.h
new file mode 100644
index 0000000000..6a4f6c9ee0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/IshConfig.h
@@ -0,0 +1,48 @@
+/** @file
+ ISH policy
+
+Copyright (c) 2017, 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 that 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 _ISH_CONFIG_H_
+#define _ISH_CONFIG_H_
+
+#define ISH_CONFIG_REVISION 1
+extern EFI_GUID gIshConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// The PCH_ISH_CONFIG block describes Integrated Sensor Hub device.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 Enable : 1; ///< ISH Controler 0: Disable; <b>1: Enable</b>.
+ UINT32 SpiGpioAssign : 1; ///< ISH SPI GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 Uart0GpioAssign : 1; ///< ISH UART0 GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 Uart1GpioAssign : 1; ///< ISH UART1 GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 I2c0GpioAssign : 1; ///< ISH I2C0 GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 I2c1GpioAssign : 1; ///< ISH I2C1 GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 I2c2GpioAssign : 1; ///< ISH I2C2 GPIO pins assigned: <b>0: False</b> 1: True
+ UINT32 Gp0GpioAssign : 1; ///< ISH GP_0 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp1GpioAssign : 1; ///< ISH GP_1 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp2GpioAssign : 1; ///< ISH GP_2 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp3GpioAssign : 1; ///< ISH GP_3 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp4GpioAssign : 1; ///< ISH GP_4 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp5GpioAssign : 1; ///< ISH GP_5 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp6GpioAssign : 1; ///< ISH GP_6 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 Gp7GpioAssign : 1; ///< ISH GP_7 GPIO pin assigned: <b>0: False</b> 1: True
+ UINT32 PdtUnlock : 1; ///< ISH PDT Unlock Msg: <b>0: False</b> 1: True
+ UINT32 RsvdBits0 : 16; ///< Reserved Bits
+} PCH_ISH_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _ISH_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LanConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LanConfig.h
new file mode 100644
index 0000000000..980f3ac709
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LanConfig.h
@@ -0,0 +1,44 @@
+/** @file
+ Lan policy
+
+Copyright (c) 2017, 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 that 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 _LAN_CONFIG_H_
+#define _LAN_CONFIG_H_
+
+#define LAN_CONFIG_REVISION 1
+extern EFI_GUID gLanConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ PCH intergrated LAN controller configuration settings.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Determines if enable PCH internal LAN, 0: Disable; <b>1: Enable</b>.
+ When Enable is changed (from disabled to enabled or from enabled to disabled),
+ it needs to set LAN Disable regsiter, which might be locked by FDSWL register.
+ So it's recommendated to issue a global reset when changing the status for PCH Internal LAN.
+ **/
+ UINT32 Enable : 1;
+ UINT32 LtrEnable : 1; ///< <b>0: Disable</b>; 1: Enable LTR capabilty of PCH internal LAN.
+ UINT32 K1OffEnable : 1; ///< Use CLKREQ for GbE power management; 1: Enabled, <b>0: Disabled</b>;
+ UINT32 RsvdBits0 : 4; ///< Reserved bits
+ UINT32 ClkReqSupported : 1; ///< Indicate whether dedicated CLKREQ# is supported; 1: Enabled, <b>0: Disabled</b>;
+ UINT32 ClkReqNumber : 4; ///< CLKREQ# used by GbE. Valid if ClkReqSupported is TRUE.
+ UINT32 RsvdBits1 : 20; ///< Reserved bits
+} PCH_LAN_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _LAN_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h
new file mode 100644
index 0000000000..f083b3b50c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h
@@ -0,0 +1,67 @@
+/** @file
+ Lock down policy
+
+Copyright (c) 2017, 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 that 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 _LOCK_DOWN_CONFIG_H_
+#define _LOCK_DOWN_CONFIG_H_
+
+#define LOCK_DOWN_CONFIG_REVISION 1
+extern EFI_GUID gLockDownConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_LOCK_DOWN_CONFIG block describes the expected configuration of the PCH
+ for security requirement.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ <b>(Test)</b> Enable SMI_LOCK bit to prevent writes to the Global SMI Enable bit. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 GlobalSmi : 1;
+ /**
+ <b>(Test)</b> Enable BIOS Interface Lock Down bit to prevent writes to the Backup Control Register
+ Top Swap bit and the General Control and Status Registers Boot BIOS Straps. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 BiosInterface : 1;
+ /**
+ <b>(Test)</b> Enable RTC lower and upper 128 byte Lock bits to lock Bytes 38h-3Fh in the upper
+ and lower 128-byte bank of RTC RAM. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 RtcLock : 1;
+ /**
+ Enable the BIOS Lock Enable (BLE) feature and set EISS bit (D31:F5:RegDCh[5])
+ for the BIOS region protection. When it is enabled, the BIOS Region can only be
+ modified from SMM after EndOfDxe protocol is installed.
+ Note: When BiosLock is enabled, platform code also needs to update to take care
+ of BIOS modification (including SetVariable) in DXE or runtime phase after
+ EndOfDxe protocol is installed. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 BiosLock : 1;
+ /**
+ Enable InSMM.STS (EISS) in SPI
+ If this bit is set, then WPD must be a '1' and InSMM.STS must be '1' also
+ in order to write to BIOS regions of SPI Flash. If this bit is clear,
+ then the InSMM.STS is a don't care.
+ The BIOS must set the EISS bit while BIOS Guard support is enabled.
+ In recovery path, platform can temporary disable EISS for SPI programming in
+ PEI phase or early DXE phase.
+ 0: Clear EISS bit; <b>1: Set EISS bit</b>.
+ **/
+ UINT32 SpiEiss : 1;
+ UINT32 RsvdBits0 : 27; ///< Reserved bits
+} PCH_LOCK_DOWN_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _LOCK_DOWN_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h
new file mode 100644
index 0000000000..be1613a5c2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h
@@ -0,0 +1,39 @@
+/** @file
+ Lpc policy
+
+Copyright (c) 2017, 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 that 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 _LPC_CONFIG_H_
+#define _LPC_CONFIG_H_
+
+#define LPC_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gLpcPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to LPC.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Enhance the port 8xh decoding.
+ Original LPC only decodes one byte of port 80h, with this enhancement LPC can decode word or dword of port 80h-83h.
+ @note: this will occupy one LPC generic IO range register. While this is enabled, read from port 80h always return 0x00.
+ 0: Disable, <b>1: Enable</b>
+ **/
+ UINT32 EnhancePort8xhDecoding : 1;
+ UINT32 RsvdBits : 31; ///< Reserved bits
+} PCH_LPC_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _LPC_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/P2sbConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/P2sbConfig.h
new file mode 100644
index 0000000000..60b9828ebf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/P2sbConfig.h
@@ -0,0 +1,50 @@
+/** @file
+ P2sb policy
+
+Copyright (c) 2017, 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 that 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 _P2SB_CONFIG_H_
+#define _P2SB_CONFIG_H_
+
+#define P2SB_CONFIG_REVISION 2
+extern EFI_GUID gP2sbConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to P2SB device.
+ <b>Revision 1:</b>
+ - Init version
+ <b>Revision 2:</b>
+ - Deprecate PsfUnlock and Add SbAccessUnlock to not lock SideBand register access.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ <b>(Test)</b>
+ This unlock the SBI lock bit to allow SBI after post time. <b>0: Disable</b>; 1: Enable.
+ NOTE: Do not set this policy "SbiUnlock" unless necessary.
+ **/
+ UINT32 SbiUnlock : 1;
+ UINT32 PsfUnlock : 1; //@deprecated
+ /**
+ <b>(Test)</b>
+ The SideBand registers will be locked before 3rd party code execution.
+ This policy unlock the SideBand space. <b>0: Disable</b>; 1: Enable.
+ NOTE: Do not set this policy "SbAccessUnlock" unless necessary.
+ **/
+ UINT32 SbAccessUnlock : 1;
+ UINT32 RsvdBits : 29;
+} PCH_P2SB_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _P2SB_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
new file mode 100644
index 0000000000..c946e9a116
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
@@ -0,0 +1,60 @@
+/** @file
+ PCH General policy
+
+Copyright (c) 2017, 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 that 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 _PCH_GENERAL_CONFIG_H_
+#define _PCH_GENERAL_CONFIG_H_
+
+#define PCH_GENERAL_CONFIG_REVISION 1
+#define PCH_GENERAL_PREMEM_CONFIG_REVISION 1
+
+extern EFI_GUID gPchGeneralConfigGuid;
+extern EFI_GUID gPchGeneralPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+enum PCH_RESERVED_PAGE_ROUTE {
+ PchReservedPageToLpc, ///< Port 80h cycles are sent to LPC.
+ PchReservedPageToPcie ///< Port 80h cycles are sent to PCIe.
+};
+
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Subsystem Vendor ID and Subsystem ID of the PCH devices.
+ This fields will be ignored if the value of SubSystemVendorId and SubSystemId
+ are both 0.
+ **/
+ UINT16 SubSystemVendorId; ///< Default Subsystem Vendor ID of the PCH devices. Default is <b>0x8086</b>
+ UINT16 SubSystemId; ///< Default Subsystem ID of the PCH devices. Default is <b>0x7270</b>
+ /**
+ This member describes whether or not the Compatibility Revision ID (CRID) feature
+ of PCH should be enabled. <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 Crid : 1;
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PCH_GENERAL_CONFIG;
+
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT16 AcpiBase; ///< Power management I/O base address. Default is <b>0x1800</b>.
+ UINT8 RsvdBytes[2];
+ /**
+ Control where the Port 80h cycles are sent, <b>0: LPC</b>; 1: PCI.
+ **/
+ UINT32 Port80Route : 1;
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PCH_GENERAL_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PCH_GENERAL_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PcieRpConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PcieRpConfig.h
new file mode 100644
index 0000000000..873386afe7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PcieRpConfig.h
@@ -0,0 +1,435 @@
+/** @file
+ Pcie root port policy
+
+Copyright (c) 2017, 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 that 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 _PCH_PCIE_CONFIG_H_
+#define _PCH_PCIE_CONFIG_H_
+
+#define PCIE_RP_CONFIG_REVISION 4
+#define PCIE_RP_PREMEM_CONFIG_REVISION 1
+
+extern EFI_GUID gPcieRpConfigGuid;
+extern EFI_GUID gPcieRpPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+#define PCH_PCIE_SWEQ_COEFFS_MAX 5
+
+typedef enum {
+ PchPcieOverrideDisabled = 0,
+ PchPcieL1L2Override = 0x01,
+ PchPcieL1SubstatesOverride = 0x02,
+ PchPcieL1L2AndL1SubstatesOverride = 0x03,
+ PchPcieLtrOverride = 0x04
+} PCH_PCIE_OVERRIDE_CONFIG;
+
+/**
+ PCIe device table entry entry
+
+ The PCIe device table is being used to override PCIe device ASPM settings.
+ To take effect table consisting of such entries must be instelled as PPI
+ on gPchPcieDeviceTablePpiGuid.
+ Last entry VendorId must be 0.
+**/
+typedef struct {
+ UINT16 VendorId; ///< The vendor Id of Pci Express card ASPM setting override, 0xFFFF means any Vendor ID
+ UINT16 DeviceId; ///< The Device Id of Pci Express card ASPM setting override, 0xFFFF means any Device ID
+ UINT8 RevId; ///< The Rev Id of Pci Express card ASPM setting override, 0xFF means all steppings
+ UINT8 BaseClassCode; ///< The Base Class Code of Pci Express card ASPM setting override, 0xFF means all base class
+ UINT8 SubClassCode; ///< The Sub Class Code of Pci Express card ASPM setting override, 0xFF means all sub class
+ UINT8 EndPointAspm; ///< Override device ASPM (see: PCH_PCIE_ASPM_CONTROL)
+ ///< Bit 1 must be set in OverrideConfig for this field to take effect
+ UINT16 OverrideConfig; ///< The override config bitmap (see: PCH_PCIE_OVERRIDE_CONFIG).
+ /**
+ The L1Substates Capability Offset Override. (applicable if bit 2 is set in OverrideConfig)
+ This field can be zero if only the L1 Substate value is going to be override.
+ **/
+ UINT16 L1SubstatesCapOffset;
+ /**
+ L1 Substate Capability Mask. (applicable if bit 2 is set in OverrideConfig)
+ Set to zero then the L1 Substate Capability [3:0] is ignored, and only L1s values are override.
+ Only bit [3:0] are applicable. Other bits are ignored.
+ **/
+ UINT8 L1SubstatesCapMask;
+ /**
+ L1 Substate Port Common Mode Restore Time Override. (applicable if bit 2 is set in OverrideConfig)
+ L1sCommonModeRestoreTime and L1sTpowerOnScale can have a valid value of 0, but not the L1sTpowerOnValue.
+ If L1sTpowerOnValue is zero, all L1sCommonModeRestoreTime, L1sTpowerOnScale, and L1sTpowerOnValue are ignored,
+ and only L1SubstatesCapOffset is override.
+ **/
+ UINT8 L1sCommonModeRestoreTime;
+ /**
+ L1 Substate Port Tpower_on Scale Override. (applicable if bit 2 is set in OverrideConfig)
+ L1sCommonModeRestoreTime and L1sTpowerOnScale can have a valid value of 0, but not the L1sTpowerOnValue.
+ If L1sTpowerOnValue is zero, all L1sCommonModeRestoreTime, L1sTpowerOnScale, and L1sTpowerOnValue are ignored,
+ and only L1SubstatesCapOffset is override.
+ **/
+ UINT8 L1sTpowerOnScale;
+ /**
+ L1 Substate Port Tpower_on Value Override. (applicable if bit 2 is set in OverrideConfig)
+ L1sCommonModeRestoreTime and L1sTpowerOnScale can have a valid value of 0, but not the L1sTpowerOnValue.
+ If L1sTpowerOnValue is zero, all L1sCommonModeRestoreTime, L1sTpowerOnScale, and L1sTpowerOnValue are ignored,
+ and only L1SubstatesCapOffset is override.
+ **/
+ UINT8 L1sTpowerOnValue;
+
+ /**
+ SnoopLatency bit definition
+ Note: All Reserved bits must be set to 0
+
+ BIT[15] - When set to 1b, indicates that the values in bits 9:0 are valid
+ When clear values in bits 9:0 will be ignored
+ BITS[14:13] - Reserved
+ BITS[12:10] - Value in bits 9:0 will be multiplied with the scale in these bits
+ 000b - 1 ns
+ 001b - 32 ns
+ 010b - 1024 ns
+ 011b - 32,768 ns
+ 100b - 1,048,576 ns
+ 101b - 33,554,432 ns
+ 110b - Reserved
+ 111b - Reserved
+ BITS[9:0] - Snoop Latency Value. The value in these bits will be multiplied with
+ the scale in bits 12:10
+
+ This field takes effect only if bit 3 is set in OverrideConfig.
+ **/
+ UINT16 SnoopLatency;
+ /**
+ NonSnoopLatency bit definition
+ Note: All Reserved bits must be set to 0
+
+ BIT[15] - When set to 1b, indicates that the values in bits 9:0 are valid
+ When clear values in bits 9:0 will be ignored
+ BITS[14:13] - Reserved
+ BITS[12:10] - Value in bits 9:0 will be multiplied with the scale in these bits
+ 000b - 1 ns
+ 001b - 32 ns
+ 010b - 1024 ns
+ 011b - 32,768 ns
+ 100b - 1,048,576 ns
+ 101b - 33,554,432 ns
+ 110b - Reserved
+ 111b - Reserved
+ BITS[9:0] - Non Snoop Latency Value. The value in these bits will be multiplied with
+ the scale in bits 12:10
+
+ This field takes effect only if bit 3 is set in OverrideConfig.
+ **/
+ UINT16 NonSnoopLatency;
+
+ /**
+ Forces LTR override to be permanent
+ The default way LTR override works is:
+ rootport uses LTR override values provided by BIOS until connected device sends an LTR message, then it will use values from the message
+ This settings allows force override of LTR mechanism. If it's enabled, then:
+ rootport will use LTR override values provided by BIOS forever; LTR messages sent from connected device will be ignored
+ **/
+ UINT8 ForceLtrOverride;
+ UINT8 Reserved[3];
+} PCH_PCIE_DEVICE_OVERRIDE;
+
+enum PCH_PCIE_SPEED {
+ PchPcieAuto,
+ PchPcieGen1,
+ PchPcieGen2,
+ PchPcieGen3
+};
+
+///
+/// The values before AutoConfig match the setting of PCI Express Base Specification 1.1, please be careful for adding new feature
+///
+typedef enum {
+ PchPcieAspmDisabled,
+ PchPcieAspmL0s,
+ PchPcieAspmL1,
+ PchPcieAspmL0sL1,
+ PchPcieAspmAutoConfig,
+ PchPcieAspmMax
+} PCH_PCIE_ASPM_CONTROL;
+
+/**
+ Refer to PCH EDS for the PCH implementation values corresponding
+ to below PCI-E spec defined ranges
+**/
+typedef enum {
+ PchPcieL1SubstatesDisabled,
+ PchPcieL1SubstatesL1_1,
+ PchPcieL1SubstatesL1_2,
+ PchPcieL1SubstatesL1_1_2,
+ PchPcieL1SubstatesMax
+} PCH_PCIE_L1SUBSTATES_CONTROL;
+
+enum PCH_PCIE_MAX_PAYLOAD {
+ PchPcieMaxPayload128 = 0,
+ PchPcieMaxPayload256,
+ PchPcieMaxPayloadMax
+};
+
+enum PCH_PCIE_COMPLETION_TIMEOUT {
+ PchPcieCompletionTO_Default,
+ PchPcieCompletionTO_50_100us,
+ PchPcieCompletionTO_1_10ms,
+ PchPcieCompletionTO_16_55ms,
+ PchPcieCompletionTO_65_210ms,
+ PchPcieCompletionTO_260_900ms,
+ PchPcieCompletionTO_1_3P5s,
+ PchPcieCompletionTO_4_13s,
+ PchPcieCompletionTO_17_64s,
+ PchPcieCompletionTO_Disabled
+};
+
+typedef enum {
+ PchPcieEqDefault = 0, ///< Use reference code default (software margining)
+ PchPcieEqHardware = 1, ///< Hardware equalization (experimental), note this requires PCH-LP C0 or PCH-H D0 or newer
+ PchPcieEqSoftware = 2, ///< Use software margining flow
+ PchPcieEqStaticCoeff = 4 ///< Fixed equalization (requires Coefficient settings per lane)
+} PCH_PCIE_EQ_METHOD;
+
+/**
+ Represent lane specific PCIe Gen3 equalization parameters.
+**/
+typedef struct {
+ UINT8 Cm; ///< Coefficient C-1
+ UINT8 Cp; ///< Coefficient C+1
+ UINT8 Rsvd0[2]; ///< Reserved bytes
+} PCH_PCIE_EQ_LANE_PARAM, PCH_PCIE_EQ_PARAM;
+
+/**
+ The PCH_PCI_EXPRESS_ROOT_PORT_CONFIG describe the feature and capability of each PCH PCIe root port.
+**/
+typedef struct {
+ UINT32 Enable : 1; ///< @deprecated.
+ UINT32 HotPlug : 1; ///< Indicate whether the root port is hot plug available. <b>0: Disable</b>; 1: Enable.
+ UINT32 PmSci : 1; ///< Indicate whether the root port power manager SCI is enabled. 0: Disable; <b>1: Enable</b>.
+ UINT32 ExtSync : 1; ///< Indicate whether the extended synch is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 TransmitterHalfSwing : 1; ///< Indicate whether the Transmitter Half Swing is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 AcsEnabled : 1; ///< Indicate whether the ACS is enabled. 0: Disable; <b>1: Enable</b>.
+ UINT32 RsvdBits0 : 5; ///< Reserved bits.
+ UINT32 ClkReqSupported : 1; ///< Indicate whether dedicated CLKREQ# is supported by the port.
+ /**
+ The ClkReq Signal mapped to this root port. Default is zero. Valid if ClkReqSupported is TRUE.
+ This Number should not exceed the Maximum Available ClkReq Signals for LP and H.
+ **/
+ UINT32 ClkReqNumber : 4;
+ /**
+ Probe CLKREQ# signal before enabling CLKREQ# based power management.
+ Conforming device shall hold CLKREQ# low until CPM is enabled. This feature attempts
+ to verify CLKREQ# signal is connected by testing pad state before enabling CPM.
+ In particular this helps to avoid issues with open-ended PCIe slots.
+ This is only applicable to non hot-plug ports.
+ <b>0: Disable</b>; 1: Enable.
+ **/
+ UINT32 ClkReqDetect : 1;
+ //
+ // Error handlings
+ //
+ UINT32 AdvancedErrorReporting : 1; ///< Indicate whether the Advanced Error Reporting is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 UnsupportedRequestReport : 1; ///< Indicate whether the Unsupported Request Report is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 FatalErrorReport : 1; ///< Indicate whether the Fatal Error Report is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 NoFatalErrorReport : 1; ///< Indicate whether the No Fatal Error Report is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 CorrectableErrorReport : 1; ///< Indicate whether the Correctable Error Report is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 SystemErrorOnFatalError : 1; ///< Indicate whether the System Error on Fatal Error is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 SystemErrorOnNonFatalError : 1; ///< Indicate whether the System Error on Non Fatal Error is enabled. <b>0: Disable</b>; 1: Enable.
+ UINT32 SystemErrorOnCorrectableError : 1; ///< Indicate whether the System Error on Correctable Error is enabled. <b>0: Disable</b>; 1: Enable.
+ /**
+ Max Payload Size supported, Default <b>128B</b>, see enum PCH_PCIE_MAX_PAYLOAD
+ Changes Max Payload Size Supported field in Device Capabilities of the root port.
+ **/
+ UINT32 MaxPayload : 2;
+ UINT32 EnableHotplugSmi : 1; ///< Indicate whether the Hotplug Smi for Rootport is enabled, for TBT rootport we need to disable hotplug smi. 0: Disable; <b>1: Enable </b>.
+ UINT32 RsvdBits1 : 3; ///< Reserved fields for future expansion w/o protocol change
+
+ UINT32 DeviceResetPadActiveHigh : 1; ///< Indicated whether PERST# is active <b>0: Low</b>; 1: High, See: DeviceResetPad
+ /**
+ Determines each PCIE Port speed capability.
+ <b>0: Auto</b>; 1: Gen1; 2: Gen2; 3: Gen3 (see: PCH_PCIE_SPEED)
+ **/
+ UINT8 PcieSpeed;
+ /**
+ PCIe Gen3 Equalization Phase 3 Method (see PCH_PCIE_EQ_METHOD).
+ <b>0: Default</b>; 2: Software Search; 4: Fixed Coefficients
+ **/
+ UINT8 Gen3EqPh3Method;
+
+ UINT8 PhysicalSlotNumber; ///< Indicates the slot number for the root port. Default is the value as root port index.
+ UINT8 CompletionTimeout; ///< The completion timeout configuration of the root port (see: PCH_PCIE_COMPLETION_TIMEOUT). Default is <b>PchPcieCompletionTO_Default</b>.
+ /**
+ The PCH pin assigned to device PERST# signal if available, zero otherwise.
+ This entry is used mainly in Gen3 software equalization flow. It is necessary for some devices
+ (mainly some graphic adapters) to successfully complete the software equalization flow.
+ See also DeviceResetPadActiveHigh
+ **/
+ UINT32 DeviceResetPad;
+ UINT32 Rsvd1; ///< Reserved bytes
+ //
+ // Power Management
+ //
+ UINT8 Aspm; ///< The ASPM configuration of the root port (see: PCH_PCIE_ASPM_CONTROL). Default is <b>PchPcieAspmAutoConfig</b>.
+ UINT8 L1Substates; ///< The L1 Substates configuration of the root port (see: PCH_PCIE_L1SUBSTATES_CONTROL). Default is <b>PchPcieL1SubstatesL1_1_2</b>.
+ UINT8 LtrEnable; ///< Latency Tolerance Reporting Mechanism. <b>0: Disable</b>; 1: Enable.
+ UINT8 LtrConfigLock; ///< <b>0: Disable</b>; 1: Enable.
+ UINT16 LtrMaxSnoopLatency; ///< <b>(Test)</b> Latency Tolerance Reporting, Max Snoop Latency.
+ UINT16 LtrMaxNoSnoopLatency; ///< <b>(Test)</b> Latency Tolerance Reporting, Max Non-Snoop Latency.
+ UINT8 SnoopLatencyOverrideMode; ///< <b>(Test)</b> Latency Tolerance Reporting, Snoop Latency Override Mode.
+ UINT8 SnoopLatencyOverrideMultiplier; ///< <b>(Test)</b> Latency Tolerance Reporting, Snoop Latency Override Multiplier.
+ UINT16 SnoopLatencyOverrideValue; ///< <b>(Test)</b> Latency Tolerance Reporting, Snoop Latency Override Value.
+ UINT8 NonSnoopLatencyOverrideMode; ///< <b>(Test)</b> Latency Tolerance Reporting, Non-Snoop Latency Override Mode.
+ UINT8 NonSnoopLatencyOverrideMultiplier; ///< <b>(Test)</b> Latency Tolerance Reporting, Non-Snoop Latency Override Multiplier.
+ UINT16 NonSnoopLatencyOverrideValue; ///< <b>(Test)</b> Latency Tolerance Reporting, Non-Snoop Latency Override Value.
+ UINT32 SlotPowerLimitScale : 2; ///< <b>(Test)</b> Specifies scale used for slot power limit value. Leave as 0 to set to default. Default is <b>zero</b>.
+ UINT32 SlotPowerLimitValue : 12; ///< <b>(Test)</b> Specifies upper limit on power supplies by slot. Leave as 0 to set to default. Default is <b>zero</b>.
+ //
+ // Gen3 Equalization settings
+ //
+ UINT32 Uptp : 4; ///< <b>(Test)</b> Upstream Port Transmitter Preset used during Gen3 Link Equalization. Used for all lanes. Default is <b>5</b>.
+ UINT32 Dptp : 4; ///< <b>(Test)</b> Downstream Port Transmiter Preset used during Gen3 Link Equalization. Used for all lanes. Default is <b>7</b>.
+ /**
+ Forces LTR override to be permanent
+ The default way LTR override works is:
+ rootport uses LTR override values provided by BIOS until connected device sends an LTR message, then it will use values from the message
+ This settings allows force override of LTR mechanism. If it's enabled, then:
+ rootport will use LTR override values provided by BIOS forever; LTR messages sent from connected device will be ignored
+ **/
+ UINT32 ForceLtrOverride : 1;
+ UINT32 EnableCpm : 1; ///< Enables Clock Power Management; even if disabled, CLKREQ# signal can still be controlled by L1 PM substates mechanism
+ UINT32 RsvdBits3 : 8; ///< Reserved Bits
+ /**
+ The number of milliseconds reference code will wait for link to exit Detect state for enabled ports
+ before assuming there is no device and potentially disabling the port.
+ It's assumed that the link will exit detect state before root port initialization (sufficient time
+ elapsed since PLTRST de-assertion) therefore default timeout is zero. However this might be useful
+ if device power-up seqence is controlled by BIOS or a specific device requires more time to detect.
+ In case of non-common clock enabled the default timout is 15ms.
+ <b>Default: 0</b>
+ **/
+ UINT16 DetectTimeoutMs;
+ UINT16 Rsvd2; ///< Reserved bytes
+ UINT32 Rsvd3; ///< Reserved bytes
+} PCH_PCIE_ROOT_PORT_CONFIG;
+
+/**
+ The PCH_PCIE_CONFIG block describes the expected configuration of the PCH PCI Express controllers
+ <b>Revision 1</b>: Init version
+ <b>Revision 2</b>: Deprecate the PCIE RP enable in post mem.
+ <b>Revision 3</b>: Added DetectTimeoutMs parameter per port. The common DetectTimeoutMs is obsolete.
+ <b>Revision 4</b>: Added EnableHotplugSmi parameter per port.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ ///
+ /// These members describe the configuration of each PCH PCIe root port.
+ ///
+ PCH_PCIE_ROOT_PORT_CONFIG RootPort[PCH_MAX_PCIE_ROOT_PORTS];
+ ///
+ /// Gen3 Equalization settings for physical PCIe lane, index 0 represents PCIe lane 1, etc.
+ /// Corresponding entries are used when root port EqPh3Method is PchPcieEqStaticCoeff (default).
+ ///
+ PCH_PCIE_EQ_LANE_PARAM EqPh3LaneParam[PCH_MAX_PCIE_ROOT_PORTS];
+ ///
+ /// List of coefficients used during equalization (applicable to both software and hardware EQ)
+ ///
+ PCH_PCIE_EQ_PARAM SwEqCoeffList[PCH_PCIE_SWEQ_COEFFS_MAX];
+ PCH_PCIE_EQ_PARAM Rsvd0[3];
+ ///
+ /// <b>(Test)</b> This member describes whether PCIE root port Port 8xh Decode is enabled. <b>0: Disable</b>; 1: Enable.
+ ///
+ UINT32 EnablePort8xhDecode : 1;
+ ///
+ /// <b>(Test)</b> The Index of PCIe Port that is selected for Port8xh Decode (0 Based)
+ ///
+ UINT32 PchPciePort8xhDecodePortIndex : 5;
+ ///
+ /// This member describes whether the PCI Express Clock Gating for each root port
+ /// is enabled by platform modules. <b>0: Disable</b>; 1: Enable.
+ ///
+ UINT32 DisableRootPortClockGating : 1;
+ ///
+ /// This member describes whether Peer Memory Writes are enabled on the platform. <b>0: Disable</b>; 1: Enable.
+ ///
+ UINT32 EnablePeerMemoryWrite : 1;
+ /**
+ This member allows BIOS to control ICC PLL Shutdown by determining PCIe devices are LTR capable
+ or leaving untouched.
+ - <b>0: Disable, ICC PLL Shutdown is determined by PCIe device LTR capablility.</b>
+ - To allow ICC PLL shutdown if all present PCIe devices are LTR capable or if no PCIe devices are
+ presented for maximum power savings where possible.
+ - To disable ICC PLL shutdown when BIOS detects any non-LTR capable PCIe device for ensuring device
+ functionality.
+ - 1: Enable, To allow ICC PLL shutdown even if some devices do not support LTR capability.
+ **/
+ UINT32 AllowNoLtrIccPllShutdown : 1;
+ /**
+ Compliance Test Mode shall be enabled when using Compliance Load Board.
+ <b>0: Disable</b>, 1: Enable
+ **/
+ UINT32 ComplianceTestMode : 1;
+ /**
+ RpFunctionSwap allows BIOS to use root port function number swapping when root port of function 0 is disabled.
+ A PCIE device can have higher functions only when Function0 exists. To satisfy this requirement,
+ BIOS will always enable Function0 of a device that contains more than 0 enabled root ports.
+ - <b>Enabled: One of enabled root ports get assigned to Function0.</b>
+ This offers no guarantee that any particular root port will be available at a specific DevNr:FuncNr location
+ - Disabled: Root port that corresponds to Function0 will be kept visible even though it might be not used.
+ That way rootport - to - DevNr:FuncNr assignment is constant. This option will impact ports 1, 9, 17.
+ NOTE: This option will not work if ports 1, 9, 17 are fused or configured for RST PCIe storage
+ NOTE: Disabling function swap may have adverse impact on power management. This option should ONLY
+ be used when each one of root ports 1, 9, 17:
+ - is configured as PCIe and has correctly configured ClkReq signal, or
+ - does not own any mPhy lanes (they are configured as SATA or USB)
+ **/
+ UINT32 RpFunctionSwap : 1;
+
+ UINT32 RsvdBits0 : 21;
+ /**
+ @deprecated since revision 3, substituted by per-port timeout parameter
+ The number of milliseconds reference code will wait for link to exit Detect state for enabled ports
+ before assuming there is no device and potentially disabling the port.
+ It's assumed that the link will exit detect state before root port initialization (sufficient time
+ elapsed since PLTRST de-assertion) therefore default timeout is zero. However this might be useful
+ if device power-up sequence is controlled by BIOS or a specific device requires more time to detect.
+ I case of non-common clock enabled the default timeout is 15ms.
+ <b>Default: 0</b>
+ **/
+ UINT16 DetectTimeoutMs;
+ UINT16 Rsvd1; ///< Reserved bytes
+ /**
+ PCIe device override table
+ The PCIe device table is being used to override PCIe device ASPM settings.
+ This is a pointer points to a 32bit address. And it's only used in PostMem phase.
+ Please refer to PCH_PCIE_DEVICE_OVERRIDE structure for the table.
+ Last entry VendorId must be 0.
+ The prototype of this policy is:
+ PCH_PCIE_DEVICE_OVERRIDE *PcieDeviceOverrideTablePtr;
+ **/
+ UINT32 PcieDeviceOverrideTablePtr;
+
+} PCH_PCIE_CONFIG;
+
+/**
+ The PCH_PCIE_RP_PREMEM_CONFIG block describes early configuration of the PCH PCI Express controllers
+ Revision 1: Init version
+ Add RpEnable in premem phase.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Root Port enabling mask.
+ Bit0 presents RP1, Bit1 presents RP2, and so on.
+ 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 RpEnabledMask;
+} PCH_PCIE_RP_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PCH_PCIE_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PmConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PmConfig.h
new file mode 100644
index 0000000000..f483987c97
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/PmConfig.h
@@ -0,0 +1,215 @@
+/** @file
+ Power Management policy
+
+Copyright (c) 2017, 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 that 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 _PM_CONFIG_H_
+#define _PM_CONFIG_H_
+
+#define PM_CONFIG_REVISION 4
+extern EFI_GUID gPmConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure allows to customize PCH wake up capability from S5 or DeepSx by WOL, LAN, PCIE wake events.
+**/
+typedef struct {
+ /**
+ Corresponds to the PME_B0_S5_DIS bit in the General PM Configuration B (GEN_PMCON_B) register.
+ When set to 1, this bit blocks wake events from PME_B0_STS in S5, regardless of the state of PME_B0_EN.
+ When cleared (default), wake events from PME_B0_STS are allowed in S5 if PME_B0_EN = 1. <b>0: Disable</b>; 1: Enable.
+ **/
+ UINT32 PmeB0S5Dis : 1;
+ UINT32 WolEnableOverride : 1; ///< Corresponds to the "WOL Enable Override" bit in the General PM Configuration B (GEN_PMCON_B) register. 0: Disable; <b>1: Enable</b>.
+ UINT32 PcieWakeFromDeepSx : 1; ///< Determine if enable PCIe to wake from deep Sx. <b>0: Disable</b>; 1: Enable.
+ UINT32 WoWlanEnable : 1; ///< Determine if WLAN wake from Sx, corresponds to the "HOST_WLAN_PP_EN" bit in the PWRM_CFG3 register. <b>0: Disable</b>; 1: Enable.
+ UINT32 WoWlanDeepSxEnable : 1; ///< Determine if WLAN wake from DeepSx, corresponds to the "DSX_WLAN_PP_EN" bit in the PWRM_CFG3 register. <b>0: Disable</b>; 1: Enable.
+ UINT32 LanWakeFromDeepSx : 1; ///< Determine if enable LAN to wake from deep Sx. 0: Disable; <b>1: Enable</b>.
+ UINT32 RsvdBits0 : 26;
+} PCH_WAKE_CONFIG;
+
+typedef enum {
+ PchDeepSxPolDisable,
+ PchDpS5BatteryEn,
+ PchDpS5AlwaysEn,
+ PchDpS4S5BatteryEn,
+ PchDpS4S5AlwaysEn,
+ PchDpS3S4S5BatteryEn,
+ PchDpS3S4S5AlwaysEn
+} PCH_DEEP_SX_CONFIG;
+
+typedef enum {
+ PchSlpS360us,
+ PchSlpS31ms,
+ PchSlpS350ms,
+ PchSlpS32s
+} PCH_SLP_S3_MIN_ASSERT;
+
+typedef enum {
+ PchSlpS4PchTime, ///< The time defined in PCH EDS Power Sequencing and Reset Signal Timings table
+ PchSlpS41s,
+ PchSlpS42s,
+ PchSlpS43s,
+ PchSlpS44s
+} PCH_SLP_S4_MIN_ASSERT;
+
+typedef enum {
+ PchSlpSus0ms,
+ PchSlpSus500ms,
+ PchSlpSus1s,
+ PchSlpSus4s
+} PCH_SLP_SUS_MIN_ASSERT;
+
+typedef enum {
+ PchSlpA0ms,
+ PchSlpA4s,
+ PchSlpA98ms,
+ PchSlpA2s
+} PCH_SLP_A_MIN_ASSERT;
+
+/**
+ The PCH_PM_CONFIG block describes expected miscellaneous power management settings.
+ The PowerResetStatusClear field would clear the Power/Reset status bits, please
+ set the bits if you want PCH Init driver to clear it, if you want to check the
+ status later then clear the bits.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Deprecate CapsuleResetType and the capsule update always uses warmreset cycle.
+ <b>Revision 3</b>:
+ - Added SlpS0VmEnable.
+ <b>Revision 4</b>
+ - Deprecate PciePllSsc and moved to PCH_HSIO_PCIE_PREMEM_CONFIG
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+
+ PCH_WAKE_CONFIG WakeConfig; ///< Specify Wake Policy
+ UINT32 PchDeepSxPol : 4; ///< Deep Sx Policy. Refer to PCH_DEEP_SX_CONFIG for each value. Default is <b>PchDeepSxPolDisable</b>.
+ UINT32 PchSlpS3MinAssert : 4; ///< SLP_S3 Minimum Assertion Width Policy. Refer to PCH_SLP_S3_MIN_ASSERT for each value. Default is <b>PchSlpS350ms</b>.
+ UINT32 PchSlpS4MinAssert : 4; ///< SLP_S4 Minimum Assertion Width Policy. Refer to PCH_SLP_S4_MIN_ASSERT for each value. Default is <b>PchSlpS44s</b>.
+ UINT32 PchSlpSusMinAssert : 4; ///< SLP_SUS Minimum Assertion Width Policy. Refer to PCH_SLP_SUS_MIN_ASSERT for each value. Default is <b>PchSlpSus4s</b>.
+ UINT32 PchSlpAMinAssert : 4; ///< SLP_A Minimum Assertion Width Policy. Refer to PCH_SLP_A_MIN_ASSERT for each value. Default is <b>PchSlpA2s</b>.
+ UINT32 RsvdBits0 : 12;
+ /**
+ This member describes whether or not the LPC ClockRun feature of PCH should
+ be enabled. <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 LpcClockRun : 1;
+ UINT32 SlpStrchSusUp : 1; ///< <b>0: Disable</b>; 1: Enable SLP_X Stretching After SUS Well Power Up
+ /**
+ Enable/Disable SLP_LAN# Low on DC Power. 0: Disable; <b>1: Enable</b>.
+ Configure On DC PHY Power Diable according to policy SlpLanLowDc.
+ When this is enabled, SLP_LAN# will be driven low when ACPRESENT is low.
+ This indicates that LAN PHY should be powered off on battery mode.
+ This will override the DC_PP_DIS setting by WolEnableOverride.
+ **/
+ UINT32 SlpLanLowDc : 1;
+ /**
+ PCH power button override period.
+ 000b-4s, 001b-6s, 010b-8s, 011b-10s, 100b-12s, 101b-14s
+ <b>Default is 0: 4s</b>
+ **/
+ UINT32 PwrBtnOverridePeriod : 3;
+ /**
+ <b>(Test)</b>
+ Disable/Enable PCH to CPU enery report feature. <b>0: Disable</b>; 1: Enable.
+ Enery Report is must have feature. Wihtout Energy Report, the performance report
+ by workloads/benchmarks will be unrealistic because PCH's energy is not being accounted
+ in power/performance management algorithm.
+ If for some reason PCH energy report is too high, which forces CPU to try to reduce
+ its power by throttling, then it could try to disable Energy Report to do first debug.
+ This might be due to energy scaling factors are not correct or the LPM settings are not
+ kicking in.
+ **/
+ UINT32 DisableEnergyReport : 1;
+ /**
+ When set to Disable, PCH will internal pull down AC_PRESENT in deep SX and during G3 exit.
+ When set to Enable, PCH will not pull down AC_PRESENT.
+ This setting is ignored when DeepSx is not supported.
+ Default is <b>0:Disable</b>
+ **/
+ UINT32 DisableDsxAcPresentPulldown : 1;
+ /**
+ <b>(Test)</b>
+ When set to true, this bit disallows host reads to PMC XRAM.
+ BIOS must set this bit (to disable and lock the feature) prior to passing control to OS
+ 0:Disable, <b>1:Enable</b>
+ **/
+ UINT32 PmcReadDisable : 1;
+ /**
+ @deprecated This determines the type of reset issued during the capsule update process by UpdateCapsule().
+ Always Warm reset.
+ **/
+ UINT32 CapsuleResetType : 1;
+ /**
+ Power button native mode disable.
+ While FALSE, the PMC's power button logic will act upon the input value from the GPIO unit, as normal.
+ While TRUE, this will result in the PMC logic constantly seeing the power button as de-asserted.
+ <b>Default is FALSE.</b>
+ **/
+ UINT32 DisableNativePowerButton : 1;
+ /**
+ Indicates whether SLP_S0# is to be asserted when PCH reaches idle state.
+ When set to one SLP_S0# will be asserted in idle state.
+ When set to zero SLP_S0# will not toggle and is always drivern high.
+ 0:Disable, <b>1:Enable</b>
+
+ @warning: In SKL PCH VCCPRIM_CORE must NOT be reduced based on SLP_S0# being asserted.
+ If a platform is using SLP_S0 to lower PCH voltage the below policy must be disabled.
+ **/
+ UINT32 SlpS0Enable : 1;
+ UINT32 MeWakeSts : 1; ///< Clear the ME_WAKE_STS bit in the Power and Reset Status (PRSTS) register. 0: Disable; <b>1: Enable</b>.
+ UINT32 WolOvrWkSts : 1; ///< Clear the WOL_OVR_WK_STS bit in the Power and Reset Status (PRSTS) register. 0: Disable; <b>1: Enable</b>.
+ /**
+ Set true to enable TCO timer.
+ When FALSE, it disables PCH ACPI timer, and stops TCO timer.
+ @note: This will have significant power impact when it's enabled.
+ If TCO timer is disabled, uCode ACPI timer emulation must be enabled,
+ and WDAT table must not be exposed to the OS.
+ <b>0: Disable</b>, 1: Enable
+ **/
+ UINT32 EnableTcoTimer : 1;
+ /**
+ Indicates platform has support for VCCPrim_Core Voltage Margining in SLP_S0# asserted state.
+ 0: Disable, <b>1: Enable</b>
+ **/
+ UINT32 SlpS0VmEnable : 1;
+ UINT32 RsvdBits1 : 16;
+ /**
+ Reset Power Cycle Duration could be customized in the unit of second. Please refer to EDS
+ for all support settings. PCH HW default is 4 seconds, and range is 1~4 seconds, where
+ <b>0 is default</b>, 1 is 1 second, 2 is 2 seconds, ... 4 is 4 seconds.
+ And make sure the setting correct, which never less than the following register.
+ - GEN_PMCON_B.SLP_S3_MIN_ASST_WDTH
+ - GEN_PMCON_B.SLP_S4_MIN_ASST_WDTH
+ - PWRM_CFG.SLP_A_MIN_ASST_WDTH
+ - PWRM_CFG.SLP_LAN_MIN_ASST_WDTH
+ **/
+ UINT8 PchPwrCycDur;
+ /**
+ @deprecated since revision 4
+ Specifies the Pcie Pll Spread Spectrum Percentage
+ The value of this policy is in 1/10th percent units.
+ Valid spread range is 0-20. A value of 0xFF is reserved for AUTO.
+ A value of 0 is SSC of 0.0%. A value of 20 is SSC of 2.0%
+ The default is <b>0xFF: AUTO - No BIOS override</b>.
+ **/
+ UINT8 PciePllSsc;
+ UINT8 Rsvd0[2]; ///< Reserved bytes
+
+} PCH_PM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PM_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Port61Config.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Port61Config.h
new file mode 100644
index 0000000000..d8b9cf6145
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/Port61Config.h
@@ -0,0 +1,34 @@
+/** @file
+ Port 61h policy
+
+Copyright (c) 2017, 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 that 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 _PORT_61_CONFIG_H_
+#define _PORT_61_CONFIG_H_
+
+#define PORT_61_CONFIG_REVISION 1
+extern EFI_GUID gPort61ConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure is used for the emulation feature for Port61h read. The port is trapped
+ and the SMI handler will toggle bit4 according to the handler's internal state.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 Enable : 1; ///< 0: Disable; <b>1: Enable</b> the emulation
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PCH_PORT61H_SMM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PORT_61_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SataConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SataConfig.h
new file mode 100644
index 0000000000..0dc76e0c23
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SataConfig.h
@@ -0,0 +1,193 @@
+/** @file
+ Sata policy
+
+Copyright (c) 2017, 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 that 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 _SATA_CONFIG_H_
+#define _SATA_CONFIG_H_
+
+#define SATA_CONFIG_REVISION 4
+extern EFI_GUID gSataConfigGuid;
+
+#pragma pack (push,1)
+
+typedef enum {
+ PchSataModeAhci,
+ PchSataModeRaid,
+ PchSataModeMax
+} PCH_SATA_MODE;
+
+enum {
+ PchSataOromDelay2sec,
+ PchSataOromDelay4sec,
+ PchSataOromDelay6sec,
+ PchSataOromDelay8sec
+} PCH_SATA_OROM_DELAY;
+
+typedef enum {
+ PchSataSpeedDefault,
+ PchSataSpeedGen1,
+ PchSataSpeedGen2,
+ PchSataSpeedGen3
+} PCH_SATA_SPEED;
+
+/**
+ This structure configures the features, property, and capability for each SATA port.
+**/
+typedef struct {
+ /**
+ Enable SATA port.
+ It is highly recommended to disable unused ports for power savings
+ **/
+ UINT32 Enable : 1; ///< 0: Disable; <b>1: Enable</b>
+ UINT32 HotPlug : 1; ///< <b>0: Disable</b>; 1: Enable
+ UINT32 InterlockSw : 1; ///< <b>0: Disable</b>; 1: Enable
+ UINT32 External : 1; ///< <b>0: Disable</b>; 1: Enable
+ UINT32 SpinUp : 1; ///< <b>0: Disable</b>; 1: Enable the COMRESET initialization Sequence to the device
+ UINT32 SolidStateDrive : 1; ///< <b>0: HDD</b>; 1: SSD
+ UINT32 DevSlp : 1; ///< <b>0: Disable</b>; 1: Enable DEVSLP on the port
+ UINT32 EnableDitoConfig : 1; ///< <b>0: Disable</b>; 1: Enable DEVSLP Idle Timeout settings (DmVal, DitoVal)
+ UINT32 DmVal : 4; ///< DITO multiplier. Default is <b>15</b>.
+ UINT32 DitoVal : 10; ///< DEVSLP Idle Timeout (DITO), Default is <b>625</b>.
+ /**
+ Support zero power ODD <b>0: Disable</b>, 1: Enable.
+ This is also used to disable ModPHY dynamic power gate.
+ **/
+ UINT32 ZpOdd : 1;
+ UINT32 RsvdBits0 : 9; ///< Reserved fields for future expansion w/o protocol change
+} PCH_SATA_PORT_CONFIG;
+
+/**
+ Rapid Storage Technology settings.
+**/
+typedef struct {
+ UINT32 RaidAlternateId : 1; ///< @deprecated
+ UINT32 Raid0 : 1; ///< 0: Disable; <b>1: Enable</b> RAID0
+ UINT32 Raid1 : 1; ///< 0: Disable; <b>1: Enable</b> RAID1
+ UINT32 Raid10 : 1; ///< 0: Disable; <b>1: Enable</b> RAID10
+ UINT32 Raid5 : 1; ///< 0: Disable; <b>1: Enable</b> RAID5
+ UINT32 Irrt : 1; ///< 0: Disable; <b>1: Enable</b> Intel Rapid Recovery Technology
+ UINT32 OromUiBanner : 1; ///< 0: Disable; <b>1: Enable</b> OROM UI and BANNER
+ UINT32 OromUiDelay : 2; ///< <b>00b: 2 secs</b>; 01b: 4 secs; 10b: 6 secs; 11: 8 secs (see: PCH_SATA_OROM_DELAY)
+ UINT32 HddUnlock : 1; ///< 0: Disable; <b>1: Enable</b>. Indicates that the HDD password unlock in the OS is enabled
+ UINT32 LedLocate : 1; ///< 0: Disable; <b>1: Enable</b>. Indicates that the LED/SGPIO hardware is attached and ping to locate feature is enabled on the OS
+ UINT32 IrrtOnly : 1; ///< 0: Disable; <b>1: Enable</b>. Allow only IRRT drives to span internal and external ports
+ UINT32 SmartStorage : 1; ///< 0: Disable; <b>1: Enable</b> RST Smart Storage caching Bit
+ UINT32 LegacyOrom : 1; ///< <b>0: Disable</b>; 1: Enable RST Legacy OROM
+ /**
+ This option allows to configure SATA controller device ID while in RAID mode
+ Choosing Client will allow RST driver loading, RSTe driver will not be able to load
+ Choosing Alternate will not allow RST inbox driver loading in Windows
+ Choosing Server will allow RSTe driver loading, RST driver will not load
+ <b>0: Client</b>; 1: Alternate; 2: Server
+ **/
+ UINT32 RaidDeviceId : 2;
+ UINT32 OptaneMemory : 1; ///< 0: Disable; <b>1: Enable</b> RST Optane(TM) Memory
+ UINT32 RsvdBits0 : 15; ///< Reserved Bits
+} PCH_SATA_RST_CONFIG;
+
+/**
+ This structure describes the details of Intel RST for PCIe Storage remapping
+ Note: In order to use this feature, Intel RST Driver is required
+**/
+typedef struct {
+ /**
+ This member describes whether or not the Intel RST for PCIe Storage remapping should be enabled. <b>0: Disable</b>; 1: Enable.
+ Note 1: If Sata Controller is disabled, PCIe Storage Remapping should be disabled as well
+ Note 2: If PCIe Storage remapping is enabled, the PCH integrated AHCI controllers Class Code is configured as RAID
+ **/
+ UINT32 Enable : 1;
+ /**
+ Intel RST for PCIe Storage remapping - PCIe Port Selection (1-based, <b>0 = autodetect</b>)
+ The supported ports for PCIe Storage remapping is different depend on the platform and cycle router, the assignments are as below:
+ SKL PCH-LP RST PCIe Storage Cycle Router Assignment:
+ i.) RST PCIe Storage Cycle Router 2 -> RP5 - RP8
+ ii.) RST PCIe Storage Cycle Router 3 -> RP9 - RP12
+
+ SKL PCH-H RST PCIe Storage Cycle Router Assignment:
+ i.) RST PCIe Storage Cycle Router 1 -> RP9 - RP12
+ ii.) RST PCIe Storage Cycle Router 2 -> RP13 - RP16
+ iii.) RST PCIe Storage Cycle Router 3 -> RP17 - RP20
+ **/
+ UINT32 RstPcieStoragePort : 5;
+ UINT32 RsvdBits0 : 2; ///< Reserved bit
+ /**
+ PCIe Storage Device Reset Delay in milliseconds (ms), which it guarantees such delay gap is fulfilled
+ before PCIe Storage Device configuration space is accessed after an reset caused by the link disable and enable step.
+ Default value is <b>100ms</b>.
+ **/
+ UINT32 DeviceResetDelay : 8;
+ UINT32 RsvdBits1 : 16; ///< Reserved bits
+
+ UINT32 Rsvd0[2]; ///< Reserved bytes
+} PCH_RST_PCIE_STORAGE_CONFIG;
+
+/**
+ The PCH_SATA_CONFIG block describes the expected configuration of the SATA controllers.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Added LegacyOrom in RST_SATA_RST_CONFIG to force RST Legacy Orom useage
+ <b>Revision 3</b>
+ - Added RaidDeviceId in PCH_SATA_RST_CONFIG to allow choice of RAID device id
+ <b>Revision 4</b>
+ - Added OptaneMemory in PCH_SATA_RST_CONFIG to enable RST optane memory
+**/
+typedef struct {
+ /**
+ This member specifies the revision of the SATA Configuration structure.
+ Any backwards compatible changes to this structure will result in an update in the revision number.
+ **/
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ ///
+ /// This member describes whether or not the SATA controllers should be enabled. 0: Disable; <b>1: Enable</b>.
+ ///
+ UINT32 Enable : 1;
+ UINT32 TestMode : 1; ///< <b>(Test)</b> <b>0: Disable</b>; 1: Allow entrance to the PCH SATA test modes
+ UINT32 SalpSupport : 1; ///< 0: Disable; <b>1: Enable</b> Aggressive Link Power Management
+ UINT32 PwrOptEnable : 1; ///< 0: Disable; <b>1: Enable</b> SATA Power Optimizer on PCH side.
+ /**
+ EsataSpeedLimit
+ When enabled, BIOS will configure the PxSCTL.SPD to 2 to limit the eSATA port speed.
+ Please be noted, this setting could be cleared by HBA reset, which might be issued
+ by EFI AHCI driver when POST time, or by SATA inbox driver/RST driver after POST.
+ To support the Speed Limitation when POST, the EFI AHCI driver should preserve the
+ setting before and after initialization. For support it after POST, it's dependent on
+ driver's behavior.
+ <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 EsataSpeedLimit : 1;
+ UINT32 RsvdBits0 : 27; ///< Reserved bits
+
+ /**
+ Determines the system will be configured to which SATA mode (PCH_SATA_MODE). Default is <b>PchSataModeAhci</b>.
+ **/
+ PCH_SATA_MODE SataMode;
+ /**
+ Indicates the maximum speed the SATA controller can support
+ <b>0h: PchSataSpeedDefault</b>; 1h: 1.5 Gb/s (Gen 1); 2h: 3 Gb/s(Gen 2); 3h: 6 Gb/s (Gen 1)
+ **/
+ PCH_SATA_SPEED SpeedLimit;
+ /**
+ This member configures the features, property, and capability for each SATA port.
+ **/
+ PCH_SATA_PORT_CONFIG PortSettings[PCH_MAX_SATA_PORTS];
+ PCH_SATA_RST_CONFIG Rst; ///< Setting applicable to Rapid Storage Technology
+ /**
+ This member describes the details of implementation of Intel RST for PCIe Storage remapping (Intel RST Driver is required)
+ **/
+ PCH_RST_PCIE_STORAGE_CONFIG RstPcieStorageRemap[PCH_MAX_RST_PCIE_STORAGE_CR];
+} PCH_SATA_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SATA_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ScsConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ScsConfig.h
new file mode 100644
index 0000000000..05a2f5dbfa
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ScsConfig.h
@@ -0,0 +1,61 @@
+/** @file
+ Scs policy
+
+Copyright (c) 2017, 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 that 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 _SCS_CONFIG_H_
+#define _SCS_CONFIG_H_
+
+#define SCS_CONFIG_REVISION 1
+extern EFI_GUID gScsConfigGuid;
+
+#pragma pack (push,1)
+
+typedef enum {
+ PchScsSdDisabled = 0,
+ PchScsSdcardMode = 2
+} PCH_SCS_DEV_SD_MODE;
+
+typedef enum {
+ DriverStrength33Ohm = 0,
+ DriverStrength40Ohm,
+ DriverStrength50Ohm
+} PCH_SCS_EMMC_DRIVER_STRENGTH;
+
+///
+/// The PCH_SCS_CONFIG block describes Storage and Communication Subsystem (SCS) settings for PCH.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+
+ UINT32 ScsEmmcEnabled : 2; ///< Determine if eMMC is enabled - 0: Disabled, <b>1: Enabled</b>.
+ UINT32 ScsEmmcHs400Enabled : 1; ///< Determine eMMC HS400 Mode if ScsEmmcEnabled - <b>0: Disabled</b>, 1: Enabled
+ /**
+ Determine if HS400 Training is required, set to FALSE if Hs400 Data is valid. <b>0: Disabled</b>, 1: Enabled.
+ First Boot or CMOS clear, system boot with Default settings, set tuning required.
+ Subsequent Boots, Get Variable 'Hs400TuningData'
+ - if failed to get variable, set tuning required
+ - if passed, retrieve Hs400DataValid, Hs400RxStrobe1Dll and Hs400TxDataDll from variable. Set tuning not required.
+ - if driver strength value changes (ScsEmmcHs400DriverStrength) re-tuning is required.
+ **/
+ UINT32 ScsEmmcHs400TuningRequired : 1;
+ UINT32 ScsEmmcHs400DllDataValid : 1; ///< Set if HS400 Tuning Data Valid
+ UINT32 ScsEmmcHs400RxStrobeDll1 : 7; ///< Rx Strobe Delay Control - Rx Strobe Delay DLL 1 (HS400 Mode)
+ UINT32 ScsEmmcHs400TxDataDll : 7; ///< Tx Data Delay Control 1 - Tx Data Delay (HS400 Mode)
+ UINT32 ScsEmmcHs400DriverStrength : 3; ///< I/O driver strength: 0 - 33 Ohm, <b>1 - 40 Ohm</b>, 2 - 50 Ohm
+ UINT32 ScsSdSwitch : 3; ///< Determine the operating mode of SDHC. Refer to PCH_SCS_DEV_SD_MODE for each value - 0: Disabled, <b>2: SDCard</b>.
+ UINT32 RsvdBits : 7;
+ UINT32 Rsvd0; ///< Reserved bytes
+} PCH_SCS_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SCS_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIoConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIoConfig.h
new file mode 100644
index 0000000000..5caa24310a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIoConfig.h
@@ -0,0 +1,56 @@
+/** @file
+ Serial IO policy
+
+Copyright (c) 2017, 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 that 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 _SERIAL_IO_CONFIG_H_
+#define _SERIAL_IO_CONFIG_H_
+
+#define SERIAL_IO_CONFIG_REVISION 1
+extern EFI_GUID gSerialIoConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_SERIAL_IO_CONFIG block provides the configurations to set the Serial IO controllers
+ to Acpi devices or Pci controllers, and also set the interrupt type to Acpi or Pci
+ through Policy. It also provides to configure the I2c0 and I2c1 voltage
+ to 1.8v or 3.3v by platform setting.
+ Please refer to PeiDxeSmmPchSerialIoLib.h for definition of device numbers and enum values for the below fields
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ 0: Disabled; 1: ACPI Mode; <b>2: PCI Mode</b>; 3: Hidden mode, 4: Legacy UART mode, 5: Skip Init
+ @note: Considering the PcdSerialIoUartDebugEnable and PcdSerialIoUartNumber for all SerialIo UARTx,
+ the PCD is more meaningful to represent the board design. It means, if PcdSerialIoUartDebugEnable is not 0,
+ the board is designed to use the SerialIo UART for debug message and the PcdSerialIoUartNumber is dedicated
+ to be Debug UART usage. Therefore, it should grayout the option from setup menu since no other options
+ available for this UART controller on this board, and also override the policy default accordingly.
+ While PcdSerialIoUartDebugEnable is 0, then it's allowed to configure the UART controller by policy.
+ @note: While DevMode is set to 5 (Skip Init), BIOS will not initialize this controller. GPIO and PSF configuration is skipped.
+ Platform is resonsible for configuring this controller. If platform initializes the Serial IO controller in
+ Hidden Mode, it MUST follow the predefined BAR address for the controller.
+ **/
+ UINT8 DevMode[PCH_SERIALIO_MAX_CONTROLLERS];
+ UINT8 Gpio; ///< 0: Disabled; <b>1: Enabled</b>.
+ UINT8 I2cVoltage[PCH_SERIALIO_MAX_I2C_CONTROLLERS]; ///< Selects the IO voltage for I2C controllers. It can be 1.8v or 3.3v. <b>0: PchSerialIoIs33V</b>; 1: PchSerialIoIs18V.
+ UINT8 SpiCsPolarity[PCH_SERIALIO_MAX_SPI_CONTROLLERS]; ///< Selects SPI ChipSelect signal polarity, <b>0=active low</b>.
+ UINT8 UartHwFlowCtrl[PCH_SERIALIO_MAX_UART_CONTROLLERS]; ///< Enables UART hardware flow control, CTS and RTS lines, <b>0:disabled</b>, 1:enabled
+ UINT8 Rsvd0[1]; ///< Bytes reserved for reuse when new fields are added to struct
+ UINT32 DebugUartNumber : 2; ///< UART number for debug purpose. 0:UART0, 1: UART1, <b>2:UART2</b>
+ UINT32 EnableDebugUartAfterPost : 1; ///< Enable debug UART controller after post. 0: diabled, <b>1: enabled</b>
+ UINT32 RsvdBits0 : 29;
+} PCH_SERIAL_IO_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SERIAL_IO_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIrqConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIrqConfig.h
new file mode 100644
index 0000000000..b64579cd92
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SerialIrqConfig.h
@@ -0,0 +1,48 @@
+/** @file
+ Serial IRQ policy
+
+Copyright (c) 2017, 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 that 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 _SERIAL_IRQ_CONFIG_H_
+#define _SERIAL_IRQ_CONFIG_H_
+
+#define SERIAL_IRQ_CONFIG_REVISION 1
+extern EFI_GUID gSerialIrqConfigGuid;
+
+#pragma pack (push,1)
+
+typedef enum {
+ PchQuietMode,
+ PchContinuousMode
+} PCH_SIRQ_MODE;
+///
+/// Refer to PCH EDS for the details of Start Frame Pulse Width in Continuous and Quiet mode
+///
+typedef enum {
+ PchSfpw4Clk,
+ PchSfpw6Clk,
+ PchSfpw8Clk
+} PCH_START_FRAME_PULSE;
+
+///
+/// The PCH_LPC_SIRQ_CONFIG block describes the expected configuration of the PCH for Serial IRQ.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 SirqEnable : 1; ///< Determines if enable Serial IRQ. 0: Disable; <b>1: Enable</b>.
+ UINT32 SirqMode : 2; ///< Serial IRQ Mode Select. Refer to PCH_SIRQ_MODE for each value. <b>0: quiet mode</b> 1: continuous mode.
+ UINT32 StartFramePulse : 3; ///< Start Frame Pulse Width. Refer to PCH_START_FRAME_PULSE for each value. Default is <b>PchSfpw4Clk</b>.
+ UINT32 RsvdBits0 : 26; ///< Reserved bits
+} PCH_LPC_SIRQ_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SERIAL_IRQ_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SmbusConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SmbusConfig.h
new file mode 100644
index 0000000000..78ac72aa87
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SmbusConfig.h
@@ -0,0 +1,56 @@
+/** @file
+ Smbus policy
+
+Copyright (c) 2017, 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 that 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 _SMBUS_CONFIG_H_
+#define _SMBUS_CONFIG_H_
+
+#define SMBUS_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gSmbusPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+#define PCH_MAX_SMBUS_RESERVED_ADDRESS 128
+
+///
+/// The SMBUS_CONFIG block lists the reserved addresses for non-ARP capable devices in the platform.
+///
+typedef struct {
+ /**
+ Revision 1: Init version
+ **/
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ This member describes whether or not the SMBus controller of PCH should be enabled.
+ 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 Enable : 1;
+ UINT32 ArpEnable : 1; ///< Enable SMBus ARP support, <b>0: Disable</b>; 1: Enable.
+ UINT32 DynamicPowerGating : 1; ///< <b>(Test)</b> <b>Disable</b> or Enable Smbus dynamic power gating.
+ ///
+ /// <b>(Test)</b> SPD Write Disable, 0: leave SPD Write Disable bit; <b>1: set SPD Write Disable bit.</b>
+ /// For security recommendations, SPD write disable bit must be set.
+ ///
+ UINT32 SpdWriteDisable : 1;
+ UINT32 RsvdBits0 : 28; ///< Reserved bits
+ UINT16 SmbusIoBase; ///< SMBUS Base Address (IO space). Default is <b>0xEFA0</b>.
+ UINT8 Rsvd0; ///< Reserved bytes
+ UINT8 NumRsvdSmbusAddresses; ///< The number of elements in the RsvdSmbusAddressTable.
+ /**
+ Array of addresses reserved for non-ARP-capable SMBus devices.
+ **/
+ UINT8 RsvdSmbusAddressTable[PCH_MAX_SMBUS_RESERVED_ADDRESS];
+} PCH_SMBUS_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SMBUS_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SpiConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SpiConfig.h
new file mode 100644
index 0000000000..688fa314cb
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/SpiConfig.h
@@ -0,0 +1,38 @@
+/** @file
+ Spi policy
+
+Copyright (c) 2017, 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 that 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 _SPI_CONFIG_H_
+#define _SPI_CONFIG_H_
+
+#define SPI_CONFIG_REVISION 1
+extern EFI_GUID gSpiConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to SPI.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Force to show SPI controller.
+ <b>0: FALSE</b>, 1: TRUE
+ NOTE: For Windows OS, it MUST BE false. It's optional for other OSs.
+ **/
+ UINT32 ShowSpiController : 1;
+ UINT32 RsvdBits : 31; ///< Reserved bits
+} PCH_SPI_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SPI_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ThermalConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ThermalConfig.h
new file mode 100644
index 0000000000..8963da6ee7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/ThermalConfig.h
@@ -0,0 +1,176 @@
+/** @file
+ Thermal policy
+
+Copyright (c) 2017, 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 that 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 _THERMAL_CONFIG_H_
+#define _THERMAL_CONFIG_H_
+
+#define THERMAL_CONFIG_REVISION 1
+extern EFI_GUID gThermalConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure lists PCH supported throttling register setting for custimization.
+ When the SuggestedSetting is enabled, the customized values are ignored.
+**/
+typedef struct {
+ UINT32 T0Level : 9; ///< Custimized T0Level value. If SuggestedSetting is used, this setting is ignored.
+ UINT32 T1Level : 9; ///< Custimized T1Level value. If SuggestedSetting is used, this setting is ignored.
+ UINT32 T2Level : 9; ///< Custimized T2Level value. If SuggestedSetting is used, this setting is ignored.
+ UINT32 TTEnable : 1; ///< Enable the thermal throttle function. If SuggestedSetting is used, this settings is ignored.
+ /**
+ When set to 1 and the programmed GPIO pin is a 1, then PMSync state 13 will force at least T2 state.
+ If SuggestedSetting is used, this setting is ignored.
+ **/
+ UINT32 TTState13Enable : 1;
+ /**
+ When set to 1, this entire register (TL) is locked and remains locked until the next platform reset.
+ If SuggestedSetting is used, this setting is ignored.
+ **/
+ UINT32 TTLock : 1;
+ UINT32 SuggestedSetting : 1; ///< 0: Disable; <b>1: Enable</b> suggested representative values.
+ /**
+ ULT processors support thermal management and cross thermal throttling between the processor package
+ and LP PCH. The PMSYNC message from PCH to CPU includes specific bit fields to update the PCH
+ thermal status to the processor which is factored into the processor throttling.
+ Enable/Disable PCH Cross Throttling; 0: Disabled, 1: <b>Enabled</b>.
+ **/
+ UINT32 PchCrossThrottling : 1;
+ UINT32 Rsvd0; ///< Reserved bytes
+} THERMAL_THROTTLE_LEVELS;
+
+/**
+ This structure allows to customize DMI HW Autonomous Width Control for Thermal and Mechanical spec design.
+ When the SuggestedSetting is enabled, the customized values are ignored.
+**/
+typedef struct {
+ UINT32 DmiTsawEn : 1; ///< DMI Thermal Sensor Autonomous Width Enable
+ UINT32 SuggestedSetting : 1; ///< 0: Disable; <b>1: Enable</b> suggested representative values
+ UINT32 RsvdBits0 : 6; ///< Reserved bits
+ UINT32 TS0TW : 2; ///< Thermal Sensor 0 Target Width
+ UINT32 TS1TW : 2; ///< Thermal Sensor 1 Target Width
+ UINT32 TS2TW : 2; ///< Thermal Sensor 2 Target Width
+ UINT32 TS3TW : 2; ///< Thermal Sensor 3 Target Width
+ UINT32 RsvdBits1 : 16; ///< Reserved bits
+} DMI_HW_WIDTH_CONTROL;
+
+/**
+ This structure lists PCH supported SATA thermal throttling register setting for custimization.
+ The settings is programmed through SATA Index/Data registers.
+ When the SuggestedSetting is enabled, the customized values are ignored.
+**/
+typedef struct {
+ UINT32 P0T1M : 2; ///< Port 0 T1 Multipler
+ UINT32 P0T2M : 2; ///< Port 0 T2 Multipler
+ UINT32 P0T3M : 2; ///< Port 0 T3 Multipler
+ UINT32 P0TDisp : 2; ///< Port 0 Tdispatch
+
+ UINT32 P1T1M : 2; ///< Port 1 T1 Multipler
+ UINT32 P1T2M : 2; ///< Port 1 T2 Multipler
+ UINT32 P1T3M : 2; ///< Port 1 T3 Multipler
+ UINT32 P1TDisp : 2; ///< Port 1 Tdispatch
+
+ UINT32 P0Tinact : 2; ///< Port 0 Tinactive
+ UINT32 P0TDispFinit : 1; ///< Port 0 Alternate Fast Init Tdispatch
+ UINT32 P1Tinact : 2; ///< Port 1 Tinactive
+ UINT32 P1TDispFinit : 1; ///< Port 1 Alternate Fast Init Tdispatch
+ UINT32 SuggestedSetting : 1; ///< 0: Disable; <b>1: Enable</b> suggested representative values
+ UINT32 RsvdBits0 : 9; ///< Reserved bits
+} SATA_THERMAL_THROTTLE;
+
+/**
+ This structure configures PCH memory throttling thermal sensor GPIO PIN settings
+**/
+typedef struct {
+ /**
+ GPIO PM_SYNC enable, 0:Diabled, 1:<b>Enabled</b>
+ When enabled, RC will overrides the selected GPIO native mode.
+ For GPIO_C, PinSelection 0: CPU_GP_0 (default) or 1: CPU_GP_1
+ For GPIO_D, PinSelection 0: CPU_GP_3 (default) or 1: CPU_GP_2
+ For SKL: CPU_GP_0 is GPP_E3, CPU_GP_1 is GPP_E7, CPU_GP_2 is GPP_B3, CPU_GP_3 is GPP_B4.
+ **/
+ UINT32 PmsyncEnable : 1;
+ UINT32 C0TransmitEnable : 1; ///< GPIO Transmit enable in C0 state, 0:Disabled, 1:<b>Enabled</b>
+ UINT32 PinSelection : 1; ///< GPIO Pin assignment selection, <b>0: default</b>, 1: secondary
+ UINT32 RsvdBits0 : 29;
+} TS_GPIO_PIN_SETTING;
+
+enum PCH_PMSYNC_GPIO_X_SELECTION {
+ TsGpioC,
+ TsGpioD,
+ MaxTsGpioPin
+};
+
+/**
+ This structure supports an external memory thermal sensor (TS-on-DIMM or TS-on-Board).
+**/
+typedef struct {
+ /**
+ This will enable PCH memory throttling.
+ While this policy is enabled, must also enable EnableExtts in SA policy.
+ <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 Enable : 1;
+ UINT32 RsvdBits0 : 31;
+ /**
+ GPIO_C and GPIO_D selection for memory throttling.
+ It's strongly recommended to choose GPIO_C and GPIO_D for memory throttling feature,
+ and route EXTTS# accordingly.
+ **/
+ TS_GPIO_PIN_SETTING TsGpioPinSetting[2];
+} PCH_MEMORY_THROTTLING;
+
+/**
+ The PCH_THERMAL_CONFIG block describes the expected configuration of the PCH for Thermal.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ This field reports the status of Thermal Device. When it reports ThermalDevice
+ is disabled, the PCI configuration space of thermal device will be hidden by
+ setting TCFD and PCR[PSF2] TRH PCIEN[8] prior to end of POST.
+ **/
+ UINT32 ThermalDeviceEnable : 2; ///< 0: Disabled, <b>1: Enabled in PCI mode</b>, 2: Enabled in ACPI mode
+ UINT32 TsmicLock : 1; ///< This locks down "SMI Enable on Alert Thermal Sensor Trip". 0: Disabled, 1: <b>Enabled</b>.
+ UINT32 RsvdBits0 : 29;
+ /**
+ This field decides the settings of Thermal throttling. When the Suggested Setting
+ is enabled, PCH RC will use the suggested representative values.
+ **/
+ THERMAL_THROTTLE_LEVELS TTLevels;
+ /**
+ This field decides the settings of DMI throttling. When the Suggested Setting
+ is enabled, PCH RC will use the suggested representative values.
+ **/
+ DMI_HW_WIDTH_CONTROL DmiHaAWC;
+ /**
+ This field decides the settings of Sata thermal throttling. When the Suggested Setting
+ is enabled, PCH RC will use the suggested representative values.
+ **/
+ SATA_THERMAL_THROTTLE SataTT;
+ /**
+ Memory Thermal Management settings
+ **/
+ PCH_MEMORY_THROTTLING MemoryThrottling;
+ /**
+ This field decides the temperature, default is <b>zero</b>.
+ - 0x00 is the hottest
+ - 0x1FF is the lowest temperature
+ **/
+ UINT16 PchHotLevel;
+ UINT8 Rsvd0[6];
+} PCH_THERMAL_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _THERMAL_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/TraceHubConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/TraceHubConfig.h
new file mode 100644
index 0000000000..5455c40514
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/TraceHubConfig.h
@@ -0,0 +1,35 @@
+/** @file
+ Trace Hub policy
+
+Copyright (c) 2017, 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 that 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 _TRACEHUB_CONFIG_H_
+#define _TRACEHUB_CONFIG_H_
+
+#define TRACEHUB_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gTraceHubPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// The PCH_TRACE_HUB_CONFIG block describes TraceHub settings for PCH.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 EnableMode : 2; ///< 0 = Disable <b> 2 = Host Debugger enabled </b>
+ UINT32 RsvdBits0 : 30; ///< Reserved bits
+ UINT32 MemReg0Size; ///< Default is <b>0 (none)</b>.
+ UINT32 MemReg1Size; ///< Default is <b>0 (none)</b>.
+} PCH_TRACE_HUB_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _TRACEHUB_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/UsbConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/UsbConfig.h
new file mode 100644
index 0000000000..c2cef0aa43
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/UsbConfig.h
@@ -0,0 +1,233 @@
+/** @file
+ USB policy
+
+Copyright (c) 2017, 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 that 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 _USB_CONFIG_H_
+#define _USB_CONFIG_H_
+
+#define USB_CONFIG_REVISION 2
+extern EFI_GUID gUsbConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// Overcurrent pins, the values match the setting of PCH EDS, please refer to PCH EDS for more details
+///
+typedef enum {
+ PchUsbOverCurrentPin0 = 0,
+ PchUsbOverCurrentPin1,
+ PchUsbOverCurrentPin2,
+ PchUsbOverCurrentPin3,
+ PchUsbOverCurrentPin4,
+ PchUsbOverCurrentPin5,
+ PchUsbOverCurrentPin6,
+ PchUsbOverCurrentPin7,
+ PchUsbOverCurrentPinSkip,
+ PchUsbOverCurrentPinMax
+} PCH_USB_OVERCURRENT_PIN;
+
+///
+/// The location of the USB connectors. This information is use to decide eye diagram tuning value for Usb 2.0 motherboard trace.
+///
+enum PCH_USB_PORT_LOCATION{
+ PchUsbPortLocationBackPanel = 0,
+ PchUsbPortLocationFrontPanel,
+ PchUsbPortLocationDock,
+ PchUsbPortLocationMiniPciE,
+ PchUsbPortLocationFlex,
+ PchUsbPortLocationInternalTopology,
+ PchUsbPortLocationSkip,
+ PchUsbPortLocationMax
+};
+
+
+/**
+ This structure configures per USB2 AFE settings.
+ It allows to setup the port parameters.
+**/
+typedef struct {
+/** Per Port HS Preemphasis Bias (PERPORTPETXISET)
+ 000b - 0mV
+ 001b - 11.25mV
+ 010b - 16.9mV
+ 011b - 28.15mV
+ 100b - 28.15mV
+ 101b - 39.35mV
+ 110b - 45mV
+ 111b - 56.3mV
+**/
+ UINT8 Petxiset;
+/** Per Port HS Transmitter Bias (PERPORTTXISET)
+ 000b - 0mV
+ 001b - 11.25mV
+ 010b - 16.9mV
+ 011b - 28.15mV
+ 100b - 28.15mV
+ 101b - 39.35mV
+ 110b - 45mV
+ 111b - 56.3mV
+**/
+ UINT8 Txiset;
+/**
+ Per Port HS Transmitter Emphasis (IUSBTXEMPHASISEN)
+ 00b - Emphasis OFF
+ 01b - De-emphasis ON
+ 10b - Pre-emphasis ON
+ 11b - Pre-emphasis & De-emphasis ON
+**/
+ UINT8 Predeemp;
+/**
+ Per Port Half Bit Pre-emphasis (PERPORTTXPEHALF)
+ 1b - half-bit pre-emphasis
+ 0b - full-bit pre-emphasis
+**/
+ UINT8 Pehalfbit;
+} PCH_USB20_AFE;
+
+/**
+ This structure configures per USB2 port physical settings.
+ It allows to setup the port location and port length, and configures the port strength accordingly.
+**/
+typedef struct {
+ UINT32 Enable : 1; ///< 0: Disable; <b>1: Enable</b>.
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+ /**
+ These members describe the specific over current pin number of USB 2.0 Port N.
+ It is SW's responsibility to ensure that a given port's bit map is set only for
+ one OC pin Description. USB2 and USB3 on the same combo Port must use the same
+ OC pin (see: PCH_USB_OVERCURRENT_PIN).
+ **/
+ UINT8 OverCurrentPin;
+ UINT8 Rsvd0[3]; ///< Reserved bytes, align to multiple 4.
+ PCH_USB20_AFE Afe; ///< USB2 AFE settings
+ UINT32 Rsvd1[1]; ///< Reserved bytes
+} PCH_USB20_PORT_CONFIG;
+
+/**
+ This structure describes whether the USB3 Port N of PCH is enabled by platform modules.
+**/
+typedef struct {
+ UINT32 Enable : 1; ///< 0: Disable; <b>1: Enable</b>.
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+ /**
+ These members describe the specific over current pin number of USB 3.0 Port N.
+ It is SW's responsibility to ensure that a given port's bit map is set only for
+ one OC pin Description. USB2 and USB3 on the same combo Port must use the same
+ OC pin (see: PCH_USB_OVERCURRENT_PIN).
+ **/
+ UINT8 OverCurrentPin;
+ UINT8 Rsvd0[3]; ///< Reserved bytes, align to multiple 4
+
+ UINT32 HsioTxDeEmphEnable : 1; ///< Enable the write to USB 3.0 TX Output -3.5dB De-Emphasis Adjustment, <b>0: Disable</b>; 1: Enable.
+ /**
+ USB 3.0 TX Output -3.5dB De-Emphasis Adjustment Setting (ow2tapgen2deemph3p5)
+ HSIO_TX_DWORD5[21:16]
+ <b>Default = 29h</b> (approximately -3.5dB De-Emphasis)
+ **/
+ UINT32 HsioTxDeEmph : 6;
+
+ UINT32 HsioTxDownscaleAmpEnable : 1; ///< Enable the write to USB 3.0 TX Output Downscale Amplitude Adjustment, <b>0: Disable</b>; 1: Enable.
+ /**
+ USB 3.0 TX Output Downscale Amplitude Adjustment (orate01margin)
+ HSIO_TX_DWORD8[21:16]
+ <b>Default = 00h</b>
+ **/
+ UINT32 HsioTxDownscaleAmp : 6;
+
+ UINT32 RsvdBits1 : 18; ///< Reserved bits
+ UINT32 Rsvd1[1]; ///< Reserved bytes
+} PCH_USB30_PORT_CONFIG;
+
+#define PCH_XHCI_MODE_OFF 0
+#define PCH_XHCI_MODE_ON 1
+
+/**
+ These members describe some settings which are related to the SSIC ports.
+**/
+typedef struct {
+ /**
+ 0: Disable; <b>1: Enable</b> SSIC support.
+ **/
+ UINT32 Enable : 1;
+ UINT32 RsvdBits1 : 31;
+} PCH_XHCI_SSIC_PORT;
+/**
+ These members describe some settings which are related to the SSIC ports.
+**/
+typedef struct {
+ PCH_XHCI_SSIC_PORT SsicPort[PCH_XHCI_MAX_SSIC_PORT_COUNT];
+} PCH_SSIC_CONFIG;
+
+/**
+ The PCH_XDCI_CONFIG block describes the configurations
+ of the xDCI Usb Device controller.
+**/
+typedef struct {
+ /**
+ This member describes whether or not the xDCI controller should be enabled.
+ 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 Enable : 1;
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PCH_XDCI_CONFIG;
+
+
+/**
+ This member describes the expected configuration of the PCH USB controllers,
+ Platform modules may need to refer Setup options, schematic, BIOS specification
+ to update this field.
+ The Usb20OverCurrentPins and Usb30OverCurrentPins field must be updated by referring
+ the schematic.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Added DelayPdoProgramming policy option.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ This policy will disable XHCI compliance mode on all ports. Complicance Mode should be default enabled.
+ For the platform that support USB Type-C, it can disable Compliance Mode, and enable Compliance Mode when testing.
+ <b>0:Disable</b> , 1: Enable
+ **/
+ UINT32 DisableComplianceMode : 1;
+ /**
+ This policy option if set will move Port Disable Override register programming to ReadyToBoot event during DXE phase.
+ If not enabled it will program Port Disable Override register in PEI phase during PCH initialization
+ <b>0: Program in PEI phase </b>, 1: Program in DXE phase
+ **/
+ UINT32 DelayPdoProgramming : 1;
+ UINT32 RsvdBits0 : 30; ///< Reserved bits
+ /**
+ These members describe whether the USB2 Port N of PCH is enabled by platform modules.
+ Panel and Dock are used to describe the layout of USB port. Panel is only available for Desktop PCH.
+ Dock is only available for Mobile LPT.
+ **/
+ PCH_USB20_PORT_CONFIG PortUsb20[PCH_MAX_USB2_PORTS];
+ /**
+ These members describe whether the USB3 Port N of PCH is enabled by platform modules.
+ **/
+ PCH_USB30_PORT_CONFIG PortUsb30[PCH_MAX_USB3_PORTS];
+ /**
+ This member describes whether or not the xDCI controller should be enabled.
+ **/
+ PCH_XDCI_CONFIG XdciConfig;
+ /**
+ These members describe some settings which are related to the SSIC ports.
+ **/
+ PCH_SSIC_CONFIG SsicConfig;
+} PCH_USB_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _USB_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/WatchDogConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/WatchDogConfig.h
new file mode 100644
index 0000000000..610c1092fb
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/ConfigBlock/WatchDogConfig.h
@@ -0,0 +1,38 @@
+/** @file
+ WatchDog policy
+
+Copyright (c) 2017, 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 that 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 _WATCH_DOG_CONFIG_H_
+#define _WATCH_DOG_CONFIG_H_
+
+#define WATCH_DOG_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gWatchDogPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This policy clears status bits and disable watchdog, then lock the
+ WDT registers.
+ while WDT is designed to be disabled and locked by Policy,
+ bios should not enable WDT by WDT PPI. In such case, bios shows the
+ warning message but not disable and lock WDT register to make sure
+ WDT event trigger correctly.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 DisableAndLock : 1; ///< <b>(Test)</b> Set 1 to clear WDT status, then disable and lock WDT registers. <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits : 31;
+} PCH_WDT_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _WATCH_DOG_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioConfig.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioConfig.h
new file mode 100644
index 0000000000..8b26020da2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioConfig.h
@@ -0,0 +1,338 @@
+/** @file
+ Header file for GpioConfig structure used by GPIO library.
+
+Copyright (c) 2017, 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 that 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 _GPIO_CONFIG_H_
+#define _GPIO_CONFIG_H_
+
+#pragma pack(push, 1)
+
+///
+/// For any GpioPad usage in code use GPIO_PAD type
+///
+typedef UINT32 GPIO_PAD;
+
+
+///
+/// For any GpioGroup usage in code use GPIO_GROUP type
+///
+typedef UINT32 GPIO_GROUP;
+
+/**
+ GPIO configuration structure used for pin programming.
+ Structure contains fields that can be used to configure pad.
+**/
+typedef struct {
+ /**
+ Pad Mode
+ Pad can be set as GPIO or one of its native functions.
+ When in native mode setting Direction (except Inversion), OutputState,
+ InterruptConfig, Host Software Pad Ownership and OutputStateLock are unnecessary.
+ Refer to definition of GPIO_PAD_MODE.
+ Refer to EDS for each native mode according to the pad.
+ **/
+ UINT32 PadMode : 5;
+ /**
+ Host Software Pad Ownership
+ Set pad to ACPI mode or GPIO Driver Mode.
+ Refer to definition of GPIO_HOSTSW_OWN.
+ **/
+ UINT32 HostSoftPadOwn : 2;
+ /**
+ GPIO Direction
+ Can choose between In, In with inversion, Out, both In and Out, both In with inversion and out or disabling both.
+ Refer to definition of GPIO_DIRECTION for supported settings.
+ **/
+ UINT32 Direction : 6;
+ /**
+ Output State
+ Set Pad output value.
+ Refer to definition of GPIO_OUTPUT_STATE for supported settings.
+ This setting takes place when output is enabled.
+ **/
+ UINT32 OutputState : 2;
+ /**
+ GPIO Interrupt Configuration
+ Set Pad to cause one of interrupts (IOxAPIC/SCI/SMI/NMI).
+ This setting is applicable only if GPIO is in GpioMode with input enabled.
+ Refer to definition of GPIO_INT_CONFIG for supported settings.
+ **/
+ UINT32 InterruptConfig : 9;
+ /**
+ GPIO Power Configuration.
+ This setting controls Pad Reset Configuration.
+ Refer to definition of GPIO_RESET_CONFIG for supported settings.
+ **/
+ UINT32 PowerConfig : 8;
+ /**
+ GPIO Electrical Configuration
+ This setting controls pads termination and voltage tolerance.
+ Refer to definition of GPIO_ELECTRICAL_CONFIG for supported settings.
+ **/
+ UINT32 ElectricalConfig : 9;
+ /**
+ GPIO Lock Configuration
+ This setting controls pads lock.
+ Refer to definition of GPIO_LOCK_CONFIG for supported settings.
+ **/
+ UINT32 LockConfig : 4;
+ /**
+ Additional GPIO configuration
+ Refer to definition of GPIO_OTHER_CONFIG for supported settings.
+ **/
+ UINT32 OtherSettings : 2;
+ UINT32 RsvdBits : 17; ///< Reserved bits for future extension
+} GPIO_CONFIG;
+
+
+typedef enum {
+ GpioHardwareDefault = 0x0 ///< Leave setting unmodified
+} GPIO_HARDWARE_DEFAULT;
+
+/**
+ GPIO Pad Mode
+ Refer to GPIO documentation on native functions available for certain pad.
+ If GPIO is set to one of NativeX modes then following settings are not applicable
+ and can be skipped:
+ - Interrupt related settings
+ - Host Software Ownership
+ - Output/Input enabling/disabling
+ - Output lock
+**/
+typedef enum {
+ GpioPadModeGpio = 0x1,
+ GpioPadModeNative1 = 0x3,
+ GpioPadModeNative2 = 0x5,
+ GpioPadModeNative3 = 0x7,
+ GpioPadModeNative4 = 0x9
+} GPIO_PAD_MODE;
+
+/**
+ Host Software Pad Ownership modes
+ This setting affects GPIO interrupt status registers. Depending on chosen ownership
+ some GPIO Interrupt status register get updated and other masked.
+ Please refer to EDS for HOSTSW_OWN register description.
+**/
+typedef enum {
+ GpioHostOwnDefault = 0x0, ///< Leave ownership value unmodified
+ /**
+ Set HOST ownership to ACPI.
+ Use this setting if pad is not going to be used by GPIO OS driver.
+ If GPIO is configured to generate SCI/SMI/NMI then this setting must be
+ used for interrupts to work
+ **/
+ GpioHostOwnAcpi = 0x1,
+ /**
+ Set HOST ownership to GPIO Driver mode.
+ Use this setting only if GPIO pad should be controlled by GPIO OS Driver.
+ GPIO OS Driver will be able to control the pad if appropriate entry in
+ ACPI exists (refer to ACPI specification for GpioIo and GpioInt descriptors)
+ **/
+ GpioHostOwnGpio = 0x3
+} GPIO_HOSTSW_OWN;
+
+///
+/// GPIO Direction
+///
+typedef enum {
+ GpioDirDefault = 0x0, ///< Leave pad direction setting unmodified
+ GpioDirInOut = (0x1 | (0x1 << 3)), ///< Set pad for both output and input
+ GpioDirInInvOut = (0x1 | (0x3 << 3)), ///< Set pad for both output and input with inversion
+ GpioDirIn = (0x3 | (0x1 << 3)), ///< Set pad for input only
+ GpioDirInInv = (0x3 | (0x3 << 3)), ///< Set pad for input with inversion
+ GpioDirOut = 0x5, ///< Set pad for output only
+ GpioDirNone = 0x7 ///< Disable both output and input
+} GPIO_DIRECTION;
+
+/**
+ GPIO Output State
+ This field is relevant only if output is enabled
+**/
+typedef enum {
+ GpioOutDefault = 0x0, ///< Leave output value unmodified
+ GpioOutLow = 0x1, ///< Set output to low
+ GpioOutHigh = 0x3 ///< Set output to high
+} GPIO_OUTPUT_STATE;
+
+/**
+ GPIO interrupt configuration
+ This setting is applicable only if pad is in GPIO mode and has input enabled.
+ GPIO_INT_CONFIG allows to choose which interrupt is generated (IOxAPIC/SCI/SMI/NMI)
+ and how it is triggered (edge or level). Refer to PADCFG_DW0 register description in
+ EDS for details on this settings.
+ Field from GpioIntNmi to GpioIntApic can be OR'ed with GpioIntLevel to GpioIntBothEdge
+ to describe an interrupt e.g. GpioIntApic | GpioIntLevel
+ If GPIO is set to cause an SCI then also GPI_GPE_EN is enabled for this pad.
+ If GPIO is set to cause an NMI then also GPI_NMI_EN is enabled for this pad.
+ Not all GPIO are capable of generating an SMI or NMI interrupt.
+ When routing GPIO to cause an IOxAPIC interrupt care must be taken, as this
+ interrupt cannot be shared and its IRQn number is not configurable.
+ Refer to EDS for GPIO pads IRQ numbers (PADCFG_DW1.IntSel)
+ If GPIO is under GPIO OS driver control and appropriate ACPI GpioInt descriptor
+ exist then use only trigger type setting (from GpioIntLevel to GpioIntBothEdge).
+ This type of GPIO Driver interrupt doesn't have any additional routing setting
+ required to be set by BIOS. Interrupt is handled by GPIO OS Driver.
+**/
+
+typedef enum {
+ GpioIntDefault = 0x0, ///< Leave value of interrupt routing unmodified
+ GpioIntDis = 0x1, ///< Disable IOxAPIC/SCI/SMI/NMI interrupt generation
+ GpioIntNmi = 0x3, ///< Enable NMI interrupt only
+ GpioIntSmi = 0x5, ///< Enable SMI interrupt only
+ GpioIntSci = 0x9, ///< Enable SCI interrupt only
+ GpioIntApic = 0x11, ///< Enable IOxAPIC interrupt only
+ GpioIntLevel = (0x1 << 5), ///< Set interrupt as level triggered
+ GpioIntEdge = (0x3 << 5), ///< Set interrupt as edge triggered (type of edge depends on input inversion)
+ GpioIntLvlEdgDis = (0x5 << 5), ///< Disable interrupt trigger
+ GpioIntBothEdge = (0x7 << 5) ///< Set interrupt as both edge triggered
+} GPIO_INT_CONFIG;
+
+#define B_GPIO_INT_CONFIG_INT_SOURCE_MASK 0x1F ///< Mask for GPIO_INT_CONFIG for interrupt source
+#define B_GPIO_INT_CONFIG_INT_TYPE_MASK 0xE0 ///< Mask for GPIO_INT_CONFIG for interrupt type
+
+/**
+ GPIO Power Configuration
+ GPIO_RESET_CONFIG allows to set GPIO Reset type (PADCFG_DW0.PadRstCfg) which will
+ be used to reset certain GPIO settings.
+ Refer to EDS for settings that are controllable by PadRstCfg.
+**/
+typedef enum {
+
+
+ GpioResetDefault = 0x00, ///< Leave value of pad reset unmodified
+ ///
+ /// @{
+ /// @deprecated settings. Maintained only for compatibility.
+ ///
+ GpioResetPwrGood = 0x09, ///< GPP: RSMRST; GPD: DSW_PWROK; (PadRstCfg = 00b = "Powergood")
+ GpioResetDeep = 0x0B, ///< Deep GPIO Reset (PadRstCfg = 01b = "Deep GPIO Reset")
+ GpioResetNormal = 0x0D, ///< GPIO Reset (PadRstCfg = 10b = "GPIO Reset" )
+ GpioResetResume = 0x0F, ///< GPP: Reserved; GPD: RSMRST; (PadRstCfg = 11b = "Resume Reset" )
+ ///
+ /// @}
+ ///
+ ///
+ /// New GPIO reset configuration options
+ ///
+ /**
+ Resume Reset (RSMRST)
+ GPP: PadRstCfg = 00b = "Powergood"
+ GPD: PadRstCfg = 11b = "Resume Reset"
+ Pad setting will reset on:
+ - DeepSx transition
+ - G3
+ Pad settings will not reset on:
+ - S3/S4/S5 transition
+ - Warm/Cold/Global reset
+ **/
+ GpioResumeReset = 0x01,
+ /**
+ Host Deep Reset
+ PadRstCfg = 01b = "Deep GPIO Reset"
+ Pad settings will reset on:
+ - Warm/Cold/Global reset
+ - DeepSx transition
+ - G3
+ Pad settings will not reset on:
+ - S3/S4/S5 transition
+ **/
+ GpioHostDeepReset = 0x03,
+ /**
+ Platform Reset (PLTRST)
+ PadRstCfg = 10b = "GPIO Reset"
+ Pad settings will reset on:
+ - S3/S4/S5 transition
+ - Warm/Cold/Global reset
+ - DeepSx transition
+ - G3
+ **/
+ GpioPlatformReset = 0x05,
+ /**
+ Deep Sleep Well Reset (DSW_PWROK)
+ GPP: not applicable
+ GPD: PadRstCfg = 00b = "Powergood"
+ Pad settings will reset on:
+ - G3
+ Pad settings will not reset on:
+ - S3/S4/S5 transition
+ - Warm/Cold/Global reset
+ - DeepSx transition
+ **/
+ GpioDswReset = 0x07
+} GPIO_RESET_CONFIG;
+
+/**
+ GPIO Electrical Configuration
+ Set GPIO termination and Pad Tolerance (applicable only for some pads)
+ Field from GpioTermNone to GpioTermNative can be OR'ed with GpioTolerance1v8.
+**/
+typedef enum {
+ GpioTermDefault = 0x0, ///< Leave termination setting unmodified
+ GpioTermNone = 0x1, ///< none
+ GpioTermWpd5K = 0x5, ///< 5kOhm weak pull-down
+ GpioTermWpd20K = 0x9, ///< 20kOhm weak pull-down
+ GpioTermWpu1K = 0x13, ///< 1kOhm weak pull-up
+ GpioTermWpu2K = 0x17, ///< 2kOhm weak pull-up
+ GpioTermWpu5K = 0x15, ///< 5kOhm weak pull-up
+ GpioTermWpu20K = 0x19, ///< 20kOhm weak pull-up
+ GpioTermWpu1K2K = 0x1B, ///< 1kOhm & 2kOhm weak pull-up
+ /**
+ Native function controls pads termination
+ This setting is applicable only to some native modes.
+ Please check EDS to determine which native functionality
+ can control pads termination
+ **/
+ GpioTermNative = 0x1F,
+ GpioNoTolerance1v8 = (0x1 << 5), ///< Disable 1.8V pad tolerance
+ GpioTolerance1v8 = (0x3 << 5) ///< Enable 1.8V pad tolerance
+} GPIO_ELECTRICAL_CONFIG;
+
+#define B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK 0x1F ///< Mask for GPIO_ELECTRICAL_CONFIG for termination value
+#define B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK 0x60 ///< Mask for GPIO_ELECTRICAL_CONFIG for 1v8 tolerance setting
+
+/**
+ GPIO LockConfiguration
+ Set GPIO configuration lock and output state lock.
+ GpioLockPadConfig and GpioLockOutputState can be OR'ed.
+ Lock settings reset is in Powergood domain. Care must be taken when using this setting
+ as fields it locks may be reset by a different signal and can be controllable
+ by what is in GPIO_RESET_CONFIG (PADCFG_DW0.PadRstCfg). GPIO library provides
+ functions which allow to unlock a GPIO pad.
+**/
+typedef enum {
+ GpioLockDefault = 0x0, ///< Leave lock setting unmodified
+ GpioPadConfigLock = 0x3, ///< Lock Pad Configuration
+ GpioOutputStateLock = 0x5 ///< Lock GPIO pad output value
+} GPIO_LOCK_CONFIG;
+
+#define B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK 0x3 ///< Mask for GPIO_LOCK_CONFIG for Pad Configuration Lock
+#define B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK 0x5 ///< Mask for GPIO_LOCK_CONFIG for Pad Output Lock
+
+/**
+ Other GPIO Configuration
+ GPIO_OTHER_CONFIG is used for less often settings and for future extensions
+ Supported settings:
+ - RX raw override to '1' - allows to override input value to '1'
+ This setting is applicable only if in input mode (both in GPIO and native usage).
+ The override takes place at the internal pad state directly from buffer and before the RXINV.
+**/
+typedef enum {
+ GpioRxRaw1Default = 0x0, ///< Use default input override value
+ GpioRxRaw1Dis = 0x1, ///< Don't override input
+ GpioRxRaw1En = 0x3 ///< Override input to '1'
+} GPIO_OTHER_CONFIG;
+
+#define B_GPIO_OTHER_CONFIG_RXRAW_MASK 0x3 ///< Mask for GPIO_OTHER_CONFIG for RxRaw1 setting
+
+#pragma pack(pop)
+
+#endif //_GPIO_CONFIG_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklH.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklH.h
new file mode 100644
index 0000000000..5230656791
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklH.h
@@ -0,0 +1,248 @@
+/** @file
+ GPIO pins for SKL-PCH-H,
+
+Copyright (c) 2017, 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 that 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 _GPIO_PINS_SKL_H_H_
+#define _GPIO_PINS_SKL_H_H_
+///
+/// This header file should be used together with
+/// PCH GPIO lib in C and ASL. All defines used
+/// must match both ASL/C syntax
+///
+///
+/// SKL H GPIO Groups
+/// Use below for functions from PCH GPIO Lib which
+/// require GpioGroup as argument
+///
+#define GPIO_SKL_H_GROUP_GPP_A 0x0100
+#define GPIO_SKL_H_GROUP_GPP_B 0x0101
+#define GPIO_SKL_H_GROUP_GPP_C 0x0102
+#define GPIO_SKL_H_GROUP_GPP_D 0x0103
+#define GPIO_SKL_H_GROUP_GPP_E 0x0104
+#define GPIO_SKL_H_GROUP_GPP_F 0x0105
+#define GPIO_SKL_H_GROUP_GPP_G 0x0106
+#define GPIO_SKL_H_GROUP_GPP_H 0x0107
+#define GPIO_SKL_H_GROUP_GPP_I 0x0108
+#define GPIO_SKL_H_GROUP_GPD 0x0109
+
+///
+/// SKL H GPIO pins
+/// Use below for functions from PCH GPIO Lib which
+/// require GpioPad as argument. Encoding used here
+/// has all information required by library functions
+///
+#define GPIO_SKL_H_GPP_A0 0x01000000
+#define GPIO_SKL_H_GPP_A1 0x01000001
+#define GPIO_SKL_H_GPP_A2 0x01000002
+#define GPIO_SKL_H_GPP_A3 0x01000003
+#define GPIO_SKL_H_GPP_A4 0x01000004
+#define GPIO_SKL_H_GPP_A5 0x01000005
+#define GPIO_SKL_H_GPP_A6 0x01000006
+#define GPIO_SKL_H_GPP_A7 0x01000007
+#define GPIO_SKL_H_GPP_A8 0x01000008
+#define GPIO_SKL_H_GPP_A9 0x01000009
+#define GPIO_SKL_H_GPP_A10 0x0100000A
+#define GPIO_SKL_H_GPP_A11 0x0100000B
+#define GPIO_SKL_H_GPP_A12 0x0100000C
+#define GPIO_SKL_H_GPP_A13 0x0100000D
+#define GPIO_SKL_H_GPP_A14 0x0100000E
+#define GPIO_SKL_H_GPP_A15 0x0100000F
+#define GPIO_SKL_H_GPP_A16 0x01000010
+#define GPIO_SKL_H_GPP_A17 0x01000011
+#define GPIO_SKL_H_GPP_A18 0x01000012
+#define GPIO_SKL_H_GPP_A19 0x01000013
+#define GPIO_SKL_H_GPP_A20 0x01000014
+#define GPIO_SKL_H_GPP_A21 0x01000015
+#define GPIO_SKL_H_GPP_A22 0x01000016
+#define GPIO_SKL_H_GPP_A23 0x01000017
+#define GPIO_SKL_H_GPP_B0 0x01010000
+#define GPIO_SKL_H_GPP_B1 0x01010001
+#define GPIO_SKL_H_GPP_B2 0x01010002
+#define GPIO_SKL_H_GPP_B3 0x01010003
+#define GPIO_SKL_H_GPP_B4 0x01010004
+#define GPIO_SKL_H_GPP_B5 0x01010005
+#define GPIO_SKL_H_GPP_B6 0x01010006
+#define GPIO_SKL_H_GPP_B7 0x01010007
+#define GPIO_SKL_H_GPP_B8 0x01010008
+#define GPIO_SKL_H_GPP_B9 0x01010009
+#define GPIO_SKL_H_GPP_B10 0x0101000A
+#define GPIO_SKL_H_GPP_B11 0x0101000B
+#define GPIO_SKL_H_GPP_B12 0x0101000C
+#define GPIO_SKL_H_GPP_B13 0x0101000D
+#define GPIO_SKL_H_GPP_B14 0x0101000E
+#define GPIO_SKL_H_GPP_B15 0x0101000F
+#define GPIO_SKL_H_GPP_B16 0x01010010
+#define GPIO_SKL_H_GPP_B17 0x01010011
+#define GPIO_SKL_H_GPP_B18 0x01010012
+#define GPIO_SKL_H_GPP_B19 0x01010013
+#define GPIO_SKL_H_GPP_B20 0x01010014
+#define GPIO_SKL_H_GPP_B21 0x01010015
+#define GPIO_SKL_H_GPP_B22 0x01010016
+#define GPIO_SKL_H_GPP_B23 0x01010017
+#define GPIO_SKL_H_GPP_C0 0x01020000
+#define GPIO_SKL_H_GPP_C1 0x01020001
+#define GPIO_SKL_H_GPP_C2 0x01020002
+#define GPIO_SKL_H_GPP_C3 0x01020003
+#define GPIO_SKL_H_GPP_C4 0x01020004
+#define GPIO_SKL_H_GPP_C5 0x01020005
+#define GPIO_SKL_H_GPP_C6 0x01020006
+#define GPIO_SKL_H_GPP_C7 0x01020007
+#define GPIO_SKL_H_GPP_C8 0x01020008
+#define GPIO_SKL_H_GPP_C9 0x01020009
+#define GPIO_SKL_H_GPP_C10 0x0102000A
+#define GPIO_SKL_H_GPP_C11 0x0102000B
+#define GPIO_SKL_H_GPP_C12 0x0102000C
+#define GPIO_SKL_H_GPP_C13 0x0102000D
+#define GPIO_SKL_H_GPP_C14 0x0102000E
+#define GPIO_SKL_H_GPP_C15 0x0102000F
+#define GPIO_SKL_H_GPP_C16 0x01020010
+#define GPIO_SKL_H_GPP_C17 0x01020011
+#define GPIO_SKL_H_GPP_C18 0x01020012
+#define GPIO_SKL_H_GPP_C19 0x01020013
+#define GPIO_SKL_H_GPP_C20 0x01020014
+#define GPIO_SKL_H_GPP_C21 0x01020015
+#define GPIO_SKL_H_GPP_C22 0x01020016
+#define GPIO_SKL_H_GPP_C23 0x01020017
+#define GPIO_SKL_H_GPP_D0 0x01030000
+#define GPIO_SKL_H_GPP_D1 0x01030001
+#define GPIO_SKL_H_GPP_D2 0x01030002
+#define GPIO_SKL_H_GPP_D3 0x01030003
+#define GPIO_SKL_H_GPP_D4 0x01030004
+#define GPIO_SKL_H_GPP_D5 0x01030005
+#define GPIO_SKL_H_GPP_D6 0x01030006
+#define GPIO_SKL_H_GPP_D7 0x01030007
+#define GPIO_SKL_H_GPP_D8 0x01030008
+#define GPIO_SKL_H_GPP_D9 0x01030009
+#define GPIO_SKL_H_GPP_D10 0x0103000A
+#define GPIO_SKL_H_GPP_D11 0x0103000B
+#define GPIO_SKL_H_GPP_D12 0x0103000C
+#define GPIO_SKL_H_GPP_D13 0x0103000D
+#define GPIO_SKL_H_GPP_D14 0x0103000E
+#define GPIO_SKL_H_GPP_D15 0x0103000F
+#define GPIO_SKL_H_GPP_D16 0x01030010
+#define GPIO_SKL_H_GPP_D17 0x01030011
+#define GPIO_SKL_H_GPP_D18 0x01030012
+#define GPIO_SKL_H_GPP_D19 0x01030013
+#define GPIO_SKL_H_GPP_D20 0x01030014
+#define GPIO_SKL_H_GPP_D21 0x01030015
+#define GPIO_SKL_H_GPP_D22 0x01030016
+#define GPIO_SKL_H_GPP_D23 0x01030017
+#define GPIO_SKL_H_GPP_E0 0x01040000
+#define GPIO_SKL_H_GPP_E1 0x01040001
+#define GPIO_SKL_H_GPP_E2 0x01040002
+#define GPIO_SKL_H_GPP_E3 0x01040003
+#define GPIO_SKL_H_GPP_E4 0x01040004
+#define GPIO_SKL_H_GPP_E5 0x01040005
+#define GPIO_SKL_H_GPP_E6 0x01040006
+#define GPIO_SKL_H_GPP_E7 0x01040007
+#define GPIO_SKL_H_GPP_E8 0x01040008
+#define GPIO_SKL_H_GPP_E9 0x01040009
+#define GPIO_SKL_H_GPP_E10 0x0104000A
+#define GPIO_SKL_H_GPP_E11 0x0104000B
+#define GPIO_SKL_H_GPP_E12 0x0104000C
+#define GPIO_SKL_H_GPP_F0 0x01050000
+#define GPIO_SKL_H_GPP_F1 0x01050001
+#define GPIO_SKL_H_GPP_F2 0x01050002
+#define GPIO_SKL_H_GPP_F3 0x01050003
+#define GPIO_SKL_H_GPP_F4 0x01050004
+#define GPIO_SKL_H_GPP_F5 0x01050005
+#define GPIO_SKL_H_GPP_F6 0x01050006
+#define GPIO_SKL_H_GPP_F7 0x01050007
+#define GPIO_SKL_H_GPP_F8 0x01050008
+#define GPIO_SKL_H_GPP_F9 0x01050009
+#define GPIO_SKL_H_GPP_F10 0x0105000A
+#define GPIO_SKL_H_GPP_F11 0x0105000B
+#define GPIO_SKL_H_GPP_F12 0x0105000C
+#define GPIO_SKL_H_GPP_F13 0x0105000D
+#define GPIO_SKL_H_GPP_F14 0x0105000E
+#define GPIO_SKL_H_GPP_F15 0x0105000F
+#define GPIO_SKL_H_GPP_F16 0x01050010
+#define GPIO_SKL_H_GPP_F17 0x01050011
+#define GPIO_SKL_H_GPP_F18 0x01050012
+#define GPIO_SKL_H_GPP_F19 0x01050013
+#define GPIO_SKL_H_GPP_F20 0x01050014
+#define GPIO_SKL_H_GPP_F21 0x01050015
+#define GPIO_SKL_H_GPP_F22 0x01050016
+#define GPIO_SKL_H_GPP_F23 0x01050017
+#define GPIO_SKL_H_GPP_G0 0x01060000
+#define GPIO_SKL_H_GPP_G1 0x01060001
+#define GPIO_SKL_H_GPP_G2 0x01060002
+#define GPIO_SKL_H_GPP_G3 0x01060003
+#define GPIO_SKL_H_GPP_G4 0x01060004
+#define GPIO_SKL_H_GPP_G5 0x01060005
+#define GPIO_SKL_H_GPP_G6 0x01060006
+#define GPIO_SKL_H_GPP_G7 0x01060007
+#define GPIO_SKL_H_GPP_G8 0x01060008
+#define GPIO_SKL_H_GPP_G9 0x01060009
+#define GPIO_SKL_H_GPP_G10 0x0106000A
+#define GPIO_SKL_H_GPP_G11 0x0106000B
+#define GPIO_SKL_H_GPP_G12 0x0106000C
+#define GPIO_SKL_H_GPP_G13 0x0106000D
+#define GPIO_SKL_H_GPP_G14 0x0106000E
+#define GPIO_SKL_H_GPP_G15 0x0106000F
+#define GPIO_SKL_H_GPP_G16 0x01060010
+#define GPIO_SKL_H_GPP_G17 0x01060011
+#define GPIO_SKL_H_GPP_G18 0x01060012
+#define GPIO_SKL_H_GPP_G19 0x01060013
+#define GPIO_SKL_H_GPP_G20 0x01060014
+#define GPIO_SKL_H_GPP_G21 0x01060015
+#define GPIO_SKL_H_GPP_G22 0x01060016
+#define GPIO_SKL_H_GPP_G23 0x01060017
+#define GPIO_SKL_H_GPP_H0 0x01070000
+#define GPIO_SKL_H_GPP_H1 0x01070001
+#define GPIO_SKL_H_GPP_H2 0x01070002
+#define GPIO_SKL_H_GPP_H3 0x01070003
+#define GPIO_SKL_H_GPP_H4 0x01070004
+#define GPIO_SKL_H_GPP_H5 0x01070005
+#define GPIO_SKL_H_GPP_H6 0x01070006
+#define GPIO_SKL_H_GPP_H7 0x01070007
+#define GPIO_SKL_H_GPP_H8 0x01070008
+#define GPIO_SKL_H_GPP_H9 0x01070009
+#define GPIO_SKL_H_GPP_H10 0x0107000A
+#define GPIO_SKL_H_GPP_H11 0x0107000B
+#define GPIO_SKL_H_GPP_H12 0x0107000C
+#define GPIO_SKL_H_GPP_H13 0x0107000D
+#define GPIO_SKL_H_GPP_H14 0x0107000E
+#define GPIO_SKL_H_GPP_H15 0x0107000F
+#define GPIO_SKL_H_GPP_H16 0x01070010
+#define GPIO_SKL_H_GPP_H17 0x01070011
+#define GPIO_SKL_H_GPP_H18 0x01070012
+#define GPIO_SKL_H_GPP_H19 0x01070013
+#define GPIO_SKL_H_GPP_H20 0x01070014
+#define GPIO_SKL_H_GPP_H21 0x01070015
+#define GPIO_SKL_H_GPP_H22 0x01070016
+#define GPIO_SKL_H_GPP_H23 0x01070017
+#define GPIO_SKL_H_GPP_I0 0x01080000
+#define GPIO_SKL_H_GPP_I1 0x01080001
+#define GPIO_SKL_H_GPP_I2 0x01080002
+#define GPIO_SKL_H_GPP_I3 0x01080003
+#define GPIO_SKL_H_GPP_I4 0x01080004
+#define GPIO_SKL_H_GPP_I5 0x01080005
+#define GPIO_SKL_H_GPP_I6 0x01080006
+#define GPIO_SKL_H_GPP_I7 0x01080007
+#define GPIO_SKL_H_GPP_I8 0x01080008
+#define GPIO_SKL_H_GPP_I9 0x01080009
+#define GPIO_SKL_H_GPP_I10 0x0108000A
+#define GPIO_SKL_H_GPD0 0x01090000
+#define GPIO_SKL_H_GPD1 0x01090001
+#define GPIO_SKL_H_GPD2 0x01090002
+#define GPIO_SKL_H_GPD3 0x01090003
+#define GPIO_SKL_H_GPD4 0x01090004
+#define GPIO_SKL_H_GPD5 0x01090005
+#define GPIO_SKL_H_GPD6 0x01090006
+#define GPIO_SKL_H_GPD7 0x01090007
+#define GPIO_SKL_H_GPD8 0x01090008
+#define GPIO_SKL_H_GPD9 0x01090009
+#define GPIO_SKL_H_GPD10 0x0109000A
+#define GPIO_SKL_H_GPD11 0x0109000B
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklLp.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklLp.h
new file mode 100644
index 0000000000..999b417011
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/GpioPinsSklLp.h
@@ -0,0 +1,207 @@
+/** @file
+ GPIO pins for SKL-PCH-LP,
+
+Copyright (c) 2017, 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 that 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 _GPIO_PINS_SKL_LP_H_
+#define _GPIO_PINS_SKL_LP_H_
+///
+/// This header file should be used together with
+/// PCH GPIO lib in C and ASL. All defines used
+/// must match both ASL/C syntax
+///
+
+///
+/// SKL LP GPIO Groups
+/// Use below for functions from PCH GPIO Lib which
+/// require GpioGroup as argument
+///
+#define GPIO_SKL_LP_GROUP_GPP_A 0x0200
+#define GPIO_SKL_LP_GROUP_GPP_B 0x0201
+#define GPIO_SKL_LP_GROUP_GPP_C 0x0202
+#define GPIO_SKL_LP_GROUP_GPP_D 0x0203
+#define GPIO_SKL_LP_GROUP_GPP_E 0x0204
+#define GPIO_SKL_LP_GROUP_GPP_F 0x0205
+#define GPIO_SKL_LP_GROUP_GPP_G 0x0206
+#define GPIO_SKL_LP_GROUP_GPD 0x0207
+
+///
+/// SKL LP GPIO pins
+/// Use below for functions from PCH GPIO Lib which
+/// require GpioPad as argument. Encoding used here
+/// has all information required by library functions
+///
+#define GPIO_SKL_LP_GPP_A0 0x02000000
+#define GPIO_SKL_LP_GPP_A1 0x02000001
+#define GPIO_SKL_LP_GPP_A2 0x02000002
+#define GPIO_SKL_LP_GPP_A3 0x02000003
+#define GPIO_SKL_LP_GPP_A4 0x02000004
+#define GPIO_SKL_LP_GPP_A5 0x02000005
+#define GPIO_SKL_LP_GPP_A6 0x02000006
+#define GPIO_SKL_LP_GPP_A7 0x02000007
+#define GPIO_SKL_LP_GPP_A8 0x02000008
+#define GPIO_SKL_LP_GPP_A9 0x02000009
+#define GPIO_SKL_LP_GPP_A10 0x0200000A
+#define GPIO_SKL_LP_GPP_A11 0x0200000B
+#define GPIO_SKL_LP_GPP_A12 0x0200000C
+#define GPIO_SKL_LP_GPP_A13 0x0200000D
+#define GPIO_SKL_LP_GPP_A14 0x0200000E
+#define GPIO_SKL_LP_GPP_A15 0x0200000F
+#define GPIO_SKL_LP_GPP_A16 0x02000010
+#define GPIO_SKL_LP_GPP_A17 0x02000011
+#define GPIO_SKL_LP_GPP_A18 0x02000012
+#define GPIO_SKL_LP_GPP_A19 0x02000013
+#define GPIO_SKL_LP_GPP_A20 0x02000014
+#define GPIO_SKL_LP_GPP_A21 0x02000015
+#define GPIO_SKL_LP_GPP_A22 0x02000016
+#define GPIO_SKL_LP_GPP_A23 0x02000017
+#define GPIO_SKL_LP_GPP_B0 0x02010000
+#define GPIO_SKL_LP_GPP_B1 0x02010001
+#define GPIO_SKL_LP_GPP_B2 0x02010002
+#define GPIO_SKL_LP_GPP_B3 0x02010003
+#define GPIO_SKL_LP_GPP_B4 0x02010004
+#define GPIO_SKL_LP_GPP_B5 0x02010005
+#define GPIO_SKL_LP_GPP_B6 0x02010006
+#define GPIO_SKL_LP_GPP_B7 0x02010007
+#define GPIO_SKL_LP_GPP_B8 0x02010008
+#define GPIO_SKL_LP_GPP_B9 0x02010009
+#define GPIO_SKL_LP_GPP_B10 0x0201000A
+#define GPIO_SKL_LP_GPP_B11 0x0201000B
+#define GPIO_SKL_LP_GPP_B12 0x0201000C
+#define GPIO_SKL_LP_GPP_B13 0x0201000D
+#define GPIO_SKL_LP_GPP_B14 0x0201000E
+#define GPIO_SKL_LP_GPP_B15 0x0201000F
+#define GPIO_SKL_LP_GPP_B16 0x02010010
+#define GPIO_SKL_LP_GPP_B17 0x02010011
+#define GPIO_SKL_LP_GPP_B18 0x02010012
+#define GPIO_SKL_LP_GPP_B19 0x02010013
+#define GPIO_SKL_LP_GPP_B20 0x02010014
+#define GPIO_SKL_LP_GPP_B21 0x02010015
+#define GPIO_SKL_LP_GPP_B22 0x02010016
+#define GPIO_SKL_LP_GPP_B23 0x02010017
+#define GPIO_SKL_LP_GPP_C0 0x02020000
+#define GPIO_SKL_LP_GPP_C1 0x02020001
+#define GPIO_SKL_LP_GPP_C2 0x02020002
+#define GPIO_SKL_LP_GPP_C3 0x02020003
+#define GPIO_SKL_LP_GPP_C4 0x02020004
+#define GPIO_SKL_LP_GPP_C5 0x02020005
+#define GPIO_SKL_LP_GPP_C6 0x02020006
+#define GPIO_SKL_LP_GPP_C7 0x02020007
+#define GPIO_SKL_LP_GPP_C8 0x02020008
+#define GPIO_SKL_LP_GPP_C9 0x02020009
+#define GPIO_SKL_LP_GPP_C10 0x0202000A
+#define GPIO_SKL_LP_GPP_C11 0x0202000B
+#define GPIO_SKL_LP_GPP_C12 0x0202000C
+#define GPIO_SKL_LP_GPP_C13 0x0202000D
+#define GPIO_SKL_LP_GPP_C14 0x0202000E
+#define GPIO_SKL_LP_GPP_C15 0x0202000F
+#define GPIO_SKL_LP_GPP_C16 0x02020010
+#define GPIO_SKL_LP_GPP_C17 0x02020011
+#define GPIO_SKL_LP_GPP_C18 0x02020012
+#define GPIO_SKL_LP_GPP_C19 0x02020013
+#define GPIO_SKL_LP_GPP_C20 0x02020014
+#define GPIO_SKL_LP_GPP_C21 0x02020015
+#define GPIO_SKL_LP_GPP_C22 0x02020016
+#define GPIO_SKL_LP_GPP_C23 0x02020017
+#define GPIO_SKL_LP_GPP_D0 0x02030000
+#define GPIO_SKL_LP_GPP_D1 0x02030001
+#define GPIO_SKL_LP_GPP_D2 0x02030002
+#define GPIO_SKL_LP_GPP_D3 0x02030003
+#define GPIO_SKL_LP_GPP_D4 0x02030004
+#define GPIO_SKL_LP_GPP_D5 0x02030005
+#define GPIO_SKL_LP_GPP_D6 0x02030006
+#define GPIO_SKL_LP_GPP_D7 0x02030007
+#define GPIO_SKL_LP_GPP_D8 0x02030008
+#define GPIO_SKL_LP_GPP_D9 0x02030009
+#define GPIO_SKL_LP_GPP_D10 0x0203000A
+#define GPIO_SKL_LP_GPP_D11 0x0203000B
+#define GPIO_SKL_LP_GPP_D12 0x0203000C
+#define GPIO_SKL_LP_GPP_D13 0x0203000D
+#define GPIO_SKL_LP_GPP_D14 0x0203000E
+#define GPIO_SKL_LP_GPP_D15 0x0203000F
+#define GPIO_SKL_LP_GPP_D16 0x02030010
+#define GPIO_SKL_LP_GPP_D17 0x02030011
+#define GPIO_SKL_LP_GPP_D18 0x02030012
+#define GPIO_SKL_LP_GPP_D19 0x02030013
+#define GPIO_SKL_LP_GPP_D20 0x02030014
+#define GPIO_SKL_LP_GPP_D21 0x02030015
+#define GPIO_SKL_LP_GPP_D22 0x02030016
+#define GPIO_SKL_LP_GPP_D23 0x02030017
+#define GPIO_SKL_LP_GPP_E0 0x02040000
+#define GPIO_SKL_LP_GPP_E1 0x02040001
+#define GPIO_SKL_LP_GPP_E2 0x02040002
+#define GPIO_SKL_LP_GPP_E3 0x02040003
+#define GPIO_SKL_LP_GPP_E4 0x02040004
+#define GPIO_SKL_LP_GPP_E5 0x02040005
+#define GPIO_SKL_LP_GPP_E6 0x02040006
+#define GPIO_SKL_LP_GPP_E7 0x02040007
+#define GPIO_SKL_LP_GPP_E8 0x02040008
+#define GPIO_SKL_LP_GPP_E9 0x02040009
+#define GPIO_SKL_LP_GPP_E10 0x0204000A
+#define GPIO_SKL_LP_GPP_E11 0x0204000B
+#define GPIO_SKL_LP_GPP_E12 0x0204000C
+#define GPIO_SKL_LP_GPP_E13 0x0204000D
+#define GPIO_SKL_LP_GPP_E14 0x0204000E
+#define GPIO_SKL_LP_GPP_E15 0x0204000F
+#define GPIO_SKL_LP_GPP_E16 0x02040010
+#define GPIO_SKL_LP_GPP_E17 0x02040011
+#define GPIO_SKL_LP_GPP_E18 0x02040012
+#define GPIO_SKL_LP_GPP_E19 0x02040013
+#define GPIO_SKL_LP_GPP_E20 0x02040014
+#define GPIO_SKL_LP_GPP_E21 0x02040015
+#define GPIO_SKL_LP_GPP_E22 0x02040016
+#define GPIO_SKL_LP_GPP_E23 0x02040017
+#define GPIO_SKL_LP_GPP_F0 0x02050000
+#define GPIO_SKL_LP_GPP_F1 0x02050001
+#define GPIO_SKL_LP_GPP_F2 0x02050002
+#define GPIO_SKL_LP_GPP_F3 0x02050003
+#define GPIO_SKL_LP_GPP_F4 0x02050004
+#define GPIO_SKL_LP_GPP_F5 0x02050005
+#define GPIO_SKL_LP_GPP_F6 0x02050006
+#define GPIO_SKL_LP_GPP_F7 0x02050007
+#define GPIO_SKL_LP_GPP_F8 0x02050008
+#define GPIO_SKL_LP_GPP_F9 0x02050009
+#define GPIO_SKL_LP_GPP_F10 0x0205000A
+#define GPIO_SKL_LP_GPP_F11 0x0205000B
+#define GPIO_SKL_LP_GPP_F12 0x0205000C
+#define GPIO_SKL_LP_GPP_F13 0x0205000D
+#define GPIO_SKL_LP_GPP_F14 0x0205000E
+#define GPIO_SKL_LP_GPP_F15 0x0205000F
+#define GPIO_SKL_LP_GPP_F16 0x02050010
+#define GPIO_SKL_LP_GPP_F17 0x02050011
+#define GPIO_SKL_LP_GPP_F18 0x02050012
+#define GPIO_SKL_LP_GPP_F19 0x02050013
+#define GPIO_SKL_LP_GPP_F20 0x02050014
+#define GPIO_SKL_LP_GPP_F21 0x02050015
+#define GPIO_SKL_LP_GPP_F22 0x02050016
+#define GPIO_SKL_LP_GPP_F23 0x02050017
+#define GPIO_SKL_LP_GPP_G0 0x02060000
+#define GPIO_SKL_LP_GPP_G1 0x02060001
+#define GPIO_SKL_LP_GPP_G2 0x02060002
+#define GPIO_SKL_LP_GPP_G3 0x02060003
+#define GPIO_SKL_LP_GPP_G4 0x02060004
+#define GPIO_SKL_LP_GPP_G5 0x02060005
+#define GPIO_SKL_LP_GPP_G6 0x02060006
+#define GPIO_SKL_LP_GPP_G7 0x02060007
+#define GPIO_SKL_LP_GPD0 0x02070000
+#define GPIO_SKL_LP_GPD1 0x02070001
+#define GPIO_SKL_LP_GPD2 0x02070002
+#define GPIO_SKL_LP_GPD3 0x02070003
+#define GPIO_SKL_LP_GPD4 0x02070004
+#define GPIO_SKL_LP_GPD5 0x02070005
+#define GPIO_SKL_LP_GPD6 0x02070006
+#define GPIO_SKL_LP_GPD7 0x02070007
+#define GPIO_SKL_LP_GPD8 0x02070008
+#define GPIO_SKL_LP_GPD9 0x02070009
+#define GPIO_SKL_LP_GPD10 0x0207000A
+#define GPIO_SKL_LP_GPD11 0x0207000B
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioLib.h
new file mode 100644
index 0000000000..5362beeea3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioLib.h
@@ -0,0 +1,707 @@
+/** @file
+ Header file for GpioLib.
+ All function in this library is available for PEI, DXE, and SMM
+
+ @note: When GPIO pads are owned by ME Firmware, BIOS/host should not
+ attempt to access these GPIO Pads registers, registers value
+ returned in this case will be 0xFF.
+
+Copyright (c) 2017, 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 that 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 _GPIO_LIB_H_
+#define _GPIO_LIB_H_
+
+#include <GpioConfig.h>
+
+typedef struct {
+ GPIO_PAD GpioPad;
+ GPIO_CONFIG GpioConfig;
+} GPIO_INIT_CONFIG;
+/**
+ This procedure will initialize multiple GPIO pins. Use GPIO_INIT_CONFIG structure.
+ Structure contains fields that can be used to configure each pad.
+ Pad not configured using GPIO_INIT_CONFIG will be left with hardware default values.
+ Separate fields could be set to hardware default if it does not matter, except
+ GpioPad and PadMode.
+ Some GpioPads are configured and switched to native mode by RC, those include:
+ SerialIo pins, ISH pins, ClkReq Pins
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioConfigurePads (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ );
+
+//
+// Functions for setting/getting multiple GpioPad settings
+//
+
+/**
+ This procedure will read multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[out] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadConfig (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_CONFIG *GpioData
+ );
+
+/**
+ This procedure will configure multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_CONFIG *GpioData
+ );
+
+//
+// Functions for setting/getting single GpioPad properties
+//
+
+/**
+ This procedure will set GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetOutputValue (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ );
+
+/**
+ This procedure will get GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] OutputVal GPIO Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetOutputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *OutputVal
+ );
+
+/**
+ This procedure will get GPIO input level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InputVal GPIO Input value
+ 0: InputLow, 1: InputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InputVal
+ );
+
+/**
+ This procedure will get GPIO IOxAPIC interrupt number
+
+ @param[in] GpioPad GPIO pad
+ @param[out] IrqNum IRQ number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadIoApicIrqNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *IrqNum
+ );
+
+/**
+ This procedure will configure GPIO input inversion
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for GPIO input inversion
+ 0: No input inversion, 1: Invert input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetInputInversion (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ );
+
+/**
+ This procedure will get GPIO pad input inversion value
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InvertState GPIO inversion state
+ 0: No input inversion, 1: Inverted input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputInversion (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InvertState
+ );
+
+/**
+ This procedure will set GPIO interrupt settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Level/Edge
+ use GPIO_INT_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadInterruptConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_INT_CONFIG Value
+ );
+
+/**
+ This procedure will set GPIO electrical settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of termination
+ use GPIO_ELECTRICAL_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadElectricalConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_ELECTRICAL_CONFIG Value
+ );
+
+/**
+ This procedure will set GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for Pad Reset Configuration
+ use GPIO_RESET_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG Value
+ );
+
+/**
+ This procedure will get GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Pad Reset Configuration
+ based on GPIO_RESET_CONFIG
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG *Value
+ );
+
+/**
+ This procedure will get GPIO Host Software Pad Ownership for certain group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Host Ownership register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] HostSwRegVal Value of Host Software Pad Ownership register
+ Bit position - PadNumber
+ Bit value - 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *HostSwRegVal
+ );
+
+/**
+ This procedure will get GPIO Host Software Pad Ownership for certain group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Host Ownership register number for current group
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] HostSwRegVal Value of Host Software Pad Ownership register
+ Bit position - PadNumber
+ Bit value - 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 HostSwRegVal
+ );
+
+/**
+ This procedure will get Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadHostSwOwn Value of Host Software Pad Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadHostSwOwn
+ );
+
+/**
+ This procedure will set Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadHostSwOwn Pad Host Software Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadHostSwOwn
+ );
+
+///
+/// Possible values of Pad Ownership
+/// If Pad is not under Host ownership then GPIO registers
+/// are not accessible by host (e.g. BIOS) and reading them
+/// will return 0xFFs.
+///
+typedef enum {
+ GpioPadOwnHost = 0x0,
+ GpioPadOwnCsme = 0x1,
+ GpioPadOwnIsh = 0x2,
+} GPIO_PAD_OWN;
+
+/**
+ This procedure will get Gpio Pad Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadOwnVal Value of Pad Ownership
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadOwnership (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_OWN *PadOwnVal
+ );
+
+/**
+ This procedure will check state of Pad Config Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockRegVal Value of PadCfgLock register
+ Bit position - PadNumber
+ Bit value - 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockRegVal
+ );
+
+/**
+ This procedure will check state of Pad Config Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLock for selected pad
+ 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLock (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLock
+ );
+
+/**
+ This procedure will check state of Pad Config Tx Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockTxRegVal Value of PadCfgLockTx register
+ Bit position - PadNumber
+ Bit value - 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockTxRegVal
+ );
+
+/**
+ This procedure will check state of Pad Config Tx Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLockTx for selected pad
+ 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLockTx (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLockTx
+ );
+
+/**
+ This procedure will clear PadCfgLock for selected pads within one group.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlock Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnlock, 1: Unlock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlock
+ );
+
+/**
+ This procedure will clear PadCfgLock for selected pad.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioUnlockPadCfg (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will set PadCfgLock for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLock Bitmask for pads which are going to be locked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotLock, 1: Lock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLock
+ );
+
+/**
+ This procedure will set PadCfgLock for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioLockPadCfg (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will clear PadCfgLockTx for selected pads within one group.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlockTx Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlockTx
+ );
+
+/**
+ This procedure will clear PadCfgLockTx for selected pad.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioUnlockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will set PadCfgLockTx for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLockTx Bitmask for pads which are going to be locked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLockTx
+ );
+
+/**
+ This procedure will set PadCfgLockTx for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioLockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will get Group to GPE mapping.
+ Refer to BWG and EDS for GPIO GPE information.
+
+ @param[out] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[out] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[out] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGroupToGpeDwX (
+ IN GPIO_GROUP *GroupToGpeDw0,
+ IN GPIO_GROUP *GroupToGpeDw1,
+ IN GPIO_GROUP *GroupToGpeDw2
+ );
+
+/**
+ This procedure will set Group to GPE mapping.
+ Refer to BWG and EDS for GPIO GPE information.
+
+ @param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetGroupToGpeDwX (
+ IN GPIO_GROUP GroupToGpeDw0,
+ IN GPIO_GROUP GroupToGpeDw1,
+ IN GPIO_GROUP GroupToGpeDw2
+ );
+
+/**
+ This procedure will get GPE number for provided GpioPad.
+ PCH allows to configure mapping between GPIO groups and related GPE (GpioSetGroupToGpeDwX())
+ what results in the fact that certain Pad can cause different General Purpose Event. Only three
+ GPIO groups can be mapped to cause unique GPE (1-tier), all others groups will be under one common
+ event (GPE_111 for 2-tier).
+
+ 1-tier:
+ Returned GpeNumber is in range <0,95>. GpioGetGpeNumber() can be used
+ to determine what _LXX ACPI method would be called on event on selected GPIO pad
+
+ 2-tier:
+ Returned GpeNumber is 0x6F (111). All GPIO pads which are not mapped to 1-tier GPE
+ will be under one master GPE_111 which is linked to _L6F ACPI method. If it is needed to determine
+ what Pad from 2-tier has caused the event, _L6F method should check GPI_GPE_STS and GPI_GPE_EN
+ registers for all GPIO groups not mapped to 1-tier GPE.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpeNumber GPE number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpeNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *GpeNumber
+ );
+
+/**
+ This procedure is used to clear SMI STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiSmiSts (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure is used by Smi Dispatcher and will clear
+ all GPI SMI Status bits
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+GpioClearAllGpiSmiSts (
+ VOID
+ );
+
+/**
+ This procedure is used to disable all GPI SMI
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+GpioDisableAllGpiSmi (
+ VOID
+ );
+
+/**
+ This procedure is used to register GPI SMI dispatch function.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpiNum GPI number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiSmiNum (
+ IN GPIO_PAD GpioPad,
+ OUT UINTN *GpiNum
+ );
+
+/**
+ This procedure is used to check GPIO inputs belongs to 2 tier or 1 tier architecture
+
+ @param[in] GpioPad GPIO pad
+
+ @retval Data 0 means 1-tier, 1 means 2-tier
+**/
+BOOLEAN
+GpioCheckFor2Tier (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure is used to clear GPE STS for a specified GpioPad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiGpeSts (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure is used to read GPE STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] Data GPE STS data
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiGpeSts (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32* Data
+ );
+
+#endif // _GPIO_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioNativeLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioNativeLib.h
new file mode 100644
index 0000000000..5f2c57fd34
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/GpioNativeLib.h
@@ -0,0 +1,225 @@
+/** @file
+ Header file for GpioLib for native and Si specific usage.
+ All function in this library is available for PEI, DXE, and SMM,
+
+Copyright (c) 2017, 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 that 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 _GPIO_NATIVE_LIB_H_
+#define _GPIO_NATIVE_LIB_H_
+
+#include <GpioConfig.h>
+
+/**
+ This procedure will get number of pads for certain GPIO group
+
+ @param[in] Group GPIO group number
+
+ @retval Value Pad number for group
+ If illegal group number then return 0
+**/
+UINT32
+GpioGetPadPerGroup (
+ IN GPIO_GROUP Group
+ );
+
+/**
+ This procedure will get number of groups
+
+ @param[in] none
+
+ @retval Value Group number
+**/
+UINT8
+GpioGetNumberOfGroups (
+ VOID
+ );
+/**
+ This procedure will get lowest group
+
+ @param[in] none
+
+ @retval Value Lowest Group
+**/
+GPIO_GROUP
+GpioGetLowestGroup (
+ VOID
+ );
+
+/**
+ This procedure will get highest group
+
+ @param[in] none
+
+ @retval Value Highest Group
+**/
+GPIO_GROUP
+GpioGetHighestGroup (
+ VOID
+ );
+
+/**
+ This procedure will get group
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group
+**/
+GPIO_GROUP
+GpioGetGroupFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will get group index (0 based) from GpioPad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will get group index (0 based) from group
+
+ @param[in] GpioGroup Gpio Group
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGroup (
+ IN GPIO_GROUP GpioGroup
+ );
+
+/**
+ This procedure will get pad number (0 based) from Gpio Pad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Pad Number
+**/
+UINT32
+GpioGetPadNumberFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will return GpioPad from Group and PadNumber
+
+ @param[in] Group GPIO group
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupAndPadNumber (
+ IN GPIO_GROUP Group,
+ IN UINT32 PadNumber
+ );
+
+/**
+ This procedure will return GpioPad from GroupIndex and PadNumber
+
+ @param[in] GroupIndex GPIO GroupIndex
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupIndexAndPadNumber (
+ IN UINT32 GroupIndex,
+ IN UINT32 PadNumber
+ );
+
+/**
+ This function sets SerialIo I2C controller pins into native mode
+
+ @param[in] SerialIoI2cControllerNumber I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoI2cPinsIntoNativeMode (
+ IN UINT32 SerialIoI2cControllerNumber
+ );
+
+/**
+ This function sets SerialIo I2C controller pins tolerance
+
+ @param[in] SerialIoI2CControllerNumber I2C controller
+ @param[in] Pad1v8Tolerance TRUE: Enable 1v8 Pad tolerance
+ FALSE: Disable 1v8 Pad tolerance
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoI2CPinsTolerance (
+ IN UINT32 SerialIoI2CControllerNumber,
+ IN BOOLEAN Pad1v8Tolerance
+ );
+
+/**
+ This function sets SerialIo UART controller pins into native mode
+
+ @param[in] SerialIoI2CControllerNumber UART controller
+ @param[in] HardwareFlowControl Hardware Flow control
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoUartPinsIntoNativeMode (
+ IN UINT32 SerialIoUartControllerNumber,
+ IN BOOLEAN HardwareFlowControl
+ );
+
+/**
+ This function sets SerialIo SPI controller pins into native mode
+
+ @param[in] SerialIoI2CControllerNumber SPI controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoSpiPinsIntoNativeMode (
+ IN UINT32 SerialIoUartControllerNumber
+ );
+
+/**
+ This function checks if GPIO pin for SATA reset port is in GPIO MODE
+
+ @param[in] SataPort SATA port number
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsSataResetPortInGpioMode (
+ IN UINTN SataPort
+ );
+
+/**
+ This function checks if SataDevSlp pin is in native mode
+
+ @param[in] SataPort SATA port
+ @param[out] DevSlpPad DevSlpPad
+
+ @retval TRUE DevSlp is in native mode
+ FALSE DevSlp is not in native mode
+**/
+BOOLEAN
+GpioIsSataDevSlpPinEnabled (
+ IN UINTN SataPort,
+ OUT GPIO_PAD *DevSlpPad
+ );
+
+#endif // _GPIO_NATIVE_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/OcWdtLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/OcWdtLib.h
new file mode 100644
index 0000000000..9f5da64dff
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/OcWdtLib.h
@@ -0,0 +1,37 @@
+/** @file
+ Header file for OC WDT Library.
+
+Copyright (c) 2017, 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 that 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 _OC_WDT_LIB_H_
+#define _OC_WDT_LIB_H_
+
+/**
+ Check for unexpected reset.
+ If there was an unexpected reset, enforces WDT expiration.
+**/
+VOID
+OcWdtResetCheck (
+ VOID
+ );
+
+/**
+ This function install WDT PPI
+
+ @retval EFI_STATUS Results of the installation of the WDT PPI
+**/
+EFI_STATUS
+EFIAPI
+OcWdtInit (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
new file mode 100644
index 0000000000..30ad2713b5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
@@ -0,0 +1,345 @@
+/** @file
+ Header file for PchCycleDecodingLib.
+
+Copyright (c) 2017, 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 that 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 _PCH_CYCLE_DECODING_LIB_H_
+#define _PCH_CYCLE_DECODING_LIB_H_
+
+/**
+ Set PCH ACPI base address.
+ The Address should not be 0 and should be 256 bytes alignment, and it is IO space, so must not exceed 0xFFFF.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. clear PMC PCI offset 44h [7] to diable ACPI base address first before changing base address.
+ 2. program PMC PCI offset 40h [15:2] to ACPI base address.
+ 3. set PMC PCI offset 44h [7] to enable ACPI base address.
+ 4. program "ACPI Base Address" PCR[DMI] + 27B4h[23:18, 15:2, 0] to [0x3F, PMC PCI Offset 40h bit[15:2], 1].
+ 5. Program "ACPI Base Destination ID" PCR[DMI] + 27B8h[31:0] to [0x23A0].
+
+ @param[in] Address Address for ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseSet (
+ IN UINT16 Address
+ );
+
+/**
+ Get PCH ACPI base address.
+
+ @param[out] Address Address of ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseGet (
+ OUT UINT16 *Address
+ );
+
+/**
+ Set PCH PWRM base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. clear PMC PCI offset 44h [8] to diable PWRM base address first before changing PWRM base address.
+ 2. program PMC PCI offset 48h [31:16] to PM base address.
+ 3. set PMC PCI offset 44h [8] to enable PWRM base address.
+ 4. program "PM Base Address Memory Range Base" PCR[DMI] + 27ACh[15:0] to the same value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the PWRMBASE to be 64KB aligned.
+ program "PM Base Address Memory Range Limit" PCR[DMI] + 27ACh[31:16] to the value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the memory allocated to PWRMBASE to be 64KB in size.
+ 5. program "PM Base Control" PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A0].
+
+ @param[in] Address Address for PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseSet (
+ IN UINT32 Address
+ );
+
+/**
+ Get PCH PWRM base address.
+
+ @param[out] Address Address of PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseGet (
+ OUT UINT32 *Address
+ );
+
+/**
+ Set PCH TCO base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. set Smbus PCI offset 54h [8] to enable TCO base address.
+ 2. program Smbus PCI offset 50h [15:5] to TCO base address.
+ 3. set Smbus PCI offset 54h [8] to enable TCO base address.
+ 4. program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1] to [Smbus PCI offset 50h[15:5], 1].
+
+ @param[in] Address Address for TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchTcoBaseSet (
+ IN UINT16 Address
+ );
+
+/**
+ Get PCH TCO base address.
+
+ @param[out] Address Address of TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchTcoBaseGet (
+ OUT UINT16 *Address
+ );
+
+///
+/// structure of LPC general IO range register
+/// It contains base address, address mask, and enable status.
+///
+typedef struct {
+ UINT32 BaseAddr :16;
+ UINT32 Length :15;
+ UINT32 Enable : 1;
+} PCH_LPC_GEN_IO_RANGE;
+
+#define PCH_LPC_GEN_IO_RANGE_MAX 4
+///
+/// structure of LPC general IO range register list
+/// It lists all LPC general IO ran registers supported by PCH.
+///
+typedef struct {
+ PCH_LPC_GEN_IO_RANGE Range[PCH_LPC_GEN_IO_RANGE_MAX];
+} PCH_LPC_GEN_IO_RANGE_LIST;
+
+/**
+ Set PCH LPC generic IO range.
+ For generic IO range, the base address must align to 4 and less than 0xFFFF, and the length must be power of 2
+ and less than or equal to 256. Moreover, the address must be length aligned.
+ This function basically checks the address and length, which should not overlap with all other generic ranges.
+ If no more generic range register available, it returns out of resource error.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ The IO ranges below 0x100 have fixed target. The target might be ITSS,RTC,LPC,PMC or terminated inside P2SB
+ but all predefined and can't be changed. IO range below 0x100 will be skipped except 0x80-0x8F.
+ Steps of programming generic IO range:
+ 1. Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ 2. Program LPC/eSPI Generic IO Range #, PCR[DMI] + 2730h ~ 273Fh to the same value programmed in LPC/eSPI PCI Offset 84h~93h.
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeSet (
+ IN UINT16 Address,
+ IN UINTN Length
+ );
+
+/**
+ Get PCH LPC generic IO range list.
+ This function returns a list of base address, length, and enable for all LPC generic IO range regsiters.
+
+ @param[out] LpcGenIoRangeList Return all LPC generic IO range register status.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeGet (
+ OUT PCH_LPC_GEN_IO_RANGE_LIST *LpcGenIoRangeList
+ );
+
+/**
+ Set PCH LPC memory range decoding.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program LPC/eSPI PCI 98h [0] to [0] to disable memory decoding first before changing base address.
+ 2. Program LPC/eSPI PCI 98h [31:16, 0] to [Address, 1].
+ 3. Program LPC/eSPI Memory Range, PCR[DMI] + 2740h to the same value programmed in LPC/eSPI PCI Offset 98h.
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeSet (
+ IN UINT32 Address
+ );
+
+/**
+ Get PCH LPC memory range decoding address.
+
+ @param[out] Address Address of LPC memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeGet (
+ OUT UINT32 *Address
+ );
+
+/**
+ Set PCH BIOS range deocding.
+ This will check General Control and Status bit 10 (GCS.BBS) to identify SPI or LPC/eSPI and program BDE register accordingly.
+ Please check EDS for detail of BiosDecodeEnable bit definition.
+ bit 15: F8-FF Enable
+ bit 14: F0-F8 Enable
+ bit 13: E8-EF Enable
+ bit 12: E0-E8 Enable
+ bit 11: D8-DF Enable
+ bit 10: D0-D7 Enable
+ bit 9: C8-CF Enable
+ bit 8: C0-C7 Enable
+ bit 7: Legacy F Segment Enable
+ bit 6: Legacy E Segment Enable
+ bit 5: Reserved
+ bit 4: Reserved
+ bit 3: 70-7F Enable
+ bit 2: 60-6F Enable
+ bit 1: 50-5F Enable
+ bit 0: 40-4F Enable
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. if GCS.BBS is 0 (SPI), program SPI PCI offset D8h to BiosDecodeEnable.
+ if GCS.BBS is 1 (LPC/eSPi), program LPC/eSPI PCI offset D8h to BiosDecodeEnable.
+ 2. program LPC/eSPI/SPI BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC/eSPI or SPI PCI Offset D8h.
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+EFIAPI
+PchBiosDecodeEnableSet (
+ IN UINT16 BiosDecodeEnable
+ );
+
+/**
+ Set PCH LPC IO decode ranges.
+ Program LPC I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC offset 80h.
+ Please check EDS for detail of Lpc IO decode ranges bit definition.
+ Bit 12: FDD range
+ Bit 9:8: LPT range
+ Bit 6:4: ComB range
+ Bit 2:0: ComA range
+
+ @param[in] LpcIoDecodeRanges Lpc IO decode ranges bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoDecodeRangesSet (
+ IN UINT16 LpcIoDecodeRanges
+ );
+
+/**
+ Set PCH LPC IO enable decoding.
+ Setup LPC I/O Enables, PCR[DMI] + 2774h[15:0] to the same value program in LPC offset 82h.
+ Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+ in LPC 82h[13:10] is always forwarded by DMI to subtractive agent for handling.
+ Please check EDS for detail of Lpc IO decode ranges bit definition.
+
+ @param[in] LpcIoEnableDecoding Lpc IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoEnableDecodingSet (
+ IN UINT16 LpcIoEnableDecoding
+ );
+
+/**
+ Set PCH IO port 80h cycle decoding to PCIE root port.
+ System BIOS is likely to do this very soon after reset before PCI bus enumeration, it must ensure that
+ the IO Base Address field (PCIe:1Ch[7:4]) contains a value greater than the IO Limit field (PCIe:1Ch[15:12])
+ before setting the IOSE bit. Otherwise the bridge will positively decode IO range 000h - FFFh by its default
+ IO range values.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program "RPR Destination ID", PCR[DMI] + 274Ch[31:16] to the Dest ID of RP.
+ 2. Program "Reserved Page Route", PCR[DMI] + 274Ch[11] to '1'. Use byte write on GCS+1 and leave the BILD bit which is RWO.
+ 3. Program IOSE bit of PCIE:Reg04h[0] to '1' for PCH to send such IO cycles to PCIe bus for subtractive decoding.
+
+ @param[in] RpPhyNumber PCIE root port physical number.
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+EFIAPI
+PchIoPort80DecodeSet (
+ IN UINTN RpPhyNumber
+ );
+
+/**
+ Get IO APIC regsiters base address.
+ It returns IO APIC INDEX, DATA, and EOI regsiter address once the parameter is not NULL.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] IoApicIndex Buffer of IO APIC INDEX regsiter address
+ @param[out] IoApicData Buffer of IO APIC DATA regsiter address
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PchIoApicBaseGet (
+ OPTIONAL OUT UINT32 *IoApicIndex,
+ OPTIONAL OUT UINT32 *IoApicData
+ );
+
+/**
+ Get HPET base address.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] HpetBase Buffer of HPET base address
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchHpetBaseGet (
+ OUT UINT32 *HpetBase
+ );
+
+#endif // _PCH_CYCLE_DECODING_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchEspiLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchEspiLib.h
new file mode 100644
index 0000000000..2096645375
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchEspiLib.h
@@ -0,0 +1,102 @@
+/** @file
+ Header file for PchEspiLib.
+ All function in this library is available for PEI, DXE, and SMM,
+
+Copyright (c) 2017, 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 that 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 _PCH_ESPI_LIB_H_
+#define _PCH_ESPI_LIB_H_
+
+/**
+ Is eSPI enabled in strap.
+
+ @retval TRUE Espi is enabled in strap
+ @retval FALSE Espi is disabled in strap
+**/
+BOOLEAN
+IsEspiEnabled (
+ VOID
+ );
+
+/**
+ Get configuration from eSPI slave
+
+ @param[in] SlaveId eSPI slave ID
+ @param[in] SlaveAddress Slave Configuration Register Address
+ @param[out] OutData Configuration data read
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_INVALID_PARAMETER Slave configuration register address exceed maximum allowed
+ @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveGetConfig (
+ IN UINT32 SlaveId,
+ IN UINT32 SlaveAddress,
+ OUT UINT32 *OutData
+ );
+
+/**
+ Set eSPI slave configuration
+
+ @param[in] SlaveId eSPI slave ID
+ @param[in] SlaveAddress Slave Configuration Register Address
+ @param[in] InData Configuration data to write
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_INVALID_PARAMETER Slave configuration register address exceed maximum allowed
+ @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned
+ @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7FF has been locked
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveSetConfig (
+ IN UINT32 SlaveId,
+ IN UINT32 SlaveAddress,
+ IN UINT32 InData
+ );
+
+/**
+ Get status from eSPI slave
+
+ @param[in] SlaveId eSPI slave ID
+ @param[out] OutData Configuration data read
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveGetStatus (
+ IN UINT32 SlaveId,
+ OUT UINT16 *OutData
+ );
+
+/**
+ eSPI slave in-band reset
+
+ @param[in] SlaveId eSPI slave ID
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveInBandReset (
+ IN UINT32 SlaveId
+ );
+
+#endif // _PEI_DXE_SMM_PCH_ESPI_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchGbeLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchGbeLib.h
new file mode 100644
index 0000000000..5461286634
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchGbeLib.h
@@ -0,0 +1,64 @@
+/** @file
+ Header file for PchGbeLib.
+
+Copyright (c) 2017, 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 that 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 _PCH_GBE_LIB_H_
+#define _PCH_GBE_LIB_H_
+
+/**
+ Check whether GbE region is valid
+ Check SPI region directly since GBE might be disabled in SW.
+
+ @retval TRUE Gbe Region is valid
+ @retval FALSE Gbe Region is invalid
+**/
+BOOLEAN
+PchIsGbeRegionValid (
+ VOID
+ );
+
+/**
+ Returns GbE over PCIe port number based on a soft strap.
+
+ @return Root port number (1-based)
+ @retval 0 GbE over PCIe disabled
+**/
+UINT32
+PchGetGbePortNumber (
+ VOID
+ );
+
+/**
+ Check whether LAN controller is enabled in the platform.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+PchIsGbePresent (
+ VOID
+ );
+
+/**
+ Check whether LAN controller is enabled in the platform.
+
+ @deprecated Use PchIsGbePresent instead.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+PchIsGbeAvailable (
+ VOID
+ );
+
+#endif // _PCH_GBE_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchHsioLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchHsioLib.h
new file mode 100644
index 0000000000..65076800a9
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchHsioLib.h
@@ -0,0 +1,114 @@
+/** @file
+ Header file for PchHsioLib.
+
+Copyright (c) 2017, 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 that 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 _PCH_HSIO_LIB_H_
+#define _PCH_HSIO_LIB_H_
+
+/**
+ Represents HSIO lane
+**/
+typedef struct {
+ UINT8 Index; ///< Lane index
+ UINT8 Pid; ///< Sideband ID
+ UINT16 Base; ///< Sideband base address
+} HSIO_LANE;
+
+/**
+ The function returns the Port Id and lane owner for the specified lane
+
+ @param[in] PhyMode Phymode that needs to be checked
+ @param[out] Pid Common Lane End Point ID
+ @param[out] LaneOwner Lane Owner
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid lane number
+**/
+EFI_STATUS
+EFIAPI
+PchGetLaneInfo (
+ IN UINT32 LaneNum,
+ OUT UINT8 *PortId,
+ OUT UINT8 *LaneOwner
+ );
+
+/**
+ Get HSIO lane representation needed to perform any operation on the lane.
+
+ @param[in] LaneIndex Number of the HSIO lane
+ @param[out] HsioLane HSIO lane representation
+**/
+VOID
+HsioGetLane (
+ IN UINT8 LaneIndex,
+ OUT HSIO_LANE *HsioLane
+ );
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] PcieLaneIndex PCIE Root Port Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetPcieLaneNum (
+ UINT32 PcieLaneIndex,
+ UINT8 *LaneNum
+ );
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] SataLaneIndex Sata Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetSataLaneNum (
+ UINT32 SataLaneIndex,
+ UINT8 *LaneNum
+ );
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] Usb3LaneIndex USB3 Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetUsb3LaneNum (
+ UINT32 Usb3LaneIndex,
+ UINT8 *LaneNum
+ );
+
+/**
+ Determine the lane number of a specified port
+
+ @param[out] LaneNum GBE Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetGbeLaneNum (
+ UINT8 *LaneNum
+ );
+
+#endif // _PCH_HSIO_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchInfoLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
new file mode 100644
index 0000000000..5902b92f18
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
@@ -0,0 +1,260 @@
+/** @file
+ Header file for PchInfoLib.
+
+Copyright (c) 2017, 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 that 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 _PCH_INFO_LIB_H_
+#define _PCH_INFO_LIB_H_
+
+#include <PchAccess.h>
+
+typedef enum {
+ PchH = 1,
+ PchLp,
+ PchUnknownSeries
+} PCH_SERIES;
+
+typedef enum {
+ SklPch = 1,
+ KblPch,
+ PchUnknownGeneration
+} PCH_GENERATION;
+
+typedef enum {
+ RstUnsupported = 0,
+ RstPremium,
+ RstOptane,
+ RstMaxMode
+} RST_MODE;
+
+typedef enum {
+ PchMobileSku = 0,
+ PchDesktopSku,
+ PchServerSku,
+ PchUnknownSku,
+ PchMaxSku
+} PCH_SKU_TYPE;
+
+/**
+ Return Pch stepping type
+
+ @retval PCH_STEPPING Pch stepping type
+**/
+PCH_STEPPING
+EFIAPI
+PchStepping (
+ VOID
+ );
+
+/**
+ Determine if PCH is supported
+
+ @retval TRUE PCH is supported
+ @retval FALSE PCH is not supported
+**/
+BOOLEAN
+IsPchSupported (
+ VOID
+ );
+
+/**
+ Return Pch Series
+
+ @retval PCH_SERIES Pch Series
+**/
+PCH_SERIES
+EFIAPI
+GetPchSeries (
+ VOID
+ );
+
+/**
+ Return Pch Generation
+
+ @retval PCH_GENERATION Pch Generation
+**/
+PCH_GENERATION
+EFIAPI
+GetPchGeneration (
+ VOID
+ );
+
+/**
+ Get PCH SKU type
+
+ @retval PCH_SKU_TYPE Type of PCH SKU
+**/
+PCH_SKU_TYPE
+GetPchSkuType (
+ VOID
+ );
+
+/**
+ Get Lpc Did
+
+ @retval UINT16 Lpc Did
+**/
+UINT16
+EFIAPI
+GetLpcDid (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Pcie Root Port Number
+
+ @retval PcieMaxRootPort Pch Maximum Pcie Root Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPciePortNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Sata Port Number
+
+ @retval Pch Maximum Sata Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxSataPortNum (
+ VOID
+ );
+
+/**
+ Get Pch Usb Maximum Physical Port Number
+
+ @retval Pch Usb Maximum Physical Port Number
+**/
+UINT8
+EFIAPI
+GetPchUsbMaxPhysicalPortNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Usb2 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb2 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb2PortNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Usb3 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb3 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb3PortNum (
+ VOID
+ );
+
+/**
+ Get PCH stepping ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchStep Pch stepping
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The stepping is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSteppingStr (
+ IN PCH_STEPPING PchStep,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ );
+
+/**
+ Get PCH series ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchSeries Pch series
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSeriesStr (
+ IN PCH_SERIES PchSeries,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ );
+
+/**
+ Get PCH Sku ASCII string
+ The return string is zero terminated.
+
+ @param [in] LpcDid LPC device id
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSkuStr (
+ IN UINT16 LpcDid,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ );
+
+/**
+ Get RST mode supported by the silicon
+
+ @retval RST_MODE RST mode supported by silicon
+**/
+RST_MODE
+EFIAPI
+GetSupportedRstMode (
+ VOID
+ );
+
+/**
+ Check if current SKU supports Optane mode
+
+ @retval TRUE This SKU supports Optane mode
+ @retval FALSE This SKU doesn't support Optane mode
+**/
+BOOLEAN
+EFIAPI
+IsOptaneModeSupported (
+ VOID
+ );
+
+/**
+ Check if current SKU supports RAID feature
+
+ @retval TRUE This SKU supports RAID
+ @retval FALSE This SKU doesn't support RAID
+**/
+BOOLEAN
+EFIAPI
+IsPchRaidSupported (
+ VOID
+ );
+#endif // _PCH_INFO_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchP2sbLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchP2sbLib.h
new file mode 100644
index 0000000000..8083ac4efd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchP2sbLib.h
@@ -0,0 +1,160 @@
+/** @file
+ Header file for PchP2sbLib.
+
+Copyright (c) 2017, 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 that 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 _PCH_P2SB_LIB_H_
+#define _PCH_P2SB_LIB_H_
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet32 (
+ IN UINTN Offset,
+ OUT UINT32 *OutData
+ );
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 2bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet16 (
+ IN UINTN Offset,
+ OUT UINT16 *OutData
+ );
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 1byte.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet8 (
+ IN UINTN Offset,
+ OUT UINT8 *OutData
+ );
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet32 (
+ IN UINTN Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ );
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 2bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet16 (
+ IN UINTN Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ );
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 1bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet8 (
+ IN UINTN Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ );
+
+/**
+ Hide P2SB device.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+PchHideP2sb (
+ IN UINTN P2sbBase
+ );
+
+/**
+ Reveal P2SB device.
+ Also return the original P2SB status which is for Hidding P2SB or not after.
+ If OrgStatus is not NULL, then TRUE means P2SB is unhidden,
+ and FALSE means P2SB is hidden originally.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+ @param[out] OrgStatus Original P2SB hidding/unhidden status
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+PchRevealP2sb (
+ IN UINTN P2sbBase,
+ OUT BOOLEAN *OrgStatus
+ );
+
+#endif // _PCH_P2SB_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcieRpLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcieRpLib.h
new file mode 100644
index 0000000000..d5084772dd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcieRpLib.h
@@ -0,0 +1,110 @@
+/** @file
+ Header file for PchPcieRpLib.
+
+Copyright (c) 2017, 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 that 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 _PCH_PCIERP_LIB_H_
+#define _PCH_PCIERP_LIB_H_
+
+#define RST_PCIE_STORAGE_CR_1 0
+#define RST_PCIE_STORAGE_CR_2 1
+#define RST_PCIE_STORAGE_CR_3 2
+#define RST_PCIE_STORAGE_CR_INVALID 99
+
+typedef struct {
+ UINT8 DevNum;
+ UINT8 Pid;
+ UINT8 RpNumBase;
+} PCH_PCIE_CONTROLLER_INFO;
+
+/**
+ Get Pch Pcie Root Port Device and Function Number by Root Port physical Number
+
+ @param[in] RpNumber Root port physical number. (0-based)
+ @param[out] RpDev Return corresponding root port device number.
+ @param[out] RpFun Return corresponding root port function number.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+GetPchPcieRpDevFun (
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ );
+
+/**
+ Get Root Port physical Number by Pch Pcie Root Port Device and Function Number
+
+ @param[in] RpDev Root port device number.
+ @param[in] RpFun Root port function number.
+ @param[out] RpNumber Return corresponding physical Root Port index (0-based)
+
+ @retval EFI_SUCCESS Physical root port is retrieved
+ @retval EFI_INVALID_PARAMETER RpDev and/or RpFun are invalid
+ @retval EFI_UNSUPPORTED Root port device and function is not assigned to any physical root port
+**/
+EFI_STATUS
+EFIAPI
+GetPchPcieRpNumber (
+ IN UINTN RpDev,
+ IN UINTN RpFun,
+ OUT UINTN *RpNumber
+ );
+
+/**
+ Gets base address of PCIe root port.
+
+ @param RpIndex Root Port Index (0 based)
+ @return PCIe port base address.
+**/
+UINTN
+PchPcieBase (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Determines whether L0s is supported on current stepping.
+
+ @return TRUE if L0s is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieL0sSupported (
+ VOID
+ );
+
+/**
+ Some early SKL PCH steppings require Native ASPM to be disabled due to hardware issues:
+ - RxL0s exit causes recovery
+ - Disabling PCIe L0s capability disables L1
+ Use this function to determine affected steppings.
+
+ @return TRUE if Native ASPM is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieNativeAspmSupported (
+ VOID
+ );
+
+/**
+ Check the RST PCIe Storage Cycle Router number according to the root port number and PCH type
+
+ @param[in] RootPortNum Root Port Number
+
+ @retval UINT32 The RST PCIe Storage Cycle Router Number
+**/
+UINT32
+RstGetCycleRouterNumber (
+ IN UINT32 RootPortNum
+ );
+
+#endif // _PCH_PCIERP_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcrLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcrLib.h
new file mode 100644
index 0000000000..149168993f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPcrLib.h
@@ -0,0 +1,196 @@
+/** @file
+ Header file for PchPcrLib.
+
+Copyright (c) 2017, 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 that 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 _PCH_PCR_LIB_H_
+#define _PCH_PCR_LIB_H_
+
+#include <PchAccess.h>
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT32 *OutData
+ );
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT16 *OutData
+ );
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT8 *OutData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 InData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 InData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 InData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ );
+
+#endif // _PCH_PCR_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPmcLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPmcLib.h
new file mode 100644
index 0000000000..61a955802a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPmcLib.h
@@ -0,0 +1,50 @@
+/** @file
+ Header file for PchPmcLib.
+
+Copyright (c) 2017, 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 that 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 _PCH_PMC_LIB_H_
+#define _PCH_PMC_LIB_H_
+
+typedef enum {
+ WarmBoot = 1,
+ ColdBoot,
+ PwrFlr,
+ PwrFlrSys,
+ PwrFlrPch,
+ PchPmStatusMax
+} PCH_PM_STATUS;
+
+/**
+ Query PCH to determine the Pm Status
+
+ @param[in] PmStatus - The Pch Pm Status to be probed
+
+ @retval Status TRUE if Status querried is Valid or FALSE if otherwise
+**/
+BOOLEAN
+GetPchPmStatus (
+ PCH_PM_STATUS PmStatus
+ );
+
+/**
+ Funtion to check if Battery lost or CMOS cleared.
+
+ @reval TRUE Battery is always present.
+ @reval FALSE CMOS is cleared.
+**/
+BOOLEAN
+EFIAPI
+PchIsRtcBatteryGood (
+ VOID
+ );
+
+#endif // _PCH_PMC_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPolicyLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPolicyLib.h
new file mode 100644
index 0000000000..f4e3659960
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPolicyLib.h
@@ -0,0 +1,113 @@
+/** @file
+ Prototype of the PeiPchPolicy library.
+
+Copyright (c) 2017, 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 that 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 _PEI_PCH_POLICY_LIB_H_
+#define _PEI_PCH_POLICY_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+
+/**
+ Print whole PCH_PREMEM_POLICY_PPI and serial out.
+
+ @param[in] SiPreMemPolicyPpi The RC PREMEM Policy PPI instance
+**/
+VOID
+EFIAPI
+PchPreMemPrintPolicyPpi (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
+ );
+
+/**
+ Print whole SI_POLICY_PPI and serial out.
+
+ @param[in] SiPolicyPpi The RC Policy PPI instance
+**/
+VOID
+EFIAPI
+PchPrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ );
+
+/**
+ Get PCH PREMEM config block table total size.
+
+ @retval Size of PCH PREMEM config block table
+**/
+UINT16
+EFIAPI
+PchGetPreMemConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ Get PCH config block table total size.
+
+ @retval Size of PCH config block table
+**/
+UINT16
+EFIAPI
+PchGetConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ PchAddPreMemConfigBlocks 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
+PchAddPreMemConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+/**
+ 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
+ );
+
+/*
+ Apply sample board PCH specific default settings
+
+ @param[in] SiPreMemPolicy The pointer to SI PREMEM Policy PPI instance
+*/
+VOID
+EFIAPI
+PchLoadSamplePreMemPolicy (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicy
+ );
+
+/*
+ Apply sample board PCH specific default settings
+
+ @param[in] SiPolicyPpi The pointer to SI Policy PPI instance
+*/
+VOID
+EFIAPI
+PchLoadSamplePolicy (
+ IN SI_POLICY_PPI *SiPolicy
+ );
+
+#endif // _PEI_PCH_POLICY_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPsfLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPsfLib.h
new file mode 100644
index 0000000000..4a2924f8f6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchPsfLib.h
@@ -0,0 +1,170 @@
+/** @file
+ Header file for PchPsfLib.
+ This is helper library of RC for PSF register programming.
+ It's not expected to be used in platform code.
+
+Copyright (c) 2017, 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 that 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 _PCH_PSF_LIB_H_
+#define _PCH_PSF_LIB_H_
+
+#include <Library/PchSerialIoLib.h>
+
+/**
+ This procedure will enable SerialIO device BAR1 at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfEnableSerialIoDeviceBar1 (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ );
+
+/**
+ This procedure will disable SerialIO device BAR1 at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfDisableSerialIoDeviceBar1 (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ );
+
+/**
+ This procedure will disable SerailIO device at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfDisableSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ );
+
+/**
+ This procedure will hide SerialIo device PciCfgSpace at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfHideSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ );
+
+/**
+ This procedure will reveal SerialIo device PciCfgSpace at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfRevealSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ );
+
+/**
+ This procedure will set BARx value for TraceHub ACPI device at PSF level
+
+ @param[in] BarNum BAR Number (0:BAR0, 1:BAR1)
+ @param[in] BarValue 32bit BAR value
+
+ @retval None
+**/
+VOID
+PsfSetTraceHubAcpiDeviceBarValue (
+ IN UINT8 BarNum,
+ IN UINT32 BarValue
+ );
+
+/**
+ This procedure will enable MSE for TraceHub ACPI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfEnableTraceHubAcpiDeviceMemorySpace (
+ VOID
+ );
+
+/**
+ Enable HECI device at PSF level
+
+ @param[in] HeciDevice HECIx Device (HECI1-3)
+
+ @retval None
+**/
+VOID
+PsfEnableHeciDevice (
+ IN UINT8 HeciDevice
+ );
+
+/**
+ Disable HECI device at PSF level
+
+ @param[in] HeciDevice HECIx Device (HECI1-3)
+
+ @retval None
+**/
+VOID
+PsfDisableHeciDevice (
+ IN UINT8 HeciDevice
+ );
+
+/**
+ Enable IDER device at PSF level
+
+ @retval None
+**/
+VOID
+PsfEnableIderDevice (
+ VOID
+ );
+
+/**
+ Disable IDER device at PSF level
+
+ @retval None
+**/
+VOID
+PsfDisableIderDevice (
+ VOID
+ );
+
+/**
+ Enable SOL device at PSF level
+
+ @retval None
+**/
+VOID
+PsfEnableSolDevice (
+ VOID
+ );
+
+/**
+ Disable SOL device at PSF level
+
+ @retval None
+**/
+VOID
+PsfDisableSolDevice (
+ VOID
+ );
+#endif // _PCH_PSF_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchResetLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchResetLib.h
new file mode 100644
index 0000000000..448cd21f50
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchResetLib.h
@@ -0,0 +1,30 @@
+/** @file
+ Header file for PCH RESET Driver.
+
+Copyright (c) 2017, 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 that 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 _PCH_RESET_LIB_H_
+#define _PCH_RESET_LIB_H_
+
+
+/**
+ Initialize PCH Reset APIs
+
+ @retval EFI_SUCCESS APIs are installed successfully
+ @retval EFI_OUT_OF_RESOURCES Can't allocate pool
+**/
+EFI_STATUS
+EFIAPI
+PchInitializeReset (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSbiAccessLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSbiAccessLib.h
new file mode 100644
index 0000000000..87d3318260
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSbiAccessLib.h
@@ -0,0 +1,162 @@
+/** @file
+ Header file for PchSbiAccessLib.
+
+Copyright (c) 2017, 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 that 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 _PCH_SBI_ACCESS_LIB_H_
+#define _PCH_SBI_ACCESS_LIB_H_
+
+/**
+ PCH SBI Register structure
+**/
+typedef struct {
+ UINT32 SbiAddr;
+ UINT32 SbiExtAddr;
+ UINT32 SbiData;
+ UINT16 SbiStat;
+ UINT16 SbiRid;
+} PCH_SBI_REGISTER_STRUCT;
+
+/**
+ PCH SBI opcode definitions
+**/
+typedef enum {
+ MemoryRead = 0x0,
+ MemoryWrite = 0x1,
+ PciConfigRead = 0x4,
+ PciConfigWrite = 0x5,
+ PrivateControlRead = 0x6,
+ PrivateControlWrite = 0x7,
+ GpioLockUnlock = 0x13
+} PCH_SBI_OPCODE;
+
+/**
+ PCH SBI response status definitions
+**/
+typedef enum {
+ SBI_SUCCESSFUL = 0,
+ SBI_UNSUCCESSFUL = 1,
+ SBI_POWERDOWN = 2,
+ SBI_MIXED = 3,
+ SBI_INVALID_RESPONSE
+} PCH_SBI_RESPONSE;
+
+/**
+ Execute PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+**/
+EFI_STATUS
+EFIAPI
+PchSbiExecution (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ );
+
+/**
+ Full function for executing PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in] Fbe First byte enable
+ @param[in] Bar Bar
+ @param[in] Fid Function ID
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+**/
+EFI_STATUS
+EFIAPI
+PchSbiExecutionEx (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN UINT16 Fbe,
+ IN UINT16 Bar,
+ IN UINT16 Fid,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ );
+
+/**
+ This function saves all PCH SBI registers.
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in, out] PchSbiRegister Structure for saving the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterSave (
+ IN OUT PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ );
+
+/**
+ This function restores all PCH SBI registers
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in] PchSbiRegister Structure for restoring the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterRestore (
+ IN PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ );
+
+#endif // _PCH_SBI_ACCESS_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoLib.h
new file mode 100644
index 0000000000..4ee5a9713e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoLib.h
@@ -0,0 +1,219 @@
+/** @file
+ Header file for PCH Serial IO Lib implementation.
+
+Copyright (c) 2017, 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 that 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 _PCH_SERIAL_IO_LIB_H_
+#define _PCH_SERIAL_IO_LIB_H_
+
+typedef enum {
+ PchSerialIoIndexI2C0,
+ PchSerialIoIndexI2C1,
+ PchSerialIoIndexI2C2,
+ PchSerialIoIndexI2C3,
+ PchSerialIoIndexI2C4,
+ PchSerialIoIndexI2C5,
+ PchSerialIoIndexSpi0,
+ PchSerialIoIndexSpi1,
+ PchSerialIoIndexUart0,
+ PchSerialIoIndexUart1,
+ PchSerialIoIndexUart2,
+ PchSerialIoIndexMax
+} PCH_SERIAL_IO_CONTROLLER;
+
+typedef enum {
+ PchSerialIoDisabled,
+ PchSerialIoAcpi,
+ PchSerialIoPci,
+ PchSerialIoAcpiHidden,
+ PchSerialIoLegacyUart,
+ PchSerialIoSkipInit
+} PCH_SERIAL_IO_MODE;
+
+enum PCH_LP_SERIAL_IO_VOLTAGE_SEL {
+ PchSerialIoIs33V = 0,
+ PchSerialIoIs18V
+};
+enum PCH_LP_SERIAL_IO_CS_POLARITY {
+ PchSerialIoCsActiveLow = 0,
+ PchSerialIoCsActiveHigh = 1
+};
+enum PCH_LP_SERIAL_IO_HW_FLOW_CTRL {
+ PchSerialIoHwFlowCtrlDisabled = 0,
+ PchSerialIoHwFlowControlEnabled = 1
+};
+
+#define SERIALIO_HID_LENGTH 8 // including null terminator
+#define SERIALIO_UID_LENGTH 1
+#define SERIALIO_CID_LENGTH 1
+#define SERIALIO_TOTAL_ID_LENGTH SERIALIO_HID_LENGTH+SERIALIO_UID_LENGTH+SERIALIO_CID_LENGTH
+
+/**
+ Returns index of the last i2c controller
+
+ @param[in] Number Number of SerialIo controller
+
+ @retval Index of I2C controller
+**/
+PCH_SERIAL_IO_CONTROLLER
+GetMaxI2cNumber (
+ VOID
+ );
+
+/**
+ Returns string with AcpiHID assigned to selected SerialIo controller
+
+ @param[in] Number Number of SerialIo controller
+
+ @retval pointer to 8-byte string
+**/
+CHAR8*
+GetSerialIoAcpiHID (
+ IN PCH_SERIAL_IO_CONTROLLER Number
+ );
+
+/**
+ Checks if Device with given PciDeviceId is one of SerialIo controllers
+ If yes, its number is returned through Number parameter, otherwise Number is not updated
+
+ @param[in] PciDevId Device ID
+ @param[out] Number Number of SerialIo controller
+
+ @retval TRUE Yes it is a SerialIo controller
+ @retval FALSE No it isn't a SerialIo controller
+**/
+BOOLEAN
+IsSerialIoPciDevId (
+ IN UINT16 PciDevId,
+ OUT PCH_SERIAL_IO_CONTROLLER *Number
+ );
+
+/**
+ Checks if Device with given AcpiHID string is one of SerialIo controllers
+ If yes, its number is returned through Number parameter, otherwise Number is not updated
+
+ @param[in] AcpiHid String
+ @param[out] Number Number of SerialIo controller
+
+ @retval TRUE yes it is a SerialIo controller
+ @retval FALSE no it isn't a SerialIo controller
+**/
+BOOLEAN
+IsSerialIoAcpiHid (
+ IN CHAR8 *AcpiHid,
+ OUT PCH_SERIAL_IO_CONTROLLER *Number
+ );
+
+/**
+ Configures Serial IO Controller
+
+ @param[in] Controller
+ @param[in] DeviceMode
+
+ @retval None
+**/
+VOID
+ConfigureSerialIoController (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode
+ );
+
+/**
+ Initializes GPIO pins used by SerialIo I2C devices
+
+ @param[in] Controller
+ @param[in] DeviceMode
+ @param[in] I2cVoltage
+
+ @retval None
+**/
+VOID
+SerialIoI2cGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN UINT32 I2cVoltage
+ );
+
+/**
+ Initializes GPIO pins used by SerialIo SPI devices
+
+ @param[in] Controller
+ @param[in] DeviceMode
+ @param[in] SpiCsPolarity
+
+ @retval None
+**/
+VOID
+SerialIoSpiGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN UINT32 SpiCsPolarity
+ );
+
+/**
+ Initializes GPIO pins used by SerialIo devices
+
+ @param[in] Controller
+ @param[in] DeviceMode
+ @param[in] HardwareFlowControl
+
+ @retval None
+**/
+VOID
+SerialIoUartGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN BOOLEAN HardwareFlowControl
+ );
+
+/**
+ Finds PCI Device Number of SerialIo devices.
+ SerialIo devices' BDF is configurable
+
+ @param[in] SerialIoNumber 0=I2C0, ..., 11=UART2
+
+ @retval SerialIo device number
+**/
+UINT8
+GetSerialIoDeviceNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ );
+
+/**
+ Finds PCI Function Number of SerialIo devices.
+ SerialIo devices' BDF is configurable
+
+ @param[in] SerialIoNumber 0=I2C0, ..., 11=UART2
+
+ @retval SerialIo funciton number
+**/
+UINT8
+GetSerialIoFunctionNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ );
+
+/**
+ Finds BAR values of SerialIo devices.
+ SerialIo devices can be configured to not appear on PCI so traditional method of reading BAR might not work.
+
+ @param[in] SerialIoDevice 0=I2C0, ..., 11=UART2
+ @param[in] BarNumber 0=BAR0, 1=BAR1
+
+ @retval SerialIo Bar value
+**/
+UINTN
+FindSerialIoBar (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice,
+ IN UINT8 BarNumber
+ );
+
+
+#endif // _PEI_DXE_SMM_PCH_SERIAL_IO_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoUartLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoUartLib.h
new file mode 100644
index 0000000000..66c5945a7b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSerialIoUartLib.h
@@ -0,0 +1,98 @@
+/** @file
+ Header file for PCH Serial IO UART Lib implementation.
+
+Copyright (c) 2017, 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 that 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 _PCH_SERIAL_IO_UART_LIB_H_
+#define _PCH_SERIAL_IO_UART_LIB_H_
+
+/**
+ Initialize selected SerialIo UART.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+ @param[in] FifoEnable When TRUE, enables 64-byte FIFOs.
+ @param[in] BaudRate Baud rate.
+ @param[in] LineControl Data length, parity, stop bits.
+ @param[in] HardwareFlowControl Automated hardware flow control. If TRUE, hardware automatically checks CTS when sending data, and sets RTS when receiving data.
+**/
+VOID
+EFIAPI
+PchSerialIoUartInit (
+ IN UINT8 UartNumber,
+ IN BOOLEAN FifoEnable,
+ IN UINT32 BaudRate,
+ IN UINT8 LineControl,
+ IN BOOLEAN HardwareFlowControl
+ );
+
+
+/**
+ Write data to serial device.
+
+ If the buffer is NULL, then return 0;
+ if NumberOfBytes is zero, then return 0.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+ @param[in] Buffer Point of data buffer which need to be writed.
+ @param[in] NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval Actual number of bytes writed to serial device.
+**/
+UINTN
+EFIAPI
+PchSerialIoUartOut (
+ IN UINT8 UartNumber,
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+);
+
+/*
+ Read data from serial device and save the datas in buffer.
+
+ If the buffer is NULL, then return 0;
+ if NumberOfBytes is zero, then return 0.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+ @param[out] Buffer Point of data buffer which need to be writed.
+ @param[in] NumberOfBytes Number of output bytes which are cached in Buffer.
+ @param[in] WaitUntilBufferFull When TRUE, function waits until whole buffer is filled. When FALSE, function returns as soon as no new characters are available.
+
+ @retval Actual number of bytes raed from serial device.
+
+**/
+UINTN
+EFIAPI
+PchSerialIoUartIn (
+ IN UINT8 UartNumber,
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes,
+ IN BOOLEAN WaitUntilBufferFull
+);
+
+/**
+ Polls a serial device to see if there is any data waiting to be read.
+ If there is data waiting to be read from the serial device, then TRUE is returned.
+ If there is no data waiting to be read from the serial device, then FALSE is returned.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+
+ @retval TRUE Data is waiting to be read from the serial device.
+ @retval FALSE There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+PchSerialIoUartPoll (
+ IN UINT8 UartNumber
+ );
+
+
+#endif // _PEI_DXE_SMM_PCH_SERIAL_IO_UART_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSmmControlLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSmmControlLib.h
new file mode 100644
index 0000000000..cdeeae5e6d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchSmmControlLib.h
@@ -0,0 +1,28 @@
+/** @file
+ Header file for SMM Control PEI Library.
+
+Copyright (c) 2017, 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 that 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 _PCH_SMM_CONTROL_LIB_H_
+#define _PCH_SMM_CONTROL_LIB_H_
+
+/**
+ This function install PEI SMM Control PPI
+
+ @retval EFI_STATUS Results of the installation of the SMM Control PPI
+**/
+EFI_STATUS
+EFIAPI
+PchSmmControlInit (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchWdtCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchWdtCommonLib.h
new file mode 100644
index 0000000000..f89e42a546
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/PchWdtCommonLib.h
@@ -0,0 +1,113 @@
+/** @file
+ Library that contains common parts of WdtPei and WdtDxe. Not a standalone module.
+
+Copyright (c) 2017, 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 that 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 _PCH_WDT_COMMON_LIB_H_
+#define _PCH_WDT_COMMON_LIB_H_
+
+extern UINT8 mAllowExpectedReset;
+
+/**
+ Reads LPC bridge to get Watchdog Timer address
+
+
+ @retval UINT32 Watchdog's address
+**/
+UINT32
+WdtGetAddress (
+ VOID
+ );
+
+/**
+ Reloads WDT with new timeout value and starts it. Also sets Unexpected Reset bit, which
+ causes the next reset to be treated as watchdog expiration - unless AllowKnownReset()
+ function was called too.
+
+ @param[in] TimeoutValue Time in seconds before WDT times out. Supported range = 1 - 1024.
+
+ @retval EFI_SUCCESS if everything's OK
+ @retval EFI_INVALID_PARAMETER if TimeoutValue parameter is wrong
+**/
+EFI_STATUS
+EFIAPI
+WdtReloadAndStart (
+ IN UINT32 TimeoutValue
+ );
+
+/**
+ Disables WDT timer.
+
+
+**/
+VOID
+EFIAPI
+WdtDisable (
+ VOID
+ );
+
+/**
+ Returns WDT failure status.
+
+
+ @retval V_PCH_OC_WDT_CTL_STATUS_FAILURE If there was WDT expiration or unexpected reset
+ @retval V_PCH_OC_WDT_CTL_STATUS_OK Otherwise
+**/
+UINT8
+EFIAPI
+WdtCheckStatus (
+ VOID
+ );
+
+/**
+ Normally, each reboot performed while watchdog runs is considered a failure.
+ This function allows platform to perform expected reboots with WDT running,
+ without being interpreted as failures.
+ In DXE phase, it is enough to call this function any time before reset.
+ In PEI phase, between calling this function and performing reset, ReloadAndStart()
+ must not be called.
+
+
+**/
+VOID
+EFIAPI
+WdtAllowKnownReset (
+ VOID
+ );
+
+/**
+ Returns information if WDT coverage for the duration of BIOS execution
+ was requested by an OS application
+
+
+ @retval TRUE if WDT was requested
+ @retval FALSE if WDT was not requested
+**/
+UINT8
+EFIAPI
+IsWdtRequired (
+ VOID
+ );
+
+/**
+ Returns WDT enabled/disabled status.
+
+
+ @retval TRUE if WDT is enabled
+ @retval FALSE if WDT is disabled
+**/
+UINT8
+EFIAPI
+IsWdtEnabled (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SecPchLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SecPchLib.h
new file mode 100644
index 0000000000..ba9586a7a2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SecPchLib.h
@@ -0,0 +1,27 @@
+/** @file
+ Header file for SEC PCH Lib.
+ All function in this library is available for SEC
+
+Copyright (c) 2017, 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 that 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 _SEC_PCH_LIB_H_
+#define _SEC_PCH_LIB_H_
+
+/**
+ This function do the PCH cycle decoding initialization.
+**/
+VOID
+EFIAPI
+EarlyCycleDecoding (
+ VOID
+ );
+
+#endif // _SEC_PCH_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SpiFlashCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SpiFlashCommonLib.h
new file mode 100644
index 0000000000..12dfaeb440
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/SpiFlashCommonLib.h
@@ -0,0 +1,104 @@
+/** @file
+ The header file includes the common header files, defines
+ internal structure and functions used by SpiFlashCommonLib.
+
+Copyright (c) 2017, 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 that 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 __SPI_FLASH_COMMON_LIB_H__
+#define __SPI_FLASH_COMMON_LIB_H__
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define SECTOR_SIZE_4KB 0x1000 // Common 4kBytes sector size
+/**
+ Enable block protection on the Serial Flash device.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashLock (
+ VOID
+ );
+
+/**
+ Read NumBytes bytes of data from the address specified by
+ PAddress into Buffer.
+
+ @param[in] Address The starting physical address of the read.
+ @param[in,out] NumBytes On input, the number of bytes to read. On output, the number
+ of bytes actually read.
+ @param[out] Buffer The destination data buffer for the read.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashRead (
+ IN UINTN Address,
+ IN OUT UINT32 *NumBytes,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Write NumBytes bytes of data from Buffer to the address specified by
+ PAddresss.
+
+ @param[in] Address The starting physical address of the write.
+ @param[in,out] NumBytes On input, the number of bytes to write. On output,
+ the actual number of bytes written.
+ @param[in] Buffer The source data buffer for the write.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashWrite (
+ IN UINTN Address,
+ IN OUT UINT32 *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Erase the block starting at Address.
+
+ @param[in] Address The starting physical address of the block to be erased.
+ This library assume that caller garantee that the PAddress
+ is at the starting address of this block.
+ @param[in] NumBytes On input, the number of bytes of the logical block to be erased.
+ On output, the actual number of bytes erased.
+
+ @retval EFI_SUCCESS. Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashBlockErase (
+ IN UINTN Address,
+ IN UINTN *NumBytes
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/TraceHubInitLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/TraceHubInitLib.h
new file mode 100644
index 0000000000..23cb544d67
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Library/TraceHubInitLib.h
@@ -0,0 +1,49 @@
+/** @file
+ Header file for TraceHub Init Lib.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, 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 that 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 _TRACE_HUB_INIT_LIB_H_
+#define _TRACE_HUB_INIT_LIB_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <PchAccess.h>
+
+///
+/// The PCH_TRACE_HUB_ENABLE_MODE describes the desired TraceHub mode of operation
+///
+typedef enum {
+ TraceHubModeDisabled = 0, ///< Pch TraceHub Disabled
+ TraceHubModeHostDebugger = 2, ///< Pch TraceHub External Debugger Present
+ TraceHubModeMax
+} TRACE_HUB_ENABLE_MODE;
+
+/**
+ This function performs basic initialization for TraceHub
+ This routine will consume address range 0xFE0C0000 - 0xFE3FFFFF for BARs usage.
+ Although controller allows access to a 64bit address resource, PEI phase is a 32bit env,
+ addresses greater than 4G is not allowed by CPU address space.
+ So, the addresses must be limited to below 4G and UBARs should be set to 0.
+ If this routine is called by platform code, it is expected EnableMode is passed in as PchTraceHubModeDisabled,
+ relying on the Intel TH debugger to enable it through the "cratchpad0 bit [24]".
+ By this practice, it gives the validation team the capability to use single debug BIOS
+ to validate the early trace functionality and code path that enable/disable Intel TH using BIOS policy.
+
+ @param[in] EnableMode Trace Hub Enable Mode
+**/
+VOID
+TraceHubInitialize (
+ IN UINT8 EnableMode
+ );
+
+#endif // _TRACE_HUB_INIT_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchAccess.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchAccess.h
new file mode 100644
index 0000000000..2c457e3a1e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchAccess.h
@@ -0,0 +1,71 @@
+/** @file
+ Macros that simplify accessing PCH devices's PCI registers.
+
+Copyright (c) 2017, 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 that 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 _PCH_ACCESS_H_
+#define _PCH_ACCESS_H_
+
+#include "PchLimits.h"
+#include "PchReservedResources.h"
+
+#ifndef STALL_ONE_MICRO_SECOND
+#define STALL_ONE_MICRO_SECOND 1
+#endif
+#ifndef STALL_ONE_SECOND
+#define STALL_ONE_SECOND 1000000
+#endif
+
+
+///
+/// The default PCH PCI bus number
+///
+#define DEFAULT_PCI_BUS_NUMBER_PCH 0
+
+//
+// Default Vendor ID and Subsystem ID
+//
+#define V_PCH_INTEL_VENDOR_ID 0x8086 ///< Default Intel PCH Vendor ID
+#define V_PCH_DEFAULT_SID 0x7270 ///< Default Intel PCH Subsystem ID
+#define V_PCH_DEFAULT_SVID_SID (V_INTEL_VENDOR_ID + (V_PCH_DEFAULT_SID << 16)) ///< Default INTEL PCH Vendor ID and Subsystem ID
+
+//
+// Include device register definitions
+//
+#include "PcieRegs.h"
+#include "Register/PchRegsPcr.h"
+#include "Register/PchRegsP2sb.h"
+#include "Register/PchRegsHda.h"
+#include "Register/PchRegsHsio.h"
+#include "Register/PchRegsLan.h"
+#include "Register/PchRegsLpc.h"
+#include "Register/PchRegsPmc.h"
+#include "Register/PchRegsPcie.h"
+#include "Register/PchRegsSata.h"
+#include "Register/PchRegsSmbus.h"
+#include "Register/PchRegsSpi.h"
+#include "Register/PchRegsThermal.h"
+#include "Register/PchRegsUsb.h"
+#include "Register/PchRegsGpio.h"
+#include "Register/PchRegsSerialIo.h"
+#include "Register/PchRegsCam.h"
+#include "Register/PchRegsTraceHub.h"
+#include "Register/PchRegsScs.h"
+#include "Register/PchRegsIsh.h"
+#include "Register/PchRegsDmi.h"
+#include "Register/PchRegsItss.h"
+#include "Register/PchRegsPsth.h"
+#include "Register/PchRegsPsf.h"
+#include "Register/PchRegsFia.h"
+#include "Register/PchRegsDci.h"
+
+#endif
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchLimits.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchLimits.h
new file mode 100644
index 0000000000..905a4778ce
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchLimits.h
@@ -0,0 +1,101 @@
+/** @file
+ Build time limits of PCH resources.
+
+Copyright (c) 2017, 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 that 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 _PCH_LIMITS_H_
+#define _PCH_LIMITS_H_
+
+//
+// PCIe limits
+//
+#define PCH_MAX_PCIE_ROOT_PORTS KBL_PCH_H_PCIE_MAX_ROOT_PORTS
+#define SKL_PCH_H_PCIE_MAX_ROOT_PORTS 20
+#define KBL_PCH_H_PCIE_MAX_ROOT_PORTS 24
+#define PCH_LP_PCIE_MAX_ROOT_PORTS 12
+
+#define PCH_MAX_PCIE_CONTROLLERS KBL_PCH_H_PCIE_MAX_CONTROLLERS
+#define PCH_PCIE_CONTROLLER_PORTS 4u
+#define SKL_PCH_H_PCIE_MAX_CONTROLLERS (SKL_PCH_H_PCIE_MAX_ROOT_PORTS / PCH_PCIE_CONTROLLER_PORTS)
+#define KBL_PCH_H_PCIE_MAX_CONTROLLERS (KBL_PCH_H_PCIE_MAX_ROOT_PORTS / PCH_PCIE_CONTROLLER_PORTS)
+#define PCH_LP_PCIE_MAX_CONTROLLERS (PCH_LP_PCIE_MAX_ROOT_PORTS / PCH_PCIE_CONTROLLER_PORTS)
+
+//
+// PCIe clocks limits
+//
+#define PCH_LP_PCIE_MAX_CLK_REQ 6
+#define PCH_H_PCIE_MAX_CLK_REQ 16
+
+//
+// RST PCIe Storage Cycle Router limits
+//
+#define PCH_MAX_RST_PCIE_STORAGE_CR 3
+
+//
+// SATA limits
+//
+#define PCH_MAX_SATA_PORTS PCH_H_AHCI_MAX_PORTS
+#define PCH_H_AHCI_MAX_PORTS 8 ///< Max number of sata ports in SKL PCH H
+#define PCH_LP_AHCI_MAX_PORTS 3 ///< Max number of sata ports in SKL PCH LP
+#define PCH_SATA_MAX_DEVICES_PER_PORT 1 ///< Max support device numner per port, Port Multiplier is not support.
+
+//
+// USB limits
+//
+#define PCH_MAX_USB2_PORTS PCH_H_XHCI_MAX_USB2_PORTS
+
+#define PCH_H_XHCI_MAX_USB2_PHYSICAL_PORTS 14 ///< Max Physical Connector XHCI, not counting virtual ports like USB-R.
+#define PCH_LP_XHCI_MAX_USB2_PHYSICAL_PORTS 10 ///< Max Physical Connector XHCI, not counting virtual ports like USB-R.
+
+#define PCH_H_XHCI_MAX_USB2_PORTS 16 ///< 14 High Speed lanes + Including two ports reserved for USBr
+#define PCH_LP_XHCI_MAX_USB2_PORTS 12 ///< 10 High Speed lanes + Including two ports reserved for USBr
+
+#define PCH_MAX_USB3_PORTS PCH_H_XHCI_MAX_USB3_PORTS
+
+#define PCH_H_XHCI_MAX_USB3_PORTS 10 ///< 10 Super Speed lanes
+#define PCH_LP_XHCI_MAX_USB3_PORTS 6 ///< 6 Super Speed lanes
+
+#define PCH_XHCI_MAX_SSIC_PORT_COUNT 2 ///< 2 SSIC ports in SKL PCH-LP and SKL PCH-H
+
+//
+// SerialIo limits
+//
+#define PCH_SERIALIO_MAX_CONTROLLERS 11 ///< Number of SerialIo controllers, this includes I2C, SPI and UART
+#define PCH_SERIALIO_MAX_I2C_CONTROLLERS 6 ///< Number of SerialIo I2C controllers
+#define PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS 6 ///< Number of SerialIo I2C controllers for PCH-LP
+#define PCH_H_SERIALIO_MAX_I2C_CONTROLLERS 4 ///< Number of SerialIo I2C controllers for PCH-H
+#define PCH_SERIALIO_MAX_SPI_CONTROLLERS 2 ///< Number of SerialIo SPI controllers
+#define PCH_SERIALIO_MAX_UART_CONTROLLERS 3 ///< Number of SerialIo UART controllers
+
+//
+// ISH limits
+//
+#define PCH_ISH_MAX_GP_PINS 8
+#define PCH_ISH_MAX_UART_CONTROLLERS 2
+#define PCH_ISH_MAX_I2C_CONTROLLERS 3
+#define PCH_ISH_MAX_SPI_CONTROLLERS 1
+
+//
+// SCS limits
+//
+#define PCH_SCS_MAX_CONTROLLERS 3 ///< Number of Storage and Communication Subsystem controllers, this includes eMMC, SDIO, SDCARD
+
+//
+// Flash Protection Range Register
+//
+#define PCH_FLASH_PROTECTED_RANGES 5
+
+//
+// Number of eSPI slaves
+//
+#define PCH_ESPI_MAX_SLAVE_ID 2
+#endif // _PCH_LIMITS_H_
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPcieStorageDetectHob.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPcieStorageDetectHob.h
new file mode 100644
index 0000000000..664f66f296
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPcieStorageDetectHob.h
@@ -0,0 +1,54 @@
+/** @file
+
+ Definitions required to create PcieStorageInfoHob
+
+Copyright (c) 2017, 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 that 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 _PCH_PCIE_STORAGE_DETECT_HOB_
+#define _PCH_PCIE_STORAGE_DETECT_HOB_
+
+#include "PchLimits.h"
+
+#define PCIE_STORAGE_INFO_HOB_REVISION 1
+
+extern EFI_GUID gPchPcieStorageDetectHobGuid;
+
+typedef enum {
+ RstLinkWidthX1 = 1,
+ RstLinkWidthX2 = 2,
+ RstLinkWidthX4 = 4
+} RST_LINK_WIDTH;
+
+//
+// Stores information about connected PCIe storage devices used later by BIOS setup and RST remapping
+//
+#pragma pack(1)
+typedef struct {
+ UINT8 Revision;
+
+ //
+ // Stores the number of root ports occupied by a connected storage device, values from RST_LINK_WIDTH are supported
+ //
+ UINT8 PcieStorageLinkWidth[PCH_MAX_PCIE_ROOT_PORTS];
+
+ //
+ // Programming interface value for a given device, 0x02 - NVMe or RAID, 0x1 - AHCI storage, 0x0 - no device connected
+ //
+ UINT8 PcieStorageProgrammingInterface[PCH_MAX_PCIE_ROOT_PORTS];
+
+ //
+ // Stores information about cycle router number under a given PCIe controller
+ //
+ UINT8 RstCycleRouterMap[PCH_MAX_PCIE_CONTROLLERS];
+} PCIE_STORAGE_INFO_HOB;
+#pragma pack()
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPolicyCommon.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPolicyCommon.h
new file mode 100644
index 0000000000..67b255fe97
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPolicyCommon.h
@@ -0,0 +1,54 @@
+/** @file
+ PCH configuration based on PCH policy
+
+Copyright (c) 2017, 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 that 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 _PCH_POLICY_COMMON_H_
+#define _PCH_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include "PchLimits.h"
+#include "ConfigBlock/PchGeneralConfig.h"
+#include "ConfigBlock/PcieRpConfig.h"
+#include "ConfigBlock/SataConfig.h"
+#include "ConfigBlock/IoApicConfig.h"
+#include "ConfigBlock/Cio2Config.h"
+#include "ConfigBlock/DmiConfig.h"
+#include "ConfigBlock/FlashProtectionConfig.h"
+#include "ConfigBlock/HdAudioConfig.h"
+#include "ConfigBlock/InterruptConfig.h"
+#include "ConfigBlock/IshConfig.h"
+#include "ConfigBlock/LanConfig.h"
+#include "ConfigBlock/LockDownConfig.h"
+#include "ConfigBlock/P2sbConfig.h"
+#include "ConfigBlock/PmConfig.h"
+#include "ConfigBlock/Port61Config.h"
+#include "ConfigBlock/ScsConfig.h"
+#include "ConfigBlock/SerialIoConfig.h"
+#include "ConfigBlock/SerialIrqConfig.h"
+#include "ConfigBlock/SpiConfig.h"
+#include "ConfigBlock/ThermalConfig.h"
+#include "ConfigBlock/UsbConfig.h"
+#include "ConfigBlock/EspiConfig.h"
+
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE 1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+#ifndef PLATFORM_POR
+#define PLATFORM_POR 0
+#endif
+
+
+#endif // _PCH_POLICY_COMMON_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
new file mode 100644
index 0000000000..8bd4c9b960
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
@@ -0,0 +1,65 @@
+/** @file
+ PCH configuration based on PCH policy
+
+Copyright (c) 2017, 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 that 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 _PCH_PREMEM_POLICY_COMMON_H_
+#define _PCH_PREMEM_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include "PchLimits.h"
+#include "ConfigBlock/PchGeneralConfig.h"
+#include "ConfigBlock/DciConfig.h"
+#include "ConfigBlock/WatchDogConfig.h"
+#include "ConfigBlock/TraceHubConfig.h"
+#include "ConfigBlock/HpetConfig.h"
+#include "ConfigBlock/SmbusConfig.h"
+#include "ConfigBlock/LpcConfig.h"
+#include "ConfigBlock/HsioPcieConfig.h"
+#include "ConfigBlock/HsioSataConfig.h"
+#include "ConfigBlock/HsioConfig.h"
+
+#pragma pack (push,1)
+
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE 1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+#ifndef PLATFORM_POR
+#define PLATFORM_POR 0
+#endif
+
+/**
+ PCH Policy revision number
+ Any backwards compatible changes to this structure will result in an update in the revision number
+**/
+#define PCH_PREMEM_POLICY_REVISION 1
+
+/**
+ PCH Policy PPI\n
+ All PCH config block change history will be listed here\n\n
+
+ - <b>Revision 1</b>:
+ - Initial version.\n
+**/
+typedef struct _PCH_PREMEM_POLICY {
+ CONFIG_BLOCK_TABLE_HEADER TableHeader;
+/*
+ Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+} PCH_PREMEM_POLICY;
+
+#pragma pack (pop)
+
+#endif // _PCH_PREMEM_POLICY_COMMON_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchReservedResources.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchReservedResources.h
new file mode 100644
index 0000000000..e5de75c0e3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchReservedResources.h
@@ -0,0 +1,62 @@
+/** @file
+ PCH preserved MMIO resource definitions.
+
+Copyright (c) 2017, 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 that 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 _PCH_PRESERVED_RESOURCES_H_
+#define _PCH_PRESERVED_RESOURCES_H_
+
+/**
+ PCH preserved MMIO range, 24 MB, from 0xFD000000 to 0xFE7FFFFF
+
+ Detailed recommended static allocation
+ +-------------------------------------------------------------------------+
+ | Size | Start | End | Usage |
+ | 16 MB | 0xFD000000 | 0xFDFFFFFF | SBREG |
+ | 64 KB | 0xFE000000 | 0xFE00FFFF | PMC MBAR |
+ | 4 KB | 0xFE010000 | 0xFE010FFF | SPI BAR0 |
+ | 88 KB | 0xFE020000 | 0xFE035FFF | SerialIo BAR in ACPI mode |
+ | 24 KB | 0xFE036000 | 0xFE03BFFF | Unused |
+ | 4 KB | 0xFE03C000 | 0xFE03CFFF | Thermal Device in ACPI mode |
+ | 524 KB | 0xFE03D000 | 0xFE0BFFFF | Unused |
+ | 256 KB | 0xFE0C0000 | 0xFE0FFFFF | TraceHub FW BAR |
+ | 1 MB | 0xFE100000 | 0xFE1FFFFF | TraceHub MTB BAR |
+ | 2 MB | 0xFE200000 | 0xFE3FFFFF | TraceHub SW BAR |
+ | 64 KB | 0xFE400000 | 0xFE40FFFF | CIO2 MMIO BAR in ACPI mode |
+ | 2 MB - 64KB | 0xFE410000 | 0xFE5FFFFF | Unused |
+ | 2 MB | 0xFE600000 | 0xFE7FFFFF | Temp address |
+ +-------------------------------------------------------------------------+
+**/
+#define PCH_PRESERVED_BASE_ADDRESS 0xFD000000 ///< Pch preserved MMIO base address
+#define PCH_PRESERVED_MMIO_SIZE 0x01800000 ///< 24MB
+#define PCH_PCR_BASE_ADDRESS 0xFD000000 ///< SBREG MMIO base address
+#define PCH_PCR_MMIO_SIZE 0x01000000 ///< 16MB
+#define PCH_PWRM_BASE_ADDRESS 0xFE000000 ///< PMC MBAR MMIO base address
+#define PCH_PWRM_MMIO_SIZE 0x00010000 ///< 64KB
+#define PCH_SPI_BASE_ADDRESS 0xFE010000 ///< SPI BAR0 MMIO base address
+#define PCH_SPI_MMIO_SIZE 0x00001000 ///< 4KB
+#define PCH_SERIAL_IO_BASE_ADDRESS 0xFE020000 ///< SerialIo MMIO base address
+#define PCH_SERIAL_IO_MMIO_SIZE 0x00016000 ///< 88KB
+#define PCH_THERMAL_BASE_ADDRESS 0xFE03C000 ///< Thermal Device in ACPI mode
+#define PCH_THERMAL_MMIO_SIZE 0x00001000 ///< 4KB
+#define PCH_TRACE_HUB_FW_BASE_ADDRESS 0xFE0C0000 ///< TraceHub FW MMIO base address
+#define PCH_TRACE_HUB_FW_MMIO_SIZE 0x00040000 ///< 256KB
+#define PCH_TRACE_HUB_MTB_BASE_ADDRESS 0xFE100000 ///< TraceHub MTB MMIO base address
+#define PCH_TRACE_HUB_MTB_MMIO_SIZE 0x00100000 ///< 1MB
+#define PCH_TRACE_HUB_SW_BASE_ADDRESS 0xFE200000 ///< TraceHub SW MMIO base address
+#define PCH_TRACE_HUB_SW_MMIO_SIZE 0x00200000 ///< 2MB
+#define PCH_CIO2_BASE_ADDRESS 0xFE400000 ///< CIO2 MMIO BAR in ACPI mode
+#define PCH_CIO2_MMIO_SIZE 0x00010000 ///< 64KB
+#define PCH_TEMP_BASE_ADDRESS 0xFE600000 ///< preserved temp address for misc usage
+#define PCH_TEMP_MMIO_SIZE 0x00200000 ///< 2MB
+
+#endif // _PCH_PRESERVED_RESOURCES_H_
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
new file mode 100644
index 0000000000..c19677cccd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
@@ -0,0 +1,28 @@
+/** @file
+ PCH Reset Platform Specific definitions.
+
+Copyright (c) 2017, 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 that 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 _PCH_RESET_PLATFORM_SPECIFIC_H_
+#define _PCH_RESET_PLATFORM_SPECIFIC_H_
+
+#define PCH_PLATFORM_SPECIFIC_RESET_STRING L"PCH_RESET"
+#define PCH_RESET_DATA_STRING_MAX_LENGTH (sizeof (PCH_PLATFORM_SPECIFIC_RESET_STRING) / sizeof (UINT16))
+
+extern EFI_GUID gPchGlobalResetGuid;
+
+typedef struct _RESET_DATA {
+ CHAR16 Description[PCH_RESET_DATA_STRING_MAX_LENGTH];
+ EFI_GUID Guid;
+} PCH_RESET_DATA;
+
+#endif // _PCH_RESET_PLATFORM_SPECIFIC_H_
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/PchReset.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/PchReset.h
new file mode 100644
index 0000000000..951dac00dc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/PchReset.h
@@ -0,0 +1,98 @@
+/** @file
+ PCH Reset PPI
+
+Copyright (c) 2017, 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 that 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 _PCH_RESET_PPI_H_
+#define _PCH_RESET_PPI_H_
+
+//
+// Extern the GUID for PPI users.
+//
+extern EFI_GUID gPchResetPpiGuid;
+extern EFI_GUID gPchResetCallbackPpiGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_RESET_PPI PCH_RESET_PPI;
+typedef struct _PCH_RESET_CALLBACK_PPI PCH_RESET_CALLBACK_PPI;
+
+//
+// Related Definitions
+//
+//
+// PCH Reset Types
+//
+typedef enum {
+ PchColdReset = 0,
+ PchWarmReset = 1,
+ PchShutdownReset = 2,
+ PchGlobalReset = 4,
+ PchResetTypeMax
+} PCH_RESET_TYPE;
+
+//
+// Member functions
+//
+/**
+ Execute Pch Reset from the host controller.
+
+ @param[in] This Pointer to the PCH_RESET_PPI instance.
+ @param[in] PchResetType Pch Reset Types which includes ColdReset, WarmReset,
+ ShutdownReset, GlobalReset
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER If ResetType is invalid.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_RESET_PPI_API) (
+ IN PCH_RESET_PPI *This,
+ IN PCH_RESET_TYPE PchResetType
+ );
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] PchResetType Pch Reset Types which includes PowerCycle, Globalreset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback ppi. Or, none of
+ callback ppi is installed.
+ @retval Others Do not do any reset from PCH
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_RESET_CALLBACK) (
+ IN PCH_RESET_TYPE PchResetType
+ );
+
+/**
+ Interface structure to execute Pch Reset from the host controller.
+**/
+struct _PCH_RESET_PPI {
+ PCH_RESET_PPI_API Reset;
+};
+
+/**
+ This ppi is used to execute PCH Reset from the host controller.
+ The PCH Reset protocol and PCH Reset PPI implement the Intel (R) PCH Reset Interface
+ for DXE and PEI environments, respectively. If other drivers need to run their
+ callback function right before issuing the reset, they can install PCH Reset
+ Callback Protocol/PPI before PCH Reset DXE/PEI driver to achieve that.
+**/
+struct _PCH_RESET_CALLBACK_PPI {
+ PCH_RESET_CALLBACK ResetCallback;
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Spi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Spi.h
new file mode 100644
index 0000000000..cd98f3601c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Spi.h
@@ -0,0 +1,32 @@
+/** @file
+ This file defines the PCH SPI PPI which implements the
+ Intel(R) PCH SPI Host Controller Compatibility Interface.
+
+Copyright (c) 2017, 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 that 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 _PCH_SPI_PPI_H_
+#define _PCH_SPI_PPI_H_
+
+#include <Protocol/Spi.h>
+
+//
+// Extern the GUID for PPI users.
+//
+extern EFI_GUID gPchSpiPpiGuid;
+
+/**
+ Reuse the PCH_SPI_PROTOCOL definitions
+ This is possible becaues the PPI implementation does not rely on a PeiService pointer,
+ as it uses EDKII Glue Lib to do IO accesses
+**/
+typedef PCH_SPI_PROTOCOL PCH_SPI_PPI;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Wdt.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Wdt.h
new file mode 100644
index 0000000000..b0bb6bccbd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Ppi/Wdt.h
@@ -0,0 +1,33 @@
+/** @file
+ Watchdog Timer PPI
+
+Copyright (c) 2017, 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 that 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 _PEI_WDT_H_
+#define _PEI_WDT_H_
+
+#include <Protocol/Wdt.h>
+//
+// MRC takes a lot of time to execute in debug mode
+//
+#define WDT_TIMEOUT_BETWEEN_PEI_DXE 60
+
+//
+// Extern the GUID for PPI users.
+//
+extern EFI_GUID gWdtPpiGuid;
+
+///
+/// Reuse WDT_PROTOCOL definition
+///
+typedef WDT_PROTOCOL WDT_PPI;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
new file mode 100644
index 0000000000..eb08a89f00
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
@@ -0,0 +1,141 @@
+/** @file
+ APIs of PCH ACPI SMI Dispatch Protocol.
+
+Copyright (c) 2017, 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 that 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 _PCH_ACPI_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_ACPI_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchAcpiSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_ACPI_SMI_DISPATCH_PROTOCOL PCH_ACPI_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH ACPI SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for PCH ACPI SMI events.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_REGISTER) (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent ACPI SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH ACPI SMIs Dispatch Protocol
+ The PCH ACPI SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH ACPI related SMIs.
+ It contains SMI types of Pme, RtcAlarm, PmeB0, and Time overflow.
+**/
+struct _PCH_ACPI_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH ACPI SMI DISPATCH PROTOCOL.
+ **/
+ PCH_ACPI_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ Pme
+ The event is triggered by hardware when the PME# signal goes active.
+ Additionally, the event is only triggered when SCI_EN is not set.
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER PmeRegister;
+ /**
+ PmeB0
+ The event is triggered PCH when any internal device with PCI Power Management
+ capabilities on bus 0 asserts the equivalent of the PME# signal.
+ Additionally, the event is only triggered when SCI_EN is not set.
+ The following are internal devices which can set this bit:
+ Intel HD Audio, Intel Management Engine "maskable" wake events, Integrated LAN,
+ SATA, xHCI, Intel SST
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER PmeB0Register;
+ /**
+ RtcAlarm
+ The event is triggered by hardware when the RTC generates an alarm
+ (assertion of the IRQ8# signal).
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER RtcAlarmRegister;
+ /**
+ TmrOverflow
+ The event is triggered any time bit 22 of the 24-bit timer goes high
+ (bits are numbered from 0 to 23).
+ This will occur every 2.3435 seconds. When the TMROF_EN bit (ABASE + 02h, bit 0) is set,
+ then the setting of the TMROF_STS bit will additionally generate an SMI#
+ Additionally, the event is only triggered when SCI_EN is not set.
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER TmrOverflowRegister;
+};
+
+/**
+ PCH ACPI SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_ACPI_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEmmcTuning.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEmmcTuning.h
new file mode 100644
index 0000000000..ad1db3833a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEmmcTuning.h
@@ -0,0 +1,74 @@
+/** @file
+ PCH eMMC HS400 Tuning Protocol
+
+Copyright (c) 2017, 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 that 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 _PCH_EMMC_TUNING_PROTOCOL_H_
+#define _PCH_EMMC_TUNING_PROTOCOL_H_
+
+#define PCH_EMMC_TUNING_PROTOCOL_REVISION 2
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchEmmcTuningProtocolGuid;
+
+//
+// Forward declaration for PCH_EMMC_TUNING_PROTOCOL
+//
+typedef struct _PCH_EMMC_TUNING_PROTOCOL PCH_EMMC_TUNING_PROTOCOL;
+
+/**
+ This structure decribes the required Emmc info for HS400 tuning
+**/
+typedef struct {
+ EFI_HANDLE PartitionHandle; ///< eMMC partition handle for block read/write
+ EFI_LBA Lba; ///< Logical Block Address for HS400 Tuning block read/write
+ UINT32 RelativeDevAddress; ///< Device system address, dynamically assigned by the host during initialization.
+ UINT8 HS200BusWidth; ///< The value to be programmed for BUS_WIDTH[183] byte
+} EMMC_INFO;
+
+///
+/// This structure describes the return value after HS400 tuning
+///
+typedef struct {
+ UINT8 Hs400DataValid; ///< Set if Hs400 Tuning Data is valid after tuning
+ UINT8 Hs400RxStrobe1Dll; ///< Rx Strobe Delay Control - Rx Strobe Delay DLL 1 (HS400 Mode)
+ UINT8 Hs400TxDataDll; ///< Tx Data Delay Control 1 - Tx Data Delay (HS400 Mode)
+ UINT8 Hs400DriverStrength; ///< Hs400 Driver Strength
+} EMMC_TUNING_DATA;
+
+///
+/// EMMC HS400 TUNING INTERFACE
+///
+typedef EFI_STATUS (EFIAPI *EMMC_TUNE) (
+ IN PCH_EMMC_TUNING_PROTOCOL *This, ///< This pointer to PCH_EMMC_TUNING_PROTOCOL
+ /**
+ Revision parameter is used to verify the layout of EMMC_INFO and TUNINGDATA.
+ If the revision is not matched, means the revision of EMMC_INFO and TUNINGDATA is not matched.
+ And function will return immediately.
+ **/
+ IN UINT8 Revision,
+ IN EMMC_INFO *EmmcInfo, ///< Pointer to EMMC_INFO
+ OUT EMMC_TUNING_DATA *EmmcTuningData ///< Pointer to EMMC_TUNING_DATA
+);
+
+/**
+ PCH EMMC TUNING PROTOCOL INTERFACE
+ Platform code uses this protocol to configure Emmc Hs400 mode, by passing the EMMC_INFO information.
+ PCH will setting EMMC controller based on EMMC_INFO and return EMMC_TUNING_DATA to platform code.
+ Platform should keep values of EMMC_TUNING_DATA and uses to configure EMMC through policies, to
+ prevent from doing EMMC tuning every boot.
+**/
+struct _PCH_EMMC_TUNING_PROTOCOL {
+ EMMC_TUNE EmmcTune; ///< Emmc Hs400 Tuning Interface
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h
new file mode 100644
index 0000000000..7d7d3a5339
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h
@@ -0,0 +1,151 @@
+/** @file
+ SmmEspiDispatch Protocol
+
+Copyright (c) 2017, 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 that 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 _PCH_ESPI_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_ESPI_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchEspiSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_ESPI_SMI_DISPATCH_PROTOCOL PCH_ESPI_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH eSPI SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+**/
+typedef
+VOID
+(EFIAPI *PCH_ESPI_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Generic function to register different types of eSPI SMI types
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration successful
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+ @retval others Registration failed
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ESPI_SMI_REGISTER) (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to unregister a callback based on handle
+
+ @param[in] This Not used
+ @param[in] DispatchHandle Handle acquired during registration
+
+ @retval EFI_SUCCESS Unregister successful
+ @retval EFI_INVALID_PARAMETER DispatchHandle is null
+ @retval EFI_INVALID_PARAMETER DispatchHandle's forward link has bad pointer
+ @retval EFI_INVALID_PARAMETER DispatchHandle does not exist in database
+ @retval EFI_ACCESS_DENIED Unregistration is done after end of DXE
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ESPI_SMI_UNREGISTER) (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH eSPI SMIs Dispatch Protocol
+ The PCH ESPI SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH eSPI related SMIs.
+ It contains SMI types of BiosWr, EcAssertedVw, and eSPI Master asserted SMIs
+**/
+struct _PCH_ESPI_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Unregister eSPI SMI events
+ **/
+ PCH_ESPI_SMI_UNREGISTER UnRegister;
+ /**
+ Register a BIOS Write Protect event
+ **/
+ PCH_ESPI_SMI_REGISTER BiosWrProtectRegister;
+ /**
+ Register a BIOS Write Report event
+ **/
+ PCH_ESPI_SMI_REGISTER BiosWrReportRegister;
+ /**
+ Register a Peripheral Channel Non Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER PcErrNonFatalRegister;
+ /**
+ Register a Peripheral Channel Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER PcErrFatalRegister;
+ /**
+ Register a Virtual Wire Non Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER VwErrNonFatalRegister;
+ /**
+ Register a Virtual Wire Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER VwErrFatalRegister;
+ /**
+ Register a Flash Channel Non Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER FlashErrNonFatalRegister;
+ /**
+ Register a Flash Channel Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER FlashErrFatalRegister;
+ /**
+ Register a Link Error event
+ **/
+ PCH_ESPI_SMI_REGISTER LnkErrType1Register;
+ /**
+ Register a SMI handler for Espi slaver
+ This routine will also lock down ESPI_SMI_LOCK bit after registration and prevent
+ this handler from unregistration.
+ On platform that supports more than 1 device through another chip select (SPT-H),
+ the SMI handler itself needs to inspect both the eSPI devices' interrupt status registers
+ (implementation specific for each Slave) in order to identify and service the cause.
+ After servicing it, it has to clear the Slaves' internal SMI# status registers
+ **/
+ PCH_ESPI_SMI_REGISTER EspiSlaveSmiRegister;
+};
+
+/**
+ PCH ESPI SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_ESPI_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchGpioUnlockSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchGpioUnlockSmiDispatch.h
new file mode 100644
index 0000000000..392733117b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchGpioUnlockSmiDispatch.h
@@ -0,0 +1,115 @@
+/** @file
+ APIs of PCH GPIO UNLOCK SMI Dispatch Protocol.
+
+Copyright (c) 2017, 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 that 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 _PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchGpioUnlockSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH GPIO UNLOCK SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_GPIO_UNLOCK_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for specific PCH GPIO UNLOCK SMI dispatch event.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_GPIO_UNLOCK_SMI_DISPATCH_REGISTER) (
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent GPIO UNLOCK SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_GPIO_UNLOCK_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH GPIOUNLOCK SMI Dispatch Protocol
+ The PCH GPIO UNLOCK SMI DISPATCH PROTOCOL provides the ability to dispatch function for
+ PCH gpio unlock SMIs.
+**/
+struct _PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH GPIO UNLOCK SMI DISPATCH PROTOCOL.
+ **/
+ PCH_GPIO_UNLOCK_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ GpioUnlock
+ The event is triggered if the GPIO registers lockdown logic is requesting an SMI#.
+ **/
+ PCH_GPIO_UNLOCK_SMI_DISPATCH_REGISTER Register;
+};
+
+/**
+ PCH GPIO UNLOCK SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_GPIO_UNLOCK_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchInfo.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchInfo.h
new file mode 100644
index 0000000000..ff81aebddf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchInfo.h
@@ -0,0 +1,57 @@
+/** @file
+ This file defines the PCH Info Protocol.
+
+Copyright (c) 2017, 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 that 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 _PCH_INFO_H_
+#define _PCH_INFO_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchInfoProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_INFO_PROTOCOL PCH_INFO_PROTOCOL;
+
+/**
+ Protocol revision number
+ Any backwards compatible changes to this protocol will result in an update in the revision number
+ Major changes will require publication of a new protocol
+
+ Revision 1: Original version
+ Revision 2: Add PcieControllerCfg6 for KBL PCH-H
+**/
+#define PCH_INFO_PROTOCOL_REVISION 2
+
+/**
+ This protocol is used to provide the information of PCH controller.
+**/
+struct _PCH_INFO_PROTOCOL {
+ /**
+ This member specifies the revision of the PCH Info protocol. This field is used
+ to indicate backwards compatible changes to the protocol. Platform code that
+ consumes this protocol must read the correct revision value to correctly interpret
+ the content of the protocol fields.
+ **/
+ UINT8 Revision;
+
+ UINT8 PcieControllerCfg1;
+ UINT8 PcieControllerCfg2;
+ UINT8 PcieControllerCfg3;
+ UINT8 PcieControllerCfg4;
+ UINT8 PcieControllerCfg5;
+ UINT8 PcieControllerCfg6;
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
new file mode 100644
index 0000000000..b80597ae9b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
@@ -0,0 +1,137 @@
+/** @file
+ APIs of PCH PCIE SMI Dispatch Protocol.
+
+Copyright (c) 2017, 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 that 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 _PCH_PCIE_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_PCIE_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchPcieSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_PCIE_SMI_DISPATCH_PROTOCOL PCH_PCIE_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+typedef struct {
+ UINT8 RpIndex; ///< Root port index (0-based), 0: RP1, 1: RP2, n: RP(N+1)
+ UINT8 BusNum; ///< Root port pci bus number
+ UINT8 DevNum; ///< Root port pci device number
+ UINT8 FuncNum; ///< Root port pci function number
+} PCH_PCIE_SMI_RP_CONTEXT;
+
+/**
+ Callback function for an PCH PCIE RP SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+ @param[in] RpContext Pointer of PCH PCIE Root Port context.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_PCIE_SMI_RP_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ Register a child SMI source dispatch function for PCH PCIERP SMI events.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[in] RpIndex Refer to PCH PCIE Root Port index.
+ 0: RP1, 1: RP2, n: RP(N+1)
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_PCIE_SMI_RP_DISPATCH_REGISTER) (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent PCIE SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_PCIE_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH PCIE SMIs Dispatch Protocol
+ The PCH PCIE SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH PCIE related SMIs.
+ It contains SMI types of HotPlug, LinkActive, and Link EQ.
+**/
+struct _PCH_PCIE_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH PCIE SMI DISPATCH PROTOCOL.
+ **/
+ PCH_PCIE_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ PcieRpXHotPlug
+ The event is triggered when PCIE root port Hot-Plug Presence Detect.
+ **/
+ PCH_PCIE_SMI_RP_DISPATCH_REGISTER HotPlugRegister;
+ /**
+ PcieRpXLinkActive
+ The event is triggered when Hot-Plug Link Active State Changed.
+ **/
+ PCH_PCIE_SMI_RP_DISPATCH_REGISTER LinkActiveRegister;
+ /**
+ PcieRpXLinkEq
+ The event is triggered when Device Requests Software Link Equalization.
+ **/
+ PCH_PCIE_SMI_RP_DISPATCH_REGISTER LinkEqRegister;
+};
+
+/**
+ PCH PCIE SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_PCIE_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchReset.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchReset.h
new file mode 100644
index 0000000000..b39543b36e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchReset.h
@@ -0,0 +1,121 @@
+/** @file
+ PCH Reset Protocol
+
+Copyright (c) 2017, 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 that 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 _PCH_RESET_PROTOCOL_H_
+#define _PCH_RESET_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchResetProtocolGuid;
+extern EFI_GUID gPchResetCallbackProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_RESET_PROTOCOL PCH_RESET_PROTOCOL;
+typedef struct _PCH_RESET_CALLBACK_PROTOCOL PCH_RESET_CALLBACK_PROTOCOL;
+
+//
+// Related Definitions
+//
+///
+/// PCH Reset Types
+///
+typedef enum {
+ PchColdReset = 0,
+ PchWarmReset = 1,
+ PchShutdownReset = 2,
+ PchGlobalReset = 4,
+ PchResetTypeMax
+} PCH_RESET_TYPE;
+
+//
+// Member functions
+//
+/**
+ Execute Pch Reset from the host controller.
+
+ @param[in] This Pointer to the PCH_RESET_PROTOCOL instance.
+ @param[in] ResetType UEFI defined reset type.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER If ResetType is invalid.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_RESET) (
+ IN PCH_RESET_PROTOCOL *This,
+ IN EFI_RESET_TYPE ResetType,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ );
+
+/**
+ Retrieve PCH platform specific ResetData
+
+ @param[in] Guid PCH platform specific reset GUID.
+ @param[out] DataSize The size of ResetData in bytes.
+
+ @retval ResetData A platform specific reset that the exact type of
+ the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+ @retval NULL If Guid is not defined in PCH platform specific reset.
+**/
+typedef
+VOID *
+(EFIAPI *PCH_RESET_GET_RESET_DATA) (
+ IN EFI_GUID *Guid,
+ OUT UINTN *DataSize
+ );
+
+/**
+ Interface structure to execute Pch Reset from the host controller.
+**/
+struct _PCH_RESET_PROTOCOL {
+ PCH_RESET Reset;
+ PCH_RESET_GET_RESET_DATA GetResetData;
+};
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] ResetType Reset Types which includes PowerCycle, GlobalReset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of
+ callback protocol is installed.
+ @retval Others Do not do any reset from PCH
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_RESET_CALLBACK) (
+ IN PCH_RESET_TYPE ResetType
+ );
+
+/**
+ This protocol is used to execute PCH Reset from the host controller.
+ The PCH Reset protocol and PCH Reset PPI implement the Intel (R) PCH Reset Interface
+ for DXE and PEI environments, respectively. If other drivers need to run their
+ callback function right before issuing the reset, they can install PCH Reset
+ Callback Protocol/PPI before PCH Reset DXE/PEI driver to achieve that.
+**/
+struct _PCH_RESET_CALLBACK_PROTOCOL {
+ PCH_RESET_CALLBACK ResetCallback;
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
new file mode 100644
index 0000000000..4f0508b238
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
@@ -0,0 +1,139 @@
+/** @file
+ APIs of PCH SMI Dispatch Protocol.
+
+Copyright (c) 2017, 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 that 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 _PCH_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for specific PCH SMI dispatch event.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMI_DISPATCH_REGISTER) (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH specific SMIs Dispatch Protocol
+ The PCH SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH misc SMIs.
+ It contains legacy SMIs and new PCH SMI types like:
+ SerialIrq, McSmi, Smbus, ...
+**/
+struct _PCH_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH SMI DISPATCH PROTOCOL.
+ **/
+ PCH_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ SerialIrq
+ The event is triggered while the SMI# was caused by the SERIRQ decoder.
+ **/
+ PCH_SMI_DISPATCH_REGISTER SerialIrqRegister;
+ /**
+ McSmi
+ The event is triggered if there has been an access to the power management
+ microcontroller range (62h or 66h) and the Microcontroller Decode Enable #1 bit
+ in the LPC Bridge I/O Enables configuration register is 1 .
+ **/
+ PCH_SMI_DISPATCH_REGISTER McSmiRegister;
+ /**
+ SmBus
+ The event is triggered while the SMI# was caused by:
+ 1. The SMBus Slave receiving a message that an SMI# should be caused, or
+ 2. The SMBALERT# signal goes active and the SMB_SMI_EN bit is set and the
+ SMBALERT_DIS bit is cleared, or
+ 3. The SMBus Slave receiving a Host Notify message and the HOST_NOTIFY_INTREN and
+ the SMB_SMI_EN bits are set, or
+ 4. The PCH detecting the SMLINK_SLAVE_SMI command while in the S0 state.
+ **/
+ PCH_SMI_DISPATCH_REGISTER SmbusRegister;
+ /**
+ SPI Asynchronous
+ When registered, the flash controller will generate an SMI when it blocks a BIOS write or erase.
+ **/
+ PCH_SMI_DISPATCH_REGISTER SpiAsyncRegister;
+};
+
+/**
+ PCH SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
new file mode 100644
index 0000000000..5d0a4d34cf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
@@ -0,0 +1,72 @@
+/** @file
+ PCH SMM IO Trap Control Protocol
+
+Copyright (c) 2017, 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 that 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 _PCH_SMM_IO_TRAP_CONTROL_H_
+#define _PCH_SMM_IO_TRAP_CONTROL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSmmIoTrapControlGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_PROTOCOL;
+
+//
+// Related Definitions
+//
+
+//
+// Member functions
+//
+
+/**
+ The Prototype of Pause and Resume IoTrap callback function.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED/RESUMED.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_IO_TRAP_CONTROL_FUNCTION) (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL * This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for the SMM IO trap pause and resume protocol
+ This protocol provides the functions to runtime control the IoTrap SMI enabled/disable.
+ This applys the capability to the DispatchHandle which returned by IoTrap callback
+ registration, and the DispatchHandle which must be MergeDisable = TRUE and Address != 0.
+ Besides, when S3 resuem, it only restores the state of IoTrap callback registration.
+ The Paused/Resume state won't be restored after S3 resume.
+**/
+struct _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL {
+ /**
+ This runtime pauses a registered IoTrap handler.
+ **/
+ PCH_SMM_IO_TRAP_CONTROL_FUNCTION Pause;
+ /**
+ This runtime resumes a registered IoTrap handler.
+ **/
+ PCH_SMM_IO_TRAP_CONTROL_FUNCTION Resume;
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
new file mode 100644
index 0000000000..95c680e75c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
@@ -0,0 +1,72 @@
+/** @file
+ PCH SMM Periodic Timer Control Protocol
+
+Copyright (c) 2017, 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 that 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 _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
+#define _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSmmPeriodicTimerControlGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL;
+
+//
+// Related Definitions
+//
+
+//
+// Member functions
+//
+
+/**
+ The Prototype of Pause and Resume SMM PERIODIC TIMER function.
+
+ @param[in] This Pointer to the PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED/RESUMED.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION) (
+ IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for the SMM PERIODIC TIMER pause and resume protocol
+ This protocol provides the functions to runtime control the SM periodic timer enabled/disable.
+ This applies the capability to the DispatchHandle which returned by SMM periodic timer callback
+ registration.
+ Besides, when S3 resume, it only restores the state of callback registration.
+ The Paused/Resume state won't be restored after S3 resume.
+**/
+struct _PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL {
+ /**
+ This runtime pauses the registered periodic timer handler.
+ **/
+ PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION Pause;
+ /**
+ This runtime resumes the registered periodic timer handler.
+ **/
+ PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION Resume;
+};
+
+#endif // _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
new file mode 100644
index 0000000000..457cdb682c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
@@ -0,0 +1,157 @@
+/** @file
+ APIs of PCH TCO SMI Dispatch Protocol.
+
+Copyright (c) 2017, 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 that 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 _PCH_TCO_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_TCO_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchTcoSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_TCO_SMI_DISPATCH_PROTOCOL PCH_TCO_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH TCO SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_TCO_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for PCH TCO SMI events.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_TCO_SMI_DISPATCH_REGISTER) (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent TCO SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_TCO_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH TCO SMIs Dispatch Protocol
+ The PCH TCO SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH TCO related SMIs.
+ It contains SMI types of Mch, TcoTimeout, OsTco, Nmi, IntruderDectect, and BiowWp.
+**/
+struct _PCH_TCO_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH TCO SMI DISPATCH PROTOCOL.
+ **/
+ PCH_TCO_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ Mch
+ The event is triggered when PCH received a DMI special cycle message using DMI indicating that
+ it wants to cause an SMI.
+ The software must read the processor to determine the reason for the SMI.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER MchRegister;
+ /**
+ TcoTimeout
+ The event is triggered by PCH to indicate that the SMI was caused by the TCO timer reaching 0.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER TcoTimeoutRegister;
+ /**
+ OsTco
+ The event is triggered when software caused an SMI# by writing to the TCO_DAT_IN register (TCOBASE + 02h).
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER OsTcoRegister;
+ /**
+ Nmi
+ The event is triggered by the PCH when an SMI# occurs because an event occurred that would otherwise have
+ caused an NMI (because NMI2SMI_EN is set)
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER NmiRegister;
+ /**
+ IntruderDectect
+ The event is triggered by PCH to indicate that an intrusion was detected.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER IntruderDetRegister;
+ /**
+ SpiBiosWp
+ This event is triggered when SMI# was caused by the TCO logic and
+ SPI flash controller asserted Synchronous SMI by BIOS lock enable set.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER SpiBiosWpRegister;
+ /**
+ LpcBiosWp
+ This event is triggered when SMI# was caused by the TCO logic and
+ LPC/eSPI BIOS lock enable set.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER LpcBiosWpRegister;
+ /**
+ NewCentury
+ This event is triggered when SMI# was caused by the TCO logic and
+ year of RTC date rolls over a century (99 to 00).
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER NewCenturyRegister;
+};
+
+/**
+ PCH TCO SMI dispatch revision number
+
+ Revision 1: Initial version
+ Revision 2: Add NEWCENTURY support
+**/
+#define PCH_TCO_SMI_DISPATCH_REVISION 2
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/SerialGpio.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/SerialGpio.h
new file mode 100644
index 0000000000..4bc396132d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/SerialGpio.h
@@ -0,0 +1,126 @@
+/** @file
+ This file defines the PCH Serial GPIO Interface Protocol which implements the
+ Intel(R) Serial Data over GPIO Pin functionality Protocol Interface.
+
+Copyright (c) 2017, 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 that 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 _PCH_SERIAL_GPIO_PROTOCOL_H_
+#define _PCH_SERIAL_GPIO_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSerialGpioProtocolGuid;
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SERIAL_GPIO_PROTOCOL PCH_SERIAL_GPIO_PROTOCOL;
+
+#define SERIAL_GPIO_MAX_DATA_RATE 63
+#define WAIT_TIME 100000
+#define WAIT_PERIOD 10
+
+///
+/// Serial GPIO protocol data structures and definitions
+///
+typedef enum {
+ EnumSerialGpioDataByte,
+ EnumSerialGpioDataWord,
+ EnumSerialGpioDataUndefined,
+ EnumSerialGpioDataDword,
+ EnumSerialGpioDataMax
+} SERIAL_GPIO_DATA_WIDTH;
+
+//
+// Protocol member functions
+//
+/**
+ Register for one GPIO Pin that will be used as serial GPIO.
+ For SKL PCH only GPP_D_0-4 will have the capability to be used as serial GPIO.
+ The caller of this procedure need to be very clear of which GPIO should be used as serial GPIO,
+ it should not be input, native, conflict with other GPIO, or Index > 4 on the caller's platform.
+
+ @param[in] This Pointer to the PCH_SERIAL_GPIO_PROTOCOL instance.
+ @param[in] SerialGpioPad The GPIO pad number that will be used as serial GPIO for data sending.
+
+ @retval EFI_SUCCESS Opcode initialization on the SERIAL_GPIO host controller completed.
+ @retval EFI_ACCESS_DENIED The SERIAL_GPIO configuration interface is locked.
+ @retval EFI_OUT_OF_RESOURCES Not enough resource available to initialize the device.
+ @retval EFI_DEVICE_ERROR Device error, operation failed.
+ @retval EFI_INVALID_PARAMETER SerialGpioPinIndex is out of range
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SERIAL_GPIO_REGISTER) (
+ IN PCH_SERIAL_GPIO_PROTOCOL * This,
+ IN UINT8 SerialGpioPad
+ );
+
+/**
+ Unregister for one GPIO Pin that has been used as serial GPIO, and recover the registers before
+ registering.
+
+ @param[in] This Pointer to the PCH_SERIAL_GPIO_PROTOCOL instance.
+ @param[in] SerialGpioPad The GPIO pad number that will be used as serial GPIO for data sending.
+
+ @retval EFI_SUCCESS Opcode initialization on the SERIAL_GPIO host controller completed.
+ @retval EFI_ACCESS_DENIED The SERIAL_GPIO configuration interface is locked.
+ @retval EFI_OUT_OF_RESOURCES Not enough resource available to initialize the device.
+ @retval EFI_DEVICE_ERROR Device error, operation failed.
+ @retval EFI_INVALID_PARAMETER Invalid function parameters
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SERIAL_GPIO_UNREGISTER) (
+ IN PCH_SERIAL_GPIO_PROTOCOL * This,
+ IN UINT8 SerialGpioPad
+ );
+
+/**
+ Execute SERIAL_GPIO commands from the host controller.
+
+ @param[in] This Pointer to the PCH_SERIAL_GPIO_PROTOCOL instance.
+ @param[in] GpioPad GPIO pad number.
+ @param[in] DataRate The data rate for serial data transferring. 1 ~ SERIAL_GPIO_MAX_DATA_RATE; 1: 128ns intervals; ...; 8: 8*128 = 1024ns intervals, default value;...
+ @param[in] DataCountInByte Number of bytes of the data will be transmitted through the GPIO pin.
+ @param[in, out] Buffer Pointer to caller-allocated buffer containing the data sent through the GPIO pin.
+
+ @retval EFI_SUCCESS Execute succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, GPIO serial data sent failed.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SERIAL_GPIO_SEND_DATA) (
+ IN PCH_SERIAL_GPIO_PROTOCOL * This,
+ IN UINT8 GpioPad,
+ IN UINT8 DataRate,
+ IN UINTN DataCountInByte,
+ IN OUT UINT8 *Buffer
+ );
+/**
+ This Protocol allows a platform module to execute the IntelR Serial Data over
+ GPIO Pin functionality Protocol Interface.
+ The caller will first call the SerialGpioRegister() function to configure the GPIO
+ to be used. Then the caller will execute one or more calls to the SerialGpioSendData()
+ function to perform serial GPIO activities. Finally, the caller will use the
+ SerialGpioUnRegister() function to un-register and allow other consumers to utilize
+ the serial GPIO services.
+ If the serial GPIO capabilities are in use by another caller, the registration
+ function will return an error.
+**/
+struct _PCH_SERIAL_GPIO_PROTOCOL {
+ PCH_SERIAL_GPIO_REGISTER SerialGpioRegister; ///< Register for one GPIO pin that will be used as serial GPIO.
+ PCH_SERIAL_GPIO_SEND_DATA SerialGpioSendData; ///< Execute SERIAL_GPIO commands from the host controller.
+ PCH_SERIAL_GPIO_UNREGISTER SerialGpioUnRegister; ///< Un-register the current GPIO pin used for serial GPIO, and recovers the registers before registering.
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Spi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Spi.h
new file mode 100644
index 0000000000..e4ce8fb472
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Spi.h
@@ -0,0 +1,299 @@
+/** @file
+ This file defines the PCH SPI Protocol which implements the
+ Intel(R) PCH SPI Host Controller Compatibility Interface.
+
+Copyright (c) 2017, 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 that 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 _PCH_SPI_PROTOCOL_H_
+#define _PCH_SPI_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSpiProtocolGuid;
+extern EFI_GUID gPchSmmSpiProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL;
+
+//
+// SPI protocol data structures and definitions
+//
+
+/**
+ Flash Region Type
+**/
+typedef enum {
+ FlashRegionDescriptor,
+ FlashRegionBios,
+ FlashRegionMe,
+ FlashRegionGbE,
+ FlashRegionPlatformData,
+ FlashRegionDer,
+ FlashRegionAll,
+ FlashRegionMax
+} FLASH_REGION_TYPE;
+
+//
+// Protocol member functions
+//
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Write data to the flash part. Remark: Erase may be needed before write to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_WRITE) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_ERASE) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ );
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_SFDP) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ );
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_JEDEC_ID) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ );
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_WRITE_STATUS) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ );
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_STATUS) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ );
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_GET_REGION_ADDRESS) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ );
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_READ_PCH_SOFTSTRAP) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_READ_CPU_SOFTSTRAP) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ These protocols/PPI allows a platform module to perform SPI operations through the
+ Intel PCH SPI Host Controller Interface.
+**/
+struct _PCH_SPI_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ PCH_SPI_FLASH_READ FlashRead; ///< Read data from the flash part.
+ PCH_SPI_FLASH_WRITE FlashWrite; ///< Write data to the flash part. Remark: Erase may be needed before write to the flash part.
+ PCH_SPI_FLASH_ERASE FlashErase; ///< Erase some area on the flash part.
+ PCH_SPI_FLASH_READ_SFDP FlashReadSfdp; ///< Read SFDP data from the flash part.
+ PCH_SPI_FLASH_READ_JEDEC_ID FlashReadJedecId; ///< Read Jedec Id from the flash part.
+ PCH_SPI_FLASH_WRITE_STATUS FlashWriteStatus; ///< Write the status register in the flash part.
+ PCH_SPI_FLASH_READ_STATUS FlashReadStatus; ///< Read status register in the flash part.
+ PCH_SPI_GET_REGION_ADDRESS GetRegionAddress; ///< Get the SPI region base and size
+ PCH_SPI_READ_PCH_SOFTSTRAP ReadPchSoftStrap; ///< Read PCH Soft Strap Values
+ PCH_SPI_READ_CPU_SOFTSTRAP ReadCpuSoftStrap; ///< Read CPU Soft Strap Values
+};
+
+/**
+ PCH SPI PPI/PROTOCOL revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_SPI_SERVICES_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Wdt.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Wdt.h
new file mode 100644
index 0000000000..4a65e016e6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Protocol/Wdt.h
@@ -0,0 +1,118 @@
+/** @file
+ Watchdog Timer protocol
+
+Copyright (c) 2017, 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 that 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 _DXE_WDT_H_
+#define _DXE_WDT_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gWdtProtocolGuid;
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _WDT_PROTOCOL WDT_PROTOCOL;
+
+/**
+ Reloads WDT with new timeout value and starts it. Also sets Unexpected Reset bit, which
+ causes the next reset to be treated as watchdog expiration - unless AllowKnownReset()
+ function was called too.
+
+ @param[in] TimeoutValue Time in seconds before WDT times out. Supported range = 1 - 1024.
+
+ @retval EFI_SUCCESS if everything's OK
+ @retval EFI_INVALID_PARAMETER if TimeoutValue parameter is wrong
+**/
+typedef
+EFI_STATUS
+(EFIAPI *WDT_RELOAD_AND_START) (
+ UINT32 TimeoutValue
+ );
+
+/**
+ Returns WDT failure status.
+
+ @retval V_PCH_OC_WDT_CTL_STATUS_FAILURE If there was WDT expiration or unexpected reset
+ @retval V_PCH_OC_WDT_CTL_STATUS_OK Otherwise
+**/
+typedef
+UINT8
+(EFIAPI *WDT_CHECK_STATUS) (
+ VOID
+ );
+
+/**
+ Returns information if WDT coverage for the duration of BIOS execution
+ was requested by an OS application.
+
+ @retval TRUE if WDT was requested
+ @retval FALSE if WDT was not requested
+**/
+typedef
+UINT8
+(EFIAPI *IS_WDT_REQUIRED) (
+ VOID
+ );
+
+/**
+ Returns WDT enabled/disabled status.
+
+ @retval TRUE if WDT is enabled
+ @retval FALSE if WDT is disabled
+**/
+typedef
+UINT8
+(EFIAPI *IS_WDT_ENABLED) (
+ VOID
+ );
+
+/**
+ Disables WDT timer.
+**/
+typedef
+VOID
+(EFIAPI *WDT_DISABLE) (
+ VOID
+ );
+
+/**
+ Normally, each reboot performed while watchdog runs is considered a failure.
+ This function allows platform to perform expected reboots with WDT running,
+ without being interpreted as failures.
+ In DXE phase, it is enough to call this function any time before reset.
+ In PEI phase, between calling this function and performing reset, ReloadAndStart()
+ must not be called.
+**/
+typedef
+VOID
+(EFIAPI *WDT_ALLOW_KNOWN_RESET) (
+ VOID
+ );
+
+/**
+ These protocols and PPI allow a platform module to perform watch dog timer operations
+ through the Intel PCH LPC Host Controller Interface. The WDT protocol and WDT PPI
+ implement the Intel (R) Watch Dog timer for DXE, and PEI environments, respectively.
+ WDT_PROTOCOL referenced hereafter represents both WDT_PROTOCOL and WDT_PPI, as they
+ share the identical data structure.
+**/
+struct _WDT_PROTOCOL {
+ WDT_RELOAD_AND_START ReloadAndStart; ///< Reloads WDT with new timeout value and starts it.
+ WDT_CHECK_STATUS CheckStatus; ///< Returns WDT failure status.
+ WDT_DISABLE Disable; ///< Disables WDT timer.
+ WDT_ALLOW_KNOWN_RESET AllowKnownReset; ///< Perform expected reboots with WDT running, without being interpreted as failures.
+ IS_WDT_REQUIRED IsWdtRequired; ///< Returns information if WDT coverage for the duration of BIOS execution was requested by an OS application.
+ IS_WDT_ENABLED IsWdtEnabled; ///< Returns WDT enabled/disabled status.
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsCam.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsCam.h
new file mode 100644
index 0000000000..c4be5c27e7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsCam.h
@@ -0,0 +1,151 @@
+/** @file
+ Register names for Camera block
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_CAM_H_
+#define _PCH_REGS_CAM_H_
+
+//
+// CIO2 Registers (D20:F3)
+//
+#define PCI_DEVICE_NUMBER_PCH_CIO2 20
+#define PCI_FUNCTION_NUMBER_PCH_CIO2 3
+#define V_PCH_CIO2_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+#define V_PCH_LP_CIO2_DEVICE_ID 0x9D32
+
+//
+// CIO2 PCI Configuration space definitions
+//
+#define R_PCH_CIO2_CIOLBA 0x10 // Camera IO Controller Lower Base Address
+#define R_PCH_CIO2_CIOUBA 0x14 // Camera IO Controller Upper Base Address
+#define B_PCH_CIO2_CFG_PMCSR_NSR BIT3 // No Software Reset
+#define R_PCH_CIO2_CFG_MID_MMC 0x90 // MSI Capability ID
+#define R_PCH_CIO2_CFG_MMLA 0x94 // MSI Message Lower Address
+#define R_PCH_CIO2_CFG_MMUA 0x98 // MSI Message Lower Address
+#define R_PCH_CIO2_CFG_MMD 0x9C // MSI Message Data
+#define R_PCH_CIO2_AFID 0xA0 // Advanced Features Capability Identifiers
+#define R_PCH_CIO2_AF_CMD_STS 0xA4 // Adavanced Features Command and Staus Register
+#define R_PCH_CIO2_CFG_PID_PC 0xD0 // Power Management Capability Identifiers
+#define R_PCH_CIO2_CFG_PMCSR 0xD4 // Power Management Control & Status
+#define V_PCH_CIO2_CFG_PMCSR_PS_D3HOT (BIT0 | BIT1)
+
+//
+// CAM_MMIO_CSI2
+//
+
+//
+// CAM_MMIO_PRI
+// Camera Pipe Host Controller's MMIO registers in Primary clock domain
+//
+#define R_PCH_CAM_MMIO_PRI_CIO2_CGC 0x1400 ///< CIO2 Clock Gating Control
+#define V_PCH_CAM_MMIO_PRI_CIO2_CGC_CLK_GATING_EN (0x00003D7E)
+#define V_PCH_CAM_MMIO_PRI_CIO2_CGC_CLK_GATING_DIS (0x05300000)
+#define R_PCH_CAM_MMIO_PRI_CIO2_D0I3C 0x1408 ///< CIO2 D0i3 Control Register
+#define B_PCH_CAM_MMIO_PRI_CIO2_D0I3C_I3 BIT2 ///< I3 (D0i3). SW sets this bit to 1 to move the IP into the D0i3 state. Writing this bit to 0 will return the IP to the fully active D0 state (D0i0)
+#define R_PCH_CAM_MMIO_PRI_PCE 0x1430 ///< PCE Power Control Enable Register
+#define B_PCH_CAM_MMIO_PRI_PCE_D3HE BIT2 ///< D3HE: D3-Hot Enable
+#define B_PCH_CAM_MMIO_PRI_PCE_I3E BIT1 ///< I3E: I3 Enable
+#define R_PCH_CAM_MMIO_PRI_CIO2_GPR0 0x1434 ///< CIO2 General Purpose register 0
+#define R_PCH_CAM_MMIO_PRI_CIO2_GPR1 0x1438 ///< CIO2 General Purpose register 1
+
+//
+// CAM_PVT CHC space defininitions
+// Private registers description for Camera Pipe Host Controller IP
+// MSG IOSF-SB Port 0xA1 (PID_CAM_CHC)
+//
+#define R_PCH_PCR_CAM_CHC_PVT_FUSVAL 0x00 ///< Fuse Value
+#define R_PCH_PCR_CAM_CHC_PVT_ECCLOG 0x04 ///< SRAM Error Count Log
+#define R_PCH_PCR_CAM_CHC_PVT_DBGCTL 0x08 ///< Debug Control
+#define R_PCH_PCR_CAM_CHC_PVT_FNCFG 0x0C ///< Lock bits
+#define B_PCH_PCR_CAM_CHC_PVT_FNCFG_MEM_LOCK BIT8 ///< lock all lockable field in MEM space
+#define B_PCH_PCR_CAM_CHC_PVT_FNCFG_BCLD BIT0 ///< lock all lockable fields in CFG space
+#define R_PCH_PCR_CAM_CHC_HDEVC 0x10 ///< Hidden Device register
+#define R_PCH_PCR_CAM_CHC_PVT_FUSE_DBG 0x14 ///< Hidden Device register
+
+//
+// fls space definitions
+// CSI2 host controller's FLIS registers
+// MSG IOSF-SB Port 0xAA (PID_CAM_FLS)
+//
+#define R_PCH_PCR_CAM_FLIS_CSI0_RXCNTRL 0x00
+#define R_PCH_PCR_CAM_FLIS_CSI0_RCCRCOMP 0x01
+#define R_PCH_PCR_CAM_FLIS_CSI0_BSCOMPARE 0x02
+#define R_PCH_PCR_CAM_FLIS_CSI1_RXCNTRL 0x03
+#define R_PCH_PCR_CAM_FLIS_CSI1_RCCRCOMP 0x04
+#define R_PCH_PCR_CAM_FLIS_CSI0_INTLPBK_CFG1 0x05
+#define R_PCH_PCR_CAM_FLIS_CSI1_BSCOMPARE 0x06
+#define R_PCH_PCR_CAM_FLIS_CSI0_INTLPBK_CFG2 0x07
+#define R_PCH_PCR_CAM_FLIS_CSI0_INTLPBK_CFG3 0x08
+#define R_PCH_PCR_CAM_FLIS_CSI2_INTLPBK_CFG2 0x09
+#define R_PCH_PCR_CAM_FLIS_CSI2_RXCNTRL 0x0A
+#define R_PCH_PCR_CAM_FLIS_CSI2_RCCRCOMP 0x0B
+#define R_PCH_PCR_CAM_FLIS_CSI2_BSCOMPARE 0x0C
+#define R_PCH_PCR_CAM_FLIS_CSI0_INTLPBK_CMP_STAT 0x0D
+#define R_PCH_PCR_CAM_FLIS_CSI0_INTLPBK_ERR_REG 0x0E
+#define R_PCH_PCR_CAM_FLIS_CSI_CLKTRIM 0x0F
+#define R_PCH_PCR_CAM_FLIS_CSI3_RXCNTRL 0x10
+#define R_PCH_PCR_CAM_FLIS_CSI3_RCCRCOMP 0x11
+#define R_PCH_PCR_CAM_FLIS_CSI3_BSCOMPARE 0x12
+#define R_PCH_PCR_CAM_FLIS_CSI_CFG 0x13
+#define B_PCH_PCR_CAM_FLIS_CSI_CFG_ACIO_LB_EN BIT26
+#define R_PCH_PCR_CAM_FLIS_CSI1_INTLPBK_CFG1 0x14
+#define R_PCH_PCR_CAM_FLIS_CSI1_INTLPBK_CFG2 0x15
+#define R_PCH_PCR_CAM_FLIS_CSI1_INTLPBK_CFG3 0x16
+#define R_PCH_PCR_CAM_FLIS_CSI2_INTLPBK_CFG1 0x17
+#define R_PCH_PCR_CAM_FLIS_CSI2_INTLPBK_CFG3 0x18
+#define R_PCH_PCR_CAM_FLIS_CSI3_INTLPBK_CFG1 0x19
+#define R_PCH_PCR_CAM_FLIS_CSI3_INTLPBK_CFG3 0x1A
+#define R_PCH_PCR_CAM_FLIS_CSI1_INTLPBK_ERR_REG 0x1B
+#define R_PCH_PCR_CAM_FLIS_CSI1_INTLPBK_CMP_STAT 0x1C
+#define R_PCH_PCR_CAM_FLIS_CSI2_INTLPBK_ERR_REG 0x1D
+#define R_PCH_PCR_CAM_FLIS_CSI2_INTLPBK_CMP_STAT 0x1E
+#define R_PCH_PCR_CAM_FLIS_CSI3_INTLPBK_ERR_REG 0x1F
+#define R_PCH_PCR_CAM_FLIS_CSI3_INTLPBK_CMP_STAT 0x20
+#define R_PCH_PCR_CAM_FLIS_CSI_RCOMPSTAT_REG 0x21
+#define R_PCH_PCR_CAM_FLIS_CSI_DLLCTL_REG 0x22
+#define R_PCH_PCR_CAM_FLIS_CSI_DATAEYE_REG 0x23
+#define R_PCH_PCR_CAM_FLIS_CSI_DATATRIM 0x24
+#define R_PCH_PCR_CAM_FLIS_CSI_CTLE 0x25
+#define R_PCH_PCR_CAM_FLIS_CSI0_DFT_CFG 0x26
+#define R_PCH_PCR_CAM_FLIS_CSI1_DFT_CFG 0x27
+#define R_PCH_PCR_CAM_FLIS_CSI2_DFT_CFG 0x28
+#define R_PCH_PCR_CAM_FLIS_CSI3_DFT_CFG 0x29
+#define R_PCH_PCR_CAM_FLIS_CSI_AFE_HS_CONTROL 0x2A
+#define R_PCH_PCR_CAM_FLIS_CSI_RCOMP_STATUS 0x2B
+#define R_PCH_PCR_CAM_FLIS_CSI_RCOMP_CONTROL 0x2C
+#define R_PCH_PCR_CAM_FLIS_CSI_DATAEYE1_REG 0x2D
+#define R_PCH_PCR_CAM_FLIS_CSI_ALL01 0x2E
+#define R_PCH_PCR_CAM_FLIS_CSI_DLLCTL1_REG 0x2F
+#define R_PCH_PCR_CAM_FLIS_CSI_DATATRIM1 0x30
+
+#endif
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDci.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDci.h
new file mode 100644
index 0000000000..d38bd7f0c4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDci.h
@@ -0,0 +1,50 @@
+/** @file
+ Register names for PCH DCI device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_DCI_H_
+#define _PCH_REGS_DCI_H_
+
+//
+// DCI PCR Registers
+//
+#define R_PCH_PCR_DCI_ECTRL 0x04 ///< DCI Control Register
+#define B_PCH_PCR_DCI_ECTRL_HDCIEN BIT4 ///< Host DCI enable
+#define B_PCH_PCR_DCI_ECTRL_HDCIEN_LOCK BIT0 ///< Host DCI Enable Lock
+#define R_PCH_PCR_DCI_ECKPWRCTL 0x08 ///< DCI Power Control
+#define R_PCH_PCR_DCI_PCE 0x30 ///< DCI Power Control Enable Register
+#define B_PCH_PCR_DCI_PCE_HAE BIT5 ///< Hardware Autonomous Enable
+#define B_PCH_PCR_DCI_PCE_D3HE BIT2 ///< D3-Hot Enable
+#define B_PCH_PCR_DCI_PCE_I3E BIT1 ///< I3 Enable
+#define B_PCH_PCR_DCI_PCE_PMCRE BIT0 ///< PMC Request Enable
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDmi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDmi.h
new file mode 100644
index 0000000000..942aeda324
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsDmi.h
@@ -0,0 +1,214 @@
+/** @file
+ Register names for DMI and OP-DMI
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_DMI_H_
+#define _PCH_REGS_DMI_H_
+
+//
+// DMI Chipset Configuration Registers (PID:DMI)
+//
+
+//
+// VC Configuration (Common)
+//
+#define R_PCH_PCR_DMI_V0CTL 0x2014 ///< Virtual channel 0 resource control
+#define B_PCH_PCR_DMI_V0CTL_EN BIT31
+#define B_PCH_PCR_DMI_V0CTL_ID (7 << 24) ///< Bit[26:24]
+#define N_PCH_PCR_DMI_V0CTL_ID 24
+#define V_PCH_PCR_DMI_V0CTL_ETVM_MASK 0xFC00
+#define V_PCH_PCR_DMI_V0CTL_TVM_MASK 0x7E
+#define R_PCH_PCR_DMI_V0STS 0x201A ///< Virtual channel 0 status
+#define B_PCH_PCR_DMI_V0STS_NP BIT1
+#define R_PCH_PCR_DMI_V1CTL 0x2020 ///< Virtual channel 1 resource control
+#define B_PCH_PCR_DMI_V1CTL_EN BIT31
+#define B_PCH_PCR_DMI_V1CTL_ID (0x0F << 24) ///< Bit[27:24]
+#define N_PCH_PCR_DMI_V1CTL_ID 24
+#define V_PCH_PCR_DMI_V1CTL_ETVM_MASK 0xFC00
+#define V_PCH_PCR_DMI_V1CTL_TVM_MASK 0xFE
+#define R_PCH_PCR_DMI_V1STS 0x2026 ///< Virtual channel 1 status
+#define B_PCH_PCR_DMI_V1STS_NP BIT1
+#define R_PCH_PCR_DMI_VMCTL 0x2040 ///< ME Virtual Channel (VCm) resource control
+#define R_PCH_PCR_DMI_VMSTS 0x2046 ///< ME Virtual Channel Resource Status
+#define R_PCH_PCR_DMI_UEM 0x2088 ///< Uncorrectable Error Mask
+#define R_PCH_PCR_DMI_REC 0x20AC ///< Root Error Command
+
+//
+// Internal Link Configuration (DMI Only)
+//
+#define R_PCH_PCR_DMI_LCAP 0x21A4 ///< Link Capabilities
+#define B_PCH_PCR_DMI_LCAP_EL1 (BIT17 | BIT16 | BIT15)
+#define B_PCH_PCR_DMI_LCAP_EL0 (BIT14 | BIT13 | BIT12)
+#define B_PCH_PCR_DMI_LCAP_APMS (BIT11 | BIT10) ///< L0 is supported on DMI
+#define B_PCH_PCR_DMI_LCAP_MLW 0x000003F0
+#define B_PCH_PCR_DMI_LCAP_MLS 0x0000000F
+#define R_PCH_PCR_DMI_LCTL 0x21A8 ///< Link Control
+#define B_PCH_PCR_DMI_LCTL_ES BIT7
+#define B_PCH_PCR_DMI_LCTL_ASPM (BIT1 | BIT0) ///< Link ASPM
+#define R_PCH_PCR_DMI_LSTS 0x21AA ///< Link Status
+#define R_PCH_PCR_DMI_LCTL2 0x21B0 ///< Link Control 2
+#define R_PCH_PCR_DMI_LSTS2 0x21B2 ///< Link Status 2
+#define R_PCH_PCR_DMI_L01EC 0x21BC ///< Lane 0 and Lane 1 Equalization Control
+#define R_PCH_PCR_DMI_L23EC 0x21C0 ///< Lane 2 and Lane 3 Equalization Control
+#define B_PCH_PCR_DMI_UPL13RPH 0x0F000000 ///< Upstream Port Lane 1/3 Transmitter Preset Hint mask
+#define N_PCH_PCR_DMI_UPL13RPH 24 ///< Upstream Port Lane 1/3 Transmitter Preset Hint value offset
+#define B_PCH_PCR_DMI_UPL02RPH 0x000000F0 ///< Upstream Port Lane 0/2 Transmitter Preset Hint mask
+#define N_PCH_PCR_DMI_UPL02RPH 8 ///< Upstream Port Lane 0/2 Transmitter Preset Hint value offset
+#define V_PCH_PCR_DMI_UPL0RPH 7 ///< Upstream Port Lane 0 Transmitter Preset Hint value
+#define V_PCH_PCR_DMI_UPL1RPH 7 ///< Upstream Port Lane 1 Transmitter Preset Hint value
+#define V_PCH_PCR_DMI_UPL2RPH 7 ///< Upstream Port Lane 2 Transmitter Preset Hint value
+#define V_PCH_PCR_DMI_UPL3RPH 7 ///< Upstream Port Lane 3 Transmitter Preset Hint value
+
+
+//
+// North Port Error Injection Configuration (DMI Only)
+//
+#define R_PCH_PCR_DMI_DMIEN 0x2230 ///< DMI Error Injection Enable
+
+//
+// DMI Control
+//
+#define R_PCH_PCR_DMI_DMIC 0x2234 ///< DMI Control
+#define B_PCH_PCR_DMI_DMIC_SRL BIT31 ///< Secured register lock
+#define B_PCH_PCR_DMI_DMIC_ORCE (BIT25 | BIT24) ///< Offset Re-Calibration Enable
+#define N_PCH_PCR_DMI_DMIC_ORCE 24
+#define V_PCH_PCR_DMI_DMIC_ORCE_EN_GEN2_GEN3 1 ///< Enable offset re-calibration for Gen 2 and Gen 3 data rate only.
+#define B_PCH_PCR_DMI_DMIC_DMICGEN (BIT4 | BIT3 | BIT2 | BIT1 | BIT0) ///< DMI Clock Gate Enable
+#define R_PCH_PCR_DMI_DMIHWAWC 0x2238 ///< DMI HW Autonomus Width Control
+#define R_PCH_PCR_DMI_IOSFSBCS 0x223E ///< IOSF Sideband Control and Status
+#define B_PCH_PCR_DMI_IOSFSBCS_DMICGEN (BIT6 | BIT5 | BIT3 | BIT2) ///< DMI Clock Gate Enable
+
+#define R_PCH_PCR_DMI_2300 0x2300
+#define R_PCH_PCR_DMI_2304 0x2304
+#define R_PCH_PCR_DMI_2310 0x2310
+#define R_PCH_PCR_DMI_2314 0x2314
+#define R_PCH_PCR_DMI_2320 0x2320
+#define R_PCH_PCR_DMI_2324 0x2324
+#define R_PCH_PCR_DMI_232C 0x232C
+#define R_PCH_PCR_DMI_2334 0x2334
+#define R_PCH_PCR_DMI_2338 0x2338
+#define R_PCH_PCR_DMI_2340 0x2340
+#define R_PCH_PCR_DMI_2344 0x2344
+#define R_PCH_PCR_DMI_2348 0x2348
+#define R_PCH_PCR_DMI_234C 0x234C
+
+//
+// Port Configuration Extension(DMI Only)
+//
+#define R_PCH_PCR_DMI_EQCFG1 0x2450
+#define B_PCH_PCR_DMI_EQCFG1_RTLEPCEB BIT16
+#define R_PCH_PCR_DMI_LTCO1 0x2470 ///< Local Transmitter Coefficient Override 1
+#define R_PCH_PCR_DMI_LTCO2 0x2474 ///< Local Transmitter Coefficient Override 2
+#define B_PCH_PCR_DMI_L13TCOE BIT25 ///< Lane 1/3 Transmitter Coefficient Override Enable
+#define B_PCH_PCR_DMI_L02TCOE BIT24 ///< Lane 0/2 Transmitter Coefficient Override Enable
+#define B_PCH_PCR_DMI_L13TPOSTCO 0x00fc0000 ///< Lane 1/3 Transmitter Post-Cursor Coefficient Override mask
+#define N_PCH_PCR_DMI_L13TPOSTCO 18 ///< Lane 1/3 Transmitter Post-Cursor Coefficient Override value offset
+#define B_PCH_PCR_DMI_L13TPRECO 0x0003f000 ///< Lane 1/3 Transmitter Pre-Cursor Coefficient Override mask
+#define N_PCH_PCR_DMI_L13TPRECO 12 ///< Lane 1/3 Transmitter Pre-Cursor Coefficient Override value offset
+#define B_PCH_PCR_DMI_L02TPOSTCO 0x00000fc0 ///< Lane 0/2 Transmitter Post-Cursor Coefficient Override mask
+#define N_PCH_PCR_DMI_L02TPOSTCO 6 ///< Lane 0/2 Transmitter Post-Cursor Coefficient Override value offset
+#define B_PCH_PCR_DMI_L02TPRECO 0x0000003f ///< Lane 0/2 Transmitter Pre-Cursor Coefficient Override mask
+#define N_PCH_PCR_DMI_L02TPRECO 0 ///< Lane 0/2 Transmitter Pre-Cursor Coefficient Override value offset
+#define R_PCH_PCR_DMI_G3L0SCTL 0x2478 ///< GEN3 L0s Control
+
+//
+// OP-DMI Specific Registers (OP-DMI Only)
+//
+#define R_PCH_PCR_OPDMI_LCTL 0x2600 ///< Link Control
+#define R_PCH_PCR_OPDMI_STC 0x260C ///< Sideband Timing Control
+#define R_PCH_PCR_OPDMI_LPMC 0x2614 ///< Link Power Management Control
+#define R_PCH_PCR_OPDMI_LCFG 0x2618 ///< Link Configuration
+
+//
+// DMI Source Decode PCRs (Common)
+//
+#define R_PCH_PCR_DMI_PCIEPAR1E 0x2700 ///< PCIE Port IOxAPIC Range 1 Enable
+#define R_PCH_PCR_DMI_PCIEPAR2E 0x2704 ///< PCIE Port IOxAPIC Range 2 Enable
+#define R_PCH_PCR_DMI_PCIEPAR3E 0x2708 ///< PCIE Port IOxAPIC Range 3 Enable
+#define R_PCH_PCR_DMI_PCIEPAR4E 0x270C ///< PCIE Port IOxAPIC Range 4 Enable
+#define R_PCH_PCR_DMI_PCIEPAR1DID 0x2710 ///< PCIE Port IOxAPIC Range 1 Destination ID
+#define R_PCH_PCR_DMI_PCIEPAR2DID 0x2714 ///< PCIE Port IOxAPIC Range 2 Destination ID
+#define R_PCH_PCR_DMI_PCIEPAR3DID 0x2718 ///< PCIE Port IOxAPIC Range 3 Destination ID
+#define R_PCH_PCR_DMI_PCIEPAR4DID 0x271C ///< PCIE Port IOxAPIC Range 4 Destination ID
+#define R_PCH_PCR_DMI_P2SBIOR 0x2720 ///< P2SB IO Range
+#define R_PCH_PCR_DMI_TTTBARB 0x2724 ///< Thermal Throttling BIOS Assigned Thermal Base Address
+#define R_PCH_PCR_DMI_TTTBARBH 0x2728 ///< Thermal Throttling BIOS Assigned Thermal Base High Address
+#define R_PCH_PCR_DMI_LPCLGIR1 0x2730 ///< LPC Generic I/O Range 1
+#define R_PCH_PCR_DMI_LPCLGIR2 0x2734 ///< LPC Generic I/O Range 2
+#define R_PCH_PCR_DMI_LPCLGIR3 0x2738 ///< LPC Generic I/O Range 3
+#define R_PCH_PCR_DMI_LPCLGIR4 0x273C ///< LPC Generic I/O Range 4
+#define R_PCH_PCR_DMI_LPCGMR 0x2740 ///< LPC Generic Memory Range
+#define R_PCH_PCR_DMI_LPCBDE 0x2744 ///< LPC BIOS Decode Enable
+#define R_PCH_PCR_DMI_UCPR 0x2748 ///< uCode Patch Region
+#define B_PCH_PCR_DMI_UCPR_UPRE BIT0 ///< uCode Patch Region Enable
+#define R_PCH_PCR_DMI_GCS 0x274C ///< Generic Control and Status
+#define B_PCH_PCR_DMI_RPRDID 0xFFFF0000 ///< RPR Destination ID
+#define B_PCH_PCR_DMI_BBS BIT10 ///< Boot BIOS Strap
+#define B_PCH_PCR_DMI_RPR BIT11 ///< Reserved Page Route
+#define B_PCH_PCR_DMI_BILD BIT0 ///< BIOS Interface Lock-Down
+#define R_PCH_PCR_DMI_IOT1 0x2750 ///< I/O Trap Register 1
+#define R_PCH_PCR_DMI_IOT2 0x2758 ///< I/O Trap Register 2
+#define R_PCH_PCR_DMI_IOT3 0x2760 ///< I/O Trap Register 3
+#define R_PCH_PCR_DMI_IOT4 0x2768 ///< I/O Trap Register 4
+#define R_PCH_PCR_DMI_LPCIOD 0x2770 ///< LPC I/O Decode Ranges
+#define R_PCH_PCR_DMI_LPCIOE 0x2774 ///< LPC I/O Enables
+#define R_PCH_PCR_DMI_TCOBASE 0x2778 ///< TCO Base Address
+#define B_PCH_PCR_DMI_TCOBASE_TCOBA 0xFFE0 ///< TCO Base Address Mask
+#define R_PCH_PCR_DMI_GPMR1 0x277C ///< General Purpose Memory Range 1
+#define R_PCH_PCR_DMI_GPMR1DID 0x2780 ///< General Purpose Memory Range 1 Destination ID
+#define R_PCH_PCR_DMI_GPMR2 0x2784 ///< General Purpose Memory Range 2
+#define R_PCH_PCR_DMI_GPMR2DID 0x2788 ///< General Purpose Memory Range 2 Destination ID
+#define R_PCH_PCR_DMI_GPMR3 0x278C ///< General Purpose Memory Range 3
+#define R_PCH_PCR_DMI_GPMR3DID 0x2790 ///< General Purpose Memory Range 3 Destination ID
+#define R_PCH_PCR_DMI_GPIOR1 0x2794 ///< General Purpose I/O Range 1
+#define R_PCH_PCR_DMI_GPIOR1DID 0x2798 ///< General Purpose I/O Range 1 Destination ID
+#define R_PCH_PCR_DMI_GPIOR2 0x279C ///< General Purpose I/O Range 2
+#define R_PCH_PCR_DMI_GPIOR2DID 0x27A0 ///< General Purpose I/O Range 2 Destination ID
+#define R_PCH_PCR_DMI_GPIOR3 0x27A4 ///< General Purpose I/O Range 3
+#define R_PCH_PCR_DMI_GPIOR3DID 0x27A8 ///< General Purpose I/O Range 3 Destination ID
+#define R_PCH_PCR_DMI_PMBASEA 0x27AC ///< PM Base Address
+#define R_PCH_PCR_DMI_PMBASEC 0x27B0 ///< PM Base Control
+#define R_PCH_PCR_DMI_ACPIBA 0x27B4 ///< ACPI Base Address
+#define R_PCH_PCR_DMI_ACPIBDID 0x27B8 ///< ACPI Base Destination ID
+
+
+//
+// Opi PHY registers
+//
+#define R_PCH_PCR_OPIPHY_0110 0x0110
+#define R_PCH_PCR_OPIPHY_0118 0x0118
+#define R_PCH_PCR_OPIPHY_011C 0x011C
+#define R_PCH_PCR_OPIPHY_0354 0x0354
+#define R_PCH_PCR_OPIPHY_B104 0xB104
+#define R_PCH_PCR_OPIPHY_B10C 0xB10C
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsFia.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsFia.h
new file mode 100644
index 0000000000..c9e08ca854
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsFia.h
@@ -0,0 +1,123 @@
+/** @file
+ Register definition for FIA component
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_FIA_H_
+#define _PCH_REGS_FIA_H_
+
+
+//
+// Private chipset regsiter (Memory space) offset definition
+// The PCR register defines is used for PCR MMIO programming and PCH SBI programming as well.
+//
+
+//
+// PID:FIA
+//
+#define SKL_PCH_MAX_FIA_DRCRM 3
+#define KBL_PCH_MAX_FIA_DRCRM 4
+#define PCH_MAX_FIA_DRCRM KBL_PCH_MAX_FIA_DRCRM
+#define R_PCH_PCR_FIA_CC 0
+#define B_PCH_PCR_FIA_CC_SRL BIT31
+#define B_PCH_PCR_FIA_CC_PTOCGE BIT17
+#define B_PCH_PCR_FIA_CC_OSCDCGE BIT16
+#define B_PCH_PCR_FIA_CC_SCPTCGE BIT15
+
+#define R_PCH_PCR_FIA_PLLCTL 0x20
+#define R_PCH_PCR_FIA_DRCRM1 0x100
+#define R_PCH_PCR_FIA_DRCRM2 0x104
+#define R_PCH_PCR_FIA_DRCRM3 0x108
+#define R_PCH_PCR_FIA_DRCRM4 0x10C // KBL-H only
+#define N_PCH_PCR_FIA_DRCRM_GBEPCKRQM 23
+#define S_PCH_PCR_FIA_DRCRM_BITS_PER_FIELD 4 // CLKREQ number is encoded in 4 bits
+#define S_PCH_PCR_FIA_DRCRM_FIELDS_PER_REG 8 // each DRCRM register contains bitfields for 8 rootports
+#define V_PCH_PCR_FIA_DRCRM_NO_CLKREQ 0 // ClkReq not present
+#define S_PCH_PCR_FIA_DRCRM 4
+#define R_PCH_PCR_FIA_STRPFUSECFG1_REG_BASE 0x200
+#define B_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIE_PEN BIT31
+#define B_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIEPORTSEL (BIT30 | BIT29 | BIT28)
+#define N_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIEPORTSEL 28
+#define R_PCH_PCR_FIA_PCIESATA_FUSECFG_REG_BASE 0x204
+#define R_PCH_PCR_FIA_PCIESATA_STRPCFG_REG_BASE 0x208
+#define R_PCH_PCR_FIA_PCIEUSB3_STRPFUSECFG_REG_BASE 0x20C
+#define R_PCH_PCR_FIA_EXP_FUSECFG_REG_BASE 0x210
+#define R_PCH_PCR_FIA_USB3SSIC_STRPFUSECFG_REG_BASE 0x214
+#define R_PCH_PCR_FIA_CSI3_STRPFUSECFG_REG_BASE 0x218
+#define R_PCH_PCR_FIA_USB3SATA_STRPFUSECFG_REG_BASE 0x21C
+#define R_PCH_PCR_FIA_UFS_STRPFUSECFG_REG_BASE 0x220
+#define R_PCH_PCR_FIA_LOS1_REG_BASE 0x250
+#define R_PCH_PCR_FIA_LOS2_REG_BASE 0x254
+#define R_PCH_PCR_FIA_LOS3_REG_BASE 0x258
+#define R_PCH_PCR_FIA_LOS4_REG_BASE 0x25C
+#define V_PCH_PCR_FIA_LANE_OWN_PCIEDMI 0x0
+#define V_PCH_PCR_FIA_LANE_OWN_USB3 0x1
+#define V_PCH_PCR_FIA_LANE_OWN_SATA 0x2
+#define V_PCH_PCR_FIA_LANE_OWN_GBE 0x3
+#define V_PCH_PCR_FIA_LANE_OWN_MOBEXP 0x4
+#define V_PCH_PCR_FIA_LANE_OWN_SSIC 0x5
+#define V_PCH_PCR_FIA_LANE_OWN_CSI3 0x6
+#define V_PCH_PCR_FIA_LANE_OWN_UFS 0x7
+#define B_PCH_PCR_FIA_L0O (BIT3 | BIT2 | BIT1 | BIT0)
+#define B_PCH_PCR_FIA_L1O (BIT7 | BIT6 | BIT5 | BIT4)
+#define B_PCH_PCR_FIA_L2O (BIT11 | BIT10 | BIT9 | BIT8)
+#define B_PCH_PCR_FIA_L3O (BIT15 | BIT14 | BIT13 | BIT12)
+#define B_PCH_PCR_FIA_L4O (BIT19 | BIT18 | BIT17 | BIT16)
+#define B_PCH_PCR_FIA_L5O (BIT23 | BIT22 | BIT21 | BIT20)
+#define B_PCH_PCR_FIA_L6O (BIT27 | BIT26 | BIT25 | BIT24)
+#define B_PCH_PCR_FIA_L7O (BIT31 | BIT30 | BIT29 | BIT28)
+#define B_PCH_PCR_FIA_L8O (BIT3 | BIT2 | BIT1 | BIT0)
+#define B_PCH_PCR_FIA_L9O (BIT7 | BIT6 | BIT5 | BIT4)
+#define B_PCH_PCR_FIA_L10O (BIT11 | BIT10 | BIT9 | BIT8)
+#define B_PCH_PCR_FIA_L11O (BIT15 | BIT14 | BIT13 | BIT12)
+#define B_PCH_PCR_FIA_L12O (BIT19 | BIT18 | BIT17 | BIT16)
+#define B_PCH_PCR_FIA_L13O (BIT23 | BIT22 | BIT21 | BIT20)
+#define B_PCH_PCR_FIA_L14O (BIT27 | BIT26 | BIT25 | BIT24)
+#define B_PCH_PCR_FIA_L15O (BIT31 | BIT30 | BIT29 | BIT28)
+#define B_PCH_PCR_FIA_L16O (BIT3 | BIT2 | BIT1 | BIT0)
+#define B_PCH_PCR_FIA_L17O (BIT7 | BIT6 | BIT5 | BIT4)
+#define B_PCH_PCR_FIA_L18O (BIT11 | BIT10 | BIT9 | BIT8)
+#define B_PCH_PCR_FIA_L19O (BIT15 | BIT14 | BIT13 | BIT12)
+#define B_PCH_PCR_FIA_L20O (BIT19 | BIT18 | BIT17 | BIT16)
+#define B_PCH_PCR_FIA_L21O (BIT23 | BIT22 | BIT21 | BIT20)
+#define B_PCH_PCR_FIA_L22O (BIT27 | BIT26 | BIT25 | BIT24)
+#define B_PCH_PCR_FIA_L23O (BIT31 | BIT30 | BIT29 | BIT28)
+#define B_PCH_PCR_FIA_L24O (BIT3 | BIT2 | BIT1 | BIT0)
+#define B_PCH_PCR_FIA_L25O (BIT7 | BIT6 | BIT5 | BIT4)
+#define B_PCH_PCR_FIA_L26O (BIT11 | BIT10 | BIT9 | BIT8)
+#define B_PCH_PCR_FIA_L27O (BIT15 | BIT14 | BIT13 | BIT12)
+#define B_PCH_PCR_FIA_L28O (BIT19 | BIT18 | BIT17 | BIT16)
+#define B_PCH_PCR_FIA_L29O (BIT23 | BIT22 | BIT21 | BIT20)
+#define PCH_H_FIA_DMILANE_START 14
+#define PCH_H_FIA_DMILANE_END 17
+#define PCH_FIA_MAX_LANES 34
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsGpio.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsGpio.h
new file mode 100644
index 0000000000..a6b2c4a8e5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsGpio.h
@@ -0,0 +1,529 @@
+/** @file
+ Register names for PCH GPIO
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_GPIO_H_
+#define _PCH_REGS_GPIO_H_
+
+#define V_PCH_GPIO_GPP_A_PAD_MAX 24
+#define V_PCH_GPIO_GPP_B_PAD_MAX 24
+#define V_PCH_GPIO_GPP_C_PAD_MAX 24
+#define V_PCH_GPIO_GPP_D_PAD_MAX 24
+#define V_PCH_GPIO_GPP_E_PAD_MAX V_PCH_LP_GPIO_GPP_E_PAD_MAX
+#define V_PCH_LP_GPIO_GPP_E_PAD_MAX 24
+#define V_PCH_H_GPIO_GPP_E_PAD_MAX 13
+#define V_PCH_GPIO_GPP_F_PAD_MAX 24
+#define V_PCH_GPIO_GPP_G_PAD_MAX V_PCH_H_GPIO_GPP_G_PAD_MAX
+#define V_PCH_LP_GPIO_GPP_G_PAD_MAX 8
+#define V_PCH_H_GPIO_GPP_G_PAD_MAX 24
+#define V_PCH_H_GPIO_GPP_H_PAD_MAX 24
+#define V_PCH_H_GPIO_GPP_I_PAD_MAX 11
+#define V_PCH_GPIO_GPD_PAD_MAX 12
+
+#define V_PCH_GPIO_GROUP_MAX 10
+#define V_PCH_H_GPIO_GROUP_MAX 10
+#define V_PCH_LP_GPIO_GROUP_MAX 8
+#define V_PCH_GPIO_NUM_SUPPORTED_GPIS 204
+#define S_PCH_GPIO_GP_SMI_EN 4
+#define S_PCH_GPIO_GP_SMI_STS 4
+
+///
+/// Groups mapped to 2-tier General Purpose Event will all be under
+/// one master GPE_111 (0x6F)
+///
+#define PCH_GPIO_2_TIER_MASTER_GPE_NUMBER 0x6F
+
+
+//
+// GPIO Common Private Configuration Registers
+//
+#define R_PCH_PCR_GPIO_REV_ID 0x00
+#define R_PCH_PCR_GPIO_CAP_LIST 0x04
+#define R_PCH_PCR_GPIO_FAMBAR 0x08
+#define R_PCH_PCR_GPIO_PADBAR 0x0C
+#define B_PCH_PCR_GPIO_PADBAR 0x0000FFFF
+#define R_PCH_PCR_GPIO_MISCCFG 0x10
+#define B_PCH_PCR_GPIO_MISCCFG_GPE0_DW2 (BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_PCR_GPIO_MISCCFG_GPE0_DW2 16
+#define B_PCH_PCR_GPIO_MISCCFG_GPE0_DW1 (BIT15 | BIT14 | BIT13 | BIT12)
+#define N_PCH_PCR_GPIO_MISCCFG_GPE0_DW1 12
+#define B_PCH_PCR_GPIO_MISCCFG_GPE0_DW0 (BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_PCR_GPIO_MISCCFG_GPE0_DW0 8
+#define B_PCH_PCR_GPIO_MISCCFG_IRQ_ROUTE BIT3
+#define N_PCH_PCR_GPIO_MISCCFG_IRQ_ROUTE 3
+#define B_PCH_PCR_GPIO_MISCCFG_GPDPCGEN BIT1
+#define B_PCH_PCR_GPIO_MISCCFG_GPDLCGEN BIT0
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_MISCSECCFG 0x14
+
+//
+// GPIO Community 0 Private Configuration Registers
+//
+// SKL PCH-LP
+#define R_PCH_LP_PCR_GPIO_GPP_A_PAD_OWN 0x20
+#define R_PCH_LP_PCR_GPIO_GPP_B_PAD_OWN 0x30
+#define R_PCH_LP_PCR_GPIO_GPP_A_GPI_VWM_EN 0x80
+#define R_PCH_LP_PCR_GPIO_GPP_B_GPI_VWM_EN 0x84
+#define R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCK 0xA0
+#define R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCKTX 0xA4
+#define R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCK 0xA8
+#define R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCKTX 0xAC
+// SKL PCH-H
+#define R_PCH_H_PCR_GPIO_GPP_A_PAD_OWN 0x20
+#define R_PCH_H_PCR_GPIO_GPP_B_PAD_OWN 0x2C
+#define R_PCH_H_PCR_GPIO_GPP_A_GPI_VWM_EN 0x70
+#define R_PCH_H_PCR_GPIO_GPP_B_GPI_VWM_EN 0x74
+#define R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCK 0x90
+#define R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCKTX 0x94
+#define R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCK 0x98
+#define R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCKTX 0x9C
+// Common
+#define R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN 0xD0
+#define R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN 0xD4
+#define R_PCH_PCR_GPIO_GPP_A_GPI_IS 0x0100
+#define R_PCH_PCR_GPIO_GPP_B_GPI_IS 0x0104
+#define R_PCH_PCR_GPIO_GPP_A_GPI_IE 0x0120
+#define R_PCH_PCR_GPIO_GPP_B_GPI_IE 0x0124
+#define R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS 0x0140
+#define R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS 0x0144
+#define R_PCH_PCR_GPIO_GPP_A_GPI_GPE_EN 0x0160
+#define R_PCH_PCR_GPIO_GPP_B_GPI_GPE_EN 0x0164
+#define R_PCH_PCR_GPIO_GPP_A_SMI_STS 0x0180
+#define R_PCH_PCR_GPIO_GPP_B_SMI_STS 0x0184
+#define R_PCH_PCR_GPIO_GPP_A_SMI_EN 0x01A0
+#define R_PCH_PCR_GPIO_GPP_B_SMI_EN 0x01A4
+#define R_PCH_PCR_GPIO_GPP_A_NMI_STS 0x01C0
+#define R_PCH_PCR_GPIO_GPP_B_NMI_STS 0x01C4
+#define R_PCH_PCR_GPIO_GPP_A_NMI_EN 0x01E0
+#define R_PCH_PCR_GPIO_GPP_B_NMI_EN 0x01E4
+#define R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET 0x400
+#define R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET 0x4C0
+
+//
+// GPIO Community 1 Private Configuration Registers
+//
+//SKL PCH-LP:
+#define R_PCH_LP_PCR_GPIO_GPP_C_PAD_OWN 0x20
+#define R_PCH_LP_PCR_GPIO_GPP_D_PAD_OWN 0x30
+#define R_PCH_LP_PCR_GPIO_GPP_E_PAD_OWN 0x40
+#define R_PCH_LP_PCR_GPIO_GPP_C_GPI_VWM_EN 0x80
+#define R_PCH_LP_PCR_GPIO_GPP_D_GPI_VWM_EN 0x84
+#define R_PCH_LP_PCR_GPIO_GPP_E_GPI_VWM_EN 0x88
+#define R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCK 0xA0
+#define R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCKTX 0xA4
+#define R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCK 0xA8
+#define R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCKTX 0xAC
+#define R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCK 0xB0
+#define R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCKTX 0xB4
+//SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_C_PAD_OWN 0x20
+#define R_PCH_H_PCR_GPIO_GPP_D_PAD_OWN 0x2C
+#define R_PCH_H_PCR_GPIO_GPP_E_PAD_OWN 0x38
+#define R_PCH_H_PCR_GPIO_GPP_F_PAD_OWN 0x40
+#define R_PCH_H_PCR_GPIO_GPP_G_PAD_OWN 0x4C
+#define R_PCH_H_PCR_GPIO_GPP_H_PAD_OWN 0x58
+#define R_PCH_H_PCR_GPIO_GPP_C_GPI_VWM_EN 0x70
+#define R_PCH_H_PCR_GPIO_GPP_D_GPI_VWM_EN 0x74
+#define R_PCH_H_PCR_GPIO_GPP_E_GPI_VWM_EN 0x78
+#define R_PCH_H_PCR_GPIO_GPP_F_GPI_VWM_EN 0x7C
+#define R_PCH_H_PCR_GPIO_GPP_G_GPI_VWM_EN 0x80
+#define R_PCH_H_PCR_GPIO_GPP_H_GPI_VWM_EN 0x84
+#define R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCK 0x90
+#define R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCKTX 0x94
+#define R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCK 0x98
+#define R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCKTX 0x9C
+#define R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCK 0xA0
+#define R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCKTX 0xA4
+#define R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCK 0xA8
+#define R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCKTX 0xAC
+#define R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCK 0xB0
+#define R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCKTX 0xB4
+#define R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCK 0xB8
+#define R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCKTX 0xBC
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN 0xD0
+#define R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN 0xD4
+#define R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN 0xD8
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_HOSTSW_OWN 0xDC
+#define R_PCH_H_PCR_GPIO_GPP_G_HOSTSW_OWN 0xE0
+#define R_PCH_H_PCR_GPIO_GPP_H_HOSTSW_OWN 0xE4
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_GPI_IS 0x0100
+#define R_PCH_PCR_GPIO_GPP_D_GPI_IS 0x0104
+#define R_PCH_PCR_GPIO_GPP_E_GPI_IS 0x0108
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_GPI_IS 0x010C
+#define R_PCH_H_PCR_GPIO_GPP_G_GPI_IS 0x0110
+#define R_PCH_H_PCR_GPIO_GPP_H_GPI_IS 0x0114
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_GPI_IE 0x0120
+#define R_PCH_PCR_GPIO_GPP_D_GPI_IE 0x0124
+#define R_PCH_PCR_GPIO_GPP_E_GPI_IE 0x0128
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_GPI_IE 0x012C
+#define R_PCH_H_PCR_GPIO_GPP_G_GPI_IE 0x0130
+#define R_PCH_H_PCR_GPIO_GPP_H_GPI_IE 0x0134
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS 0x0140
+#define R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS 0x0144
+#define R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS 0x0148
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_STS 0x014C
+#define R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_STS 0x0150
+#define R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_STS 0x0154
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_GPI_GPE_EN 0x0160
+#define R_PCH_PCR_GPIO_GPP_D_GPI_GPE_EN 0x0164
+#define R_PCH_PCR_GPIO_GPP_E_GPI_GPE_EN 0x0168
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_EN 0x016C
+#define R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_EN 0x0170
+#define R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_EN 0x0174
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_SMI_STS 0x0180
+#define R_PCH_PCR_GPIO_GPP_D_SMI_STS 0x0184
+#define R_PCH_PCR_GPIO_GPP_E_SMI_STS 0x0188
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_SMI_STS 0x018C
+#define R_PCH_H_PCR_GPIO_GPP_G_SMI_STS 0x0190
+#define R_PCH_H_PCR_GPIO_GPP_H_SMI_STS 0x0194
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_SMI_EN 0x01A0
+#define R_PCH_PCR_GPIO_GPP_D_SMI_EN 0x01A4
+#define R_PCH_PCR_GPIO_GPP_E_SMI_EN 0x01A8
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_SMI_EN 0x01AC
+#define R_PCH_H_PCR_GPIO_GPP_G_SMI_EN 0x01B0
+#define R_PCH_H_PCR_GPIO_GPP_H_SMI_EN 0x01B4
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_NMI_STS 0x01C0
+#define R_PCH_PCR_GPIO_GPP_D_NMI_STS 0x01C4
+#define R_PCH_PCR_GPIO_GPP_E_NMI_STS 0x01C8
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_NMI_STS 0x01CC
+#define R_PCH_H_PCR_GPIO_GPP_G_NMI_STS 0x01D0
+#define R_PCH_H_PCR_GPIO_GPP_H_NMI_STS 0x01D4
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_NMI_EN 0x01E0
+#define R_PCH_PCR_GPIO_GPP_D_NMI_EN 0x01E4
+#define R_PCH_PCR_GPIO_GPP_E_NMI_EN 0x01E8
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_NMI_EN 0x01EC
+#define R_PCH_H_PCR_GPIO_GPP_G_NMI_EN 0x01F0
+#define R_PCH_H_PCR_GPIO_GPP_H_NMI_EN 0x01F4
+// Common:
+#define R_PCH_PCR_GPIO_CAP_LIST_1_PWM 0x0200
+#define R_PCH_PCR_GPIO_PWMC 0x0204
+#define R_PCH_PCR_GPIO_CAP_LIST_2_SER_BLINK 0x0208
+#define R_PCH_PCR_GPIO_GP_SER_BLINK 0x020C
+#define B_PCH_PCR_GPIO_GP_SER_BLINK 0x1F
+#define R_PCH_PCR_GPIO_GP_SER_CMDSTS 0x0210
+#define B_PCH_PCR_GPIO_GP_SER_CMDSTS_DLS (BIT23 | BIT22)
+#define N_PCH_PCR_GPIO_GP_SER_CMDSTS_DLS 22
+#define B_PCH_PCR_GPIO_GP_SER_CMDSTS_DRS 0x003F0000
+#define N_PCH_PCR_GPIO_GP_SER_CMDSTS_DRS 16
+#define B_PCH_PCR_GPIO_GP_SER_CMDSTS_BUSY BIT8
+#define B_PCH_PCR_GPIO_GP_SER_CMDSTS_GO BIT0
+#define R_PCH_PCR_GPIO_GP_SER_DATA 0x0210
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GSX 0x218
+#define R_PCH_H_PCR_GPIO_GSX_CAP 0x21C
+#define R_PCH_H_PCR_GPIO_GSX_C0CAP_DW0 0x220
+#define R_PCH_H_PCR_GPIO_GSX_C0CAP_DW1 0x224
+#define R_PCH_H_PCR_GPIO_GSX_C0GPILVL_DW0 0x228
+#define R_PCH_H_PCR_GPIO_GSX_C0GPILVL_DW1 0x22C
+#define R_PCH_H_PCR_GPIO_GSX_C0GPOLVL_DW0 0x230
+#define R_PCH_H_PCR_GPIO_GSX_C0GPOLVL_DW1 0x234
+#define R_PCH_H_PCR_GPIO_GSX_C0CMD 0x238
+#define R_PCH_H_PCR_GPIO_GSX_C0CTM 0x23C
+// Common:
+#define R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET 0x400
+#define R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET 0x4C0
+#define R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET 0x580
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_F_PADCFG_OFFSET 0x5E8
+#define R_PCH_H_PCR_GPIO_GPP_G_PADCFG_OFFSET 0x6A8
+#define R_PCH_H_PCR_GPIO_GPP_H_PADCFG_OFFSET 0x768
+
+//
+// GPIO Community 2 Private Configuration Registers
+//
+// SKL PCH-LP
+#define R_PCH_LP_PCR_GPIO_GPD_PAD_OWN 0x20
+#define R_PCH_LP_PCR_GPIO_GPD_GPI_VWM_EN 0x80
+#define R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCK 0xA0
+#define R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCKTX 0xA4
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPD_PAD_OWN 0x20
+#define R_PCH_H_PCR_GPIO_GPD_GPI_VWM_EN 0x70
+#define R_PCH_H_PCR_GPIO_GPD_PADCFGLOCK 0x90
+#define R_PCH_H_PCR_GPIO_GPD_PADCFGLOCKTX 0x94
+// Common:
+#define R_PCH_PCR_GPIO_GPD_HOSTSW_OWN 0xD0
+#define R_PCH_PCR_GPIO_GPD_GPI_IS 0x0100
+#define R_PCH_PCR_GPIO_GPD_GPI_IE 0x0120
+#define R_PCH_PCR_GPIO_GPD_GPI_GPE_STS 0x0140
+#define R_PCH_PCR_GPIO_GPD_GPI_GPE_EN 0x0160
+#define R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET 0x400
+//
+// GPIO Community 3 Private Configuration Registers
+//
+// SKL PCH-LP:
+#define R_PCH_LP_PCR_GPIO_GPP_F_PAD_OWN 0x20
+#define R_PCH_LP_PCR_GPIO_GPP_G_PAD_OWN 0x30
+#define R_PCH_LP_PCR_GPIO_GPP_F_GPI_VWM_EN 0x80
+#define R_PCH_LP_PCR_GPIO_GPP_G_GPI_VWM_EN 0x84
+#define R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCK 0xA0
+#define R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCKTX 0xA4
+#define R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCK 0xA8
+#define R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCKTX 0xAC
+#define R_PCH_LP_PCR_GPIO_GPP_F_HOSTSW_OWN 0xD0
+#define R_PCH_LP_PCR_GPIO_GPP_G_HOSTSW_OWN 0xD4
+#define R_PCH_LP_PCR_GPIO_GPP_F_GPI_IS 0x0100
+#define R_PCH_LP_PCR_GPIO_GPP_G_GPI_IS 0x0104
+#define R_PCH_LP_PCR_GPIO_GPP_F_GPI_IE 0x0120
+#define R_PCH_LP_PCR_GPIO_GPP_G_GPI_IE 0x0124
+#define R_PCH_LP_PCR_GPIO_GPP_F_GPI_GPE_STS 0x0140
+#define R_PCH_LP_PCR_GPIO_GPP_G_GPI_GPE_STS 0x0144
+#define R_PCH_LP_PCR_GPIO_GPP_F_GPI_GPE_EN 0x0160
+#define R_PCH_LP_PCR_GPIO_GPP_G_GPI_GPE_EN 0x0164
+#define R_PCH_LP_PCR_GPIO_GPP_F_PADCFG_OFFSET 0x400
+#define R_PCH_LP_PCR_GPIO_GPP_G_PADCFG_OFFSET 0x4C0
+// SKL PCH-H:
+#define R_PCH_H_PCR_GPIO_GPP_I_PAD_OWN 0x20
+#define R_PCH_H_PCR_GPIO_GPP_I_GPI_VWM_EN 0x70
+#define R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCK 0x90
+#define R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCKTX 0x94
+#define R_PCH_H_PCR_GPIO_GPP_I_HOSTSW_OWN 0xD0
+#define R_PCH_H_PCR_GPIO_GPP_I_GPI_IS 0x0100
+#define R_PCH_H_PCR_GPIO_GPP_I_GPI_IE 0x0120
+#define R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_STS 0x0140
+#define R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_EN 0x0160
+#define R_PCH_H_PCR_GPIO_GPP_I_SMI_STS 0x0180
+#define R_PCH_H_PCR_GPIO_GPP_I_SMI_EN 0x01A0
+#define R_PCH_H_PCR_GPIO_GPP_I_NMI_STS 0x01C0
+#define R_PCH_H_PCR_GPIO_GPP_I_NMI_EN 0x01E0
+#define R_PCH_H_PCR_GPIO_GPP_I_PADCFG_OFFSET 0x400
+
+//
+// Define Pad Number
+//
+#define V_GPIO_PAD0 0
+#define V_GPIO_PAD1 1
+#define V_GPIO_PAD2 2
+#define V_GPIO_PAD3 3
+#define V_GPIO_PAD4 4
+#define V_GPIO_PAD5 5
+#define V_GPIO_PAD6 6
+#define V_GPIO_PAD7 7
+#define V_GPIO_PAD8 8
+#define V_GPIO_PAD9 9
+#define V_GPIO_PAD10 10
+#define V_GPIO_PAD11 11
+#define V_GPIO_PAD12 12
+#define V_GPIO_PAD13 13
+#define V_GPIO_PAD14 14
+#define V_GPIO_PAD15 15
+#define V_GPIO_PAD16 16
+#define V_GPIO_PAD17 17
+#define V_GPIO_PAD18 18
+#define V_GPIO_PAD19 19
+#define V_GPIO_PAD20 20
+#define V_GPIO_PAD21 21
+#define V_GPIO_PAD22 22
+#define V_GPIO_PAD23 23
+
+//
+// Host Software Pad Ownership modes
+//
+#define V_PCH_PCR_GPIO_HOSTSW_OWN_ACPI 0x00
+#define V_PCH_PCR_GPIO_HOSTSW_OWN_GPIO 0x01
+
+//
+// Pad Ownership modes
+//
+#define V_PCH_PCR_GPIO_PAD_OWN_HOST 0x00
+#define V_PCH_PCR_GPIO_PAD_OWN_CSME 0x01
+#define V_PCH_PCR_GPIO_PAD_OWN_ISH 0x02
+
+//
+// Pad Configuration Register DW0
+//
+
+//Pad Reset Config
+#define B_PCH_GPIO_RST_CONF (BIT31 | BIT30)
+#define N_PCH_GPIO_RST_CONF 30
+#define V_PCH_GPIO_RST_CONF_POW_GOOD 0x00
+#define V_PCH_GPIO_RST_CONF_DEEP_RST 0x01
+#define V_PCH_GPIO_RST_CONF_GPIO_RST 0x02
+#define V_PCH_GPIO_RST_CONF_RESUME_RST 0x03 // Only for GPD Group
+
+//RX Pad State Select
+#define B_PCH_GPIO_RX_PAD_STATE BIT29
+#define N_PCH_GPIO_RX_PAD_STATE 29
+#define V_PCH_GPIO_RX_PAD_STATE_RAW 0x00
+#define V_PCH_GPIO_RX_PAD_STATE_INT 0x01
+
+//RX Raw Overrride to 1
+#define B_PCH_GPIO_RX_RAW1 BIT28
+#define N_PCH_GPIO_RX_RAW1 28
+#define V_PCH_GPIO_RX_RAW1_DIS 0x00
+#define V_PCH_GPIO_RX_RAW1_EN 0x01
+
+//RX Level/Edge Configuration
+#define B_PCH_GPIO_RX_LVL_EDG (BIT26 | BIT25)
+#define N_PCH_GPIO_RX_LVL_EDG 25
+#define V_PCH_GPIO_RX_LVL_EDG_LVL 0x00
+#define V_PCH_GPIO_RX_LVL_EDG_EDG 0x01
+#define V_PCH_GPIO_RX_LVL_EDG_0 0x02
+#define V_PCH_GPIO_RX_LVL_EDG_RIS_FAL 0x03
+
+//RX Invert
+#define B_PCH_GPIO_RXINV BIT23
+#define N_PCH_GPIO_RXINV 23
+#define V_PCH_GPIO_RXINV_NO 0x00
+#define V_PCH_GPIO_RXINV_YES 0x01
+
+//GPIO Input Route IOxAPIC
+#define B_PCH_GPIO_RX_APIC_ROUTE BIT20
+#define N_PCH_GPIO_RX_APIC_ROUTE 20
+#define V_PCH_GPIO_RX_APIC_ROUTE_DIS 0x00
+#define V_PCH_GPIO_RX_APIC_ROUTE_EN 0x01
+
+//GPIO Input Route SCI
+#define B_PCH_GPIO_RX_SCI_ROUTE BIT19
+#define N_PCH_GPIO_RX_SCI_ROUTE 19
+#define V_PCH_GPIO_RX_SCI_ROUTE_DIS 0x00
+#define V_PCH_GPIO_RX_SCI_ROUTE_EN 0x01
+
+//GPIO Input Route SMI
+#define B_PCH_GPIO_RX_SMI_ROUTE BIT18
+#define N_PCH_GPIO_RX_SMI_ROUTE 18
+#define V_PCH_GPIO_RX_SMI_ROUTE_DIS 0x00
+#define V_PCH_GPIO_RX_SMI_ROUTE_EN 0x01
+
+//GPIO Input Route NMI
+#define B_PCH_GPIO_RX_NMI_ROUTE BIT17
+#define N_PCH_GPIO_RX_NMI_ROUTE 17
+#define V_PCH_GPIO_RX_NMI_ROUTE_DIS 0x00
+#define V_PCH_GPIO_RX_NMI_ROUTE_EN 0x01
+
+//GPIO Pad Mode
+#define B_PCH_GPIO_PAD_MODE (BIT12 | BIT11 | BIT10)
+#define N_PCH_GPIO_PAD_MODE 10
+#define V_PCH_GPIO_PAD_MODE_GPIO 0
+#define V_PCH_GPIO_PAD_MODE_NAT_1 1
+#define V_PCH_GPIO_PAD_MODE_NAT_2 2
+#define V_PCH_GPIO_PAD_MODE_NAT_3 3
+#define V_PCH_GPIO_PAD_MODE_NAT_4 4 // SPT-H only
+
+//GPIO RX Disable
+#define B_PCH_GPIO_RXDIS BIT9
+#define N_PCH_GPIO_RXDIS 9
+#define V_PCH_GPIO_RXDIS_EN 0x00
+#define V_PCH_GPIO_RXDIS_DIS 0x01
+
+//GPIO TX Disable
+#define B_PCH_GPIO_TXDIS BIT8
+#define N_PCH_GPIO_TXDIS 8
+#define V_PCH_GPIO_TXDIS_EN 0x00
+#define V_PCH_GPIO_TXDIS_DIS 0x01
+
+//GPIO RX State
+#define B_PCH_GPIO_RX_STATE BIT1
+#define N_PCH_GPIO_RX_STATE 1
+#define V_PCH_GPIO_RX_STATE_LOW 0x00
+#define V_PCH_GPIO_RX_STATE_HIGH 0x01
+
+//GPIO TX State
+#define B_PCH_GPIO_TX_STATE BIT0
+#define N_PCH_GPIO_TX_STATE 0
+#define V_PCH_GPIO_TX_STATE_LOW 0x00
+#define V_PCH_GPIO_TX_STATE_HIGH 0x01
+
+//
+// Pad Configuration Register DW1
+//
+
+//Padtol
+#define B_PCH_GPIO_PADTOL BIT25
+#define N_PCH_GPIO_PADTOL 25
+#define V_PCH_GPIO_PADTOL_NONE 0x00
+#define V_PCH_GPIO_PADTOL_CLEAR 0x00
+#define V_PCH_GPIO_PADTOL_SET 0x01
+
+//Termination
+#define B_PCH_GPIO_TERM (BIT13 | BIT12 | BIT11 | BIT10)
+#define N_PCH_GPIO_TERM 10
+#define V_PCH_GPIO_TERM_WPD_NONE 0x00
+#define V_PCH_GPIO_TERM_WPD_5K 0x02
+#define V_PCH_GPIO_TERM_WPD_20K 0x04
+#define V_PCH_GPIO_TERM_WPU_NONE 0x08
+#define V_PCH_GPIO_TERM_WPU_1K 0x09
+#define V_PCH_GPIO_TERM_WPU_2K 0x0B
+#define V_PCH_GPIO_TERM_WPU_5K 0x0A
+#define V_PCH_GPIO_TERM_WPU_20K 0x0C
+#define V_PCH_GPIO_TERM_WPU_1K_2K 0x0D
+#define V_PCH_GPIO_TERM_NATIVE 0x0F
+
+//Interrupt number
+#define B_PCH_GPIO_INTSEL 0x7F
+#define N_PCH_GPIO_INTSEL 0
+
+//
+// Ownership
+//
+#define V_PCH_GPIO_OWN_GPIO 0x01
+#define V_PCH_GPIO_OWN_ACPI 0x00
+
+//
+// GPE
+//
+#define V_PCH_GPIO_GPE_EN 0x01
+#define V_PCH_GPIO_GPE_DIS 0x00
+//
+// SMI
+//
+#define V_PCH_GPIO_SMI_EN 0x01
+#define V_PCH_GPIO_SMI_DIS 0x00
+//
+// NMI
+//
+#define V_PCH_GPIO_NMI_EN 0x01
+#define V_PCH_GPIO_NMI_DIS 0x00
+//
+// Reserved: RSVD1
+//
+#define V_PCH_GPIO_RSVD1 0x00
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHda.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHda.h
new file mode 100644
index 0000000000..1d5c0e9e76
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHda.h
@@ -0,0 +1,201 @@
+/** @file
+ Register names for PCH High Definition Audio device.
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_HDA_H_
+#define _PCH_REGS_HDA_H_
+
+//
+// HD-A Controller Registers (D31:F3)
+//
+// PCI Configuration Space Registers
+//
+#define PCI_DEVICE_NUMBER_PCH_HDA 31
+#define PCI_FUNCTION_NUMBER_PCH_HDA 3
+
+#define R_PCH_HDA_PI 0x09
+#define V_PCH_HDA_PI_ADSP_UAA 0x80
+#define R_PCH_HDA_SCC 0x0A
+#define V_PCH_HDA_SCC_ADSP 0x01
+#define R_PCH_HDA_HDALBA 0x10
+#define B_PCH_HDA_HDALBA_LBA 0xFFFFC000
+#define V_PCH_HDA_HDBAR_SIZE (1 << 14)
+#define R_PCH_HDA_HDAUBA 0x14
+#define B_PCH_HDA_HDAUBA_UBA 0xFFFFFFFF
+#define R_PCH_HDA_CGCTL 0x48
+#define B_PCH_HDA_CGCTL_SROTCGE BIT18
+#define B_PCH_HDA_CGCTL_MISCBDCGE BIT6
+#define R_PCH_HDA_PC 0x52
+#define V_PCH_HDA_PC_PMES 0x18
+#define N_PCH_HDA_PC_PMES 11
+#define R_PCH_HDA_PCS 0x54
+#define B_PCH_HDA_PCS_PMEE BIT8
+#define B_PCH_HDA_PCS_PS (BIT1 | BIT0)
+#define R_PCH_HDA_MMC 0x62
+#define B_PCH_HDA_MMC_ME BIT0
+#define R_PCH_HDA_DEVC 0x78
+#define B_PCH_HDA_DEVC_NSNPEN BIT11
+#define R_PCH_HDA_SEM1 0xC0
+#define B_PCH_HDA_SEM1_LFLCS BIT24
+#define B_PCH_HDA_SEM1_BLKC3DIS BIT17
+#define B_PCH_HDA_SEM1_TMODE BIT12
+#define B_PCH_HDA_SEM1_FIFORDYSEL (BIT10 | BIT9)
+#define R_PCH_HDA_SEM2 0xC4
+#define B_PCH_HDA_SEM2_BSMT (BIT27 | BIT26)
+#define V_PCH_HDA_SEM2_BSMT 0x1
+#define N_PCH_HDA_SEM2_BSMT 26
+#define B_PCH_HDA_SEM2_VC0PSNR BIT24
+#define B_PCH_HDA_SEM2_DUM BIT23
+#define R_PCH_HDA_SEM3L 0xC8
+#define B_PCH_HDA_SEM3L_ISL1EXT2 (BIT21 | BIT20)
+#define V_PCH_HDA_SEM3L_ISL1EXT2 0x2
+#define N_PCH_HDA_SEM3L_ISL1EXT2 20
+#define R_PCH_HDA_SEM4L 0xD0
+#define B_PCH_HDA_SEM4L_OSL1EXT2 (BIT21 | BIT20)
+#define V_PCH_HDA_SEM4L_OSL1EXT2 0x3
+#define N_PCH_HDA_SEM4L_OSL1EXT2 20
+
+//
+// Memory Space Registers
+//
+//
+// Resides in 'HD Audio Global Registers' (0000h)
+//
+#define R_PCH_HDABA_GCAP 0x00
+#define R_PCH_HDABA_GCTL 0x08
+#define B_PCH_HDABA_GCTL_CRST BIT0
+
+#define R_PCH_HDABA_OUTPAY 0x04
+#define R_PCH_HDABA_INPAY 0x06
+#define V_PCH_HDABA_INPAY_DEFAULT 0x1C
+
+#define R_PCH_HDABA_WAKEEN 0x0C
+#define B_PCH_HDABA_WAKEEN_SDI_3 BIT3
+#define B_PCH_HDABA_WAKEEN_SDI_2 BIT2
+#define B_PCH_HDABA_WAKEEN_SDI_1 BIT1
+#define B_PCH_HDABA_WAKEEN_SDI_0 BIT0
+
+#define R_PCH_HDABA_WAKESTS 0x0E
+#define B_PCH_HDABA_WAKESTS_SDIN3 BIT3
+#define B_PCH_HDABA_WAKESTS_SDIN2 BIT2
+#define B_PCH_HDABA_WAKESTS_SDIN1 BIT1
+#define B_PCH_HDABA_WAKESTS_SDIN0 BIT0
+
+//
+// Resides in 'HD Audio Controller Registers' (0030h)
+//
+#define R_PCH_HDABA_IC 0x60
+#define R_PCH_HDABA_IR 0x64
+#define R_PCH_HDABA_ICS 0x68
+#define B_PCH_HDABA_ICS_IRV BIT1
+#define B_PCH_HDABA_ICS_ICB BIT0
+
+//
+// Resides in 'HD Audio Processing Pipe Capability Structure' (0800h)
+//
+#define R_PCH_HDABA_PPC 0x0800 // Processing Pipe Capability Structure (Memory Space, offset 0800h)
+#define R_PCH_HDABA_PPCTL (R_PCH_HDABA_PPC + 0x04)
+#define B_PCH_HDABA_PPCTL_GPROCEN BIT30
+
+//
+// Resides in 'HD Audio Multiple Links Capability Structure' (0C00h)
+//
+#define V_PCH_HDA_HDALINK_INDEX 0
+#define V_PCH_HDA_IDISPLINK_INDEX 1
+
+#define R_PCH_HDABA_MLC 0x0C00 // Multiple Links Capability Structure (Memory Space, offset 0C00h)
+#define R_PCH_HDABA_LCTLX(x) (R_PCH_HDABA_MLC + (0x40 + (0x40 * (x)) + 0x04)) // x - Link index: 0 - HDA Link, 1 - iDisp Link
+#define B_PCH_HDABA_LCTLX_CPA BIT23
+#define B_PCH_HDABA_LCTLX_SPA BIT16
+#define N_PCH_HDABA_LCTLX_SCF 0
+#define V_PCH_HDABA_LCTLX_SCF_6MHZ 0x0
+#define V_PCH_HDABA_LCTLX_SCF_12MHZ 0x1
+#define V_PCH_HDABA_LCTLX_SCF_24MHZ 0x2
+#define V_PCH_HDABA_LCTLX_SCF_48MHZ 0x3
+#define V_PCH_HDABA_LCTLX_SCF_96MHZ 0x4
+
+//
+// Resides in 'HD Audio Vendor Specific Registers' (1000h)
+//
+#define R_PCH_HDABA_LTRC 0x1048
+#define V_PCH_HDABA_LTRC_GB 0x29
+#define N_PCH_HDABA_LTRC_GB 0
+#define R_PCH_HDABA_PCE 0x104B
+#define B_PCH_HDABA_PCE_D3HE BIT2
+
+//
+// Private Configuration Space Registers
+//
+//
+// Resides in IOSF & Fabric Configuration Registers (000h)
+//
+#define R_PCH_PCR_HDA_TTCCFG 0xE4
+#define B_PCH_PCR_HDA_TTCCFG_HCDT BIT1
+
+//
+// Resides in PCI & Codec Configuration Registers (500h)
+//
+#define R_PCH_PCR_HDA_PCICDCCFG 0x500 // PCI & Codec Configuration Registers (PCR, offset 500h)
+#define B_PCH_PCR_HDA_PCICDCCFG_ACPIIN 0x0000FF00
+#define N_PCH_PCR_HDA_PCICDCCFG_ACPIIN 8
+#define R_PCH_PCR_HDA_FNCFG (R_PCH_PCR_HDA_PCICDCCFG + 0x30)
+#define B_PCH_PCR_HDA_FNCFG_PGD BIT5
+#define B_PCH_PCR_HDA_FNCFG_BCLD BIT4
+#define B_PCH_PCR_HDA_FNCFG_CGD BIT3
+#define B_PCH_PCR_HDA_FNCFG_ADSPD BIT2
+#define B_PCH_PCR_HDA_FNCFG_HDASD BIT0
+#define R_PCH_PCR_HDA_CDCCFG (R_PCH_PCR_HDA_PCICDCCFG + 0x34)
+#define B_PCH_PCR_HDA_CDCCFG_DIS_SDIN2 BIT2
+
+//
+// Resides in Power Management & EBB Configuration Registers (600h)
+//
+#define R_PCH_PCR_HDA_PWRMANCFG 0x600 // Power Management & EBB Configuration Registers (PCR, offset 600h)
+#define R_PCH_PCR_HDA_APLLP0 (R_PCH_PCR_HDA_PWRMANCFG + 0x10)
+#define V_PCH_PCR_HDA_APLLP0 0xFC1E0000
+#define R_PCH_PCR_HDA_APLLP1 (R_PCH_PCR_HDA_PWRMANCFG + 0x14)
+#define V_PCH_PCR_HDA_APLLP1 0x00001E00
+#define R_PCH_PCR_HDA_APLLP2 (R_PCH_PCR_HDA_PWRMANCFG + 0x18)
+#define V_PCH_PCR_HDA_APLLP2 0x0000011D
+#define R_PCH_PCR_HDA_IOBCTL (R_PCH_PCR_HDA_PWRMANCFG + 0x1C)
+#define B_PCH_PCR_HDA_IOBCTL_OSEL (BIT9 | BIT8)
+#define V_PCH_PCR_HDA_IOBCTL_OSEL_HDALINK 0
+#define V_PCH_PCR_HDA_IOBCTL_OSEL_HDALINK_I2S 1
+#define V_PCH_PCR_HDA_IOBCTL_OSEL_I2S 3
+#define N_PCH_PCR_HDA_IOBCTL_OSEL 8
+#define B_PCH_PCR_HDA_IOBCTL_VSEL BIT1
+#define R_PCH_PCR_HDA_PTDC (R_PCH_PCR_HDA_PWRMANCFG + 0x28)
+#define B_PCH_PCR_HDA_PTDC_SRMIW (BIT6 | BIT5 | BIT4)
+#define V_PCH_PCR_HDA_PTDC_SRMIW_256XTAL 0x6
+#define N_PCH_PCR_HDA_PTDC_SRMIW 4
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHsio.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHsio.h
new file mode 100644
index 0000000000..faa938e5a5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsHsio.h
@@ -0,0 +1,185 @@
+/** @file
+ Register definition for HSIO
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_HSIO_H_
+#define _PCH_REGS_HSIO_H_
+
+#define B_PCH_HSIO_ACCESS_TYPE (BIT15 | BIT14)
+#define N_PCH_HSIO_ACCESS_TYPE 14
+#define V_PCH_HSIO_ACCESS_TYPE_BDCAST (BIT15 | BIT14)
+#define V_PCH_HSIO_ACCESS_TYPE_MULCAST BIT15
+#define B_PCH_HSIO_LANE_GROUP_NO (BIT13 | BIT12 | BIT11 | BIT10 | BIT9)
+#define B_PCH_HSIO_FUNCTION_NO (BIT8 | BIT7)
+#define N_PCH_HSIO_FUNCTION_NO 7
+#define B_PCH_HSIO_REG_OFFSET (BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+
+#define V_PCH_HSIO_ACCESS_TYPE_BCAST 0x03
+#define V_PCH_HSIO_ACCESS_TYPE_MCAST 0x02
+#define V_PCH_HSIO_ACCESS_TYPE_UCAST 0x00
+
+#define V_PCH_HSIO_LANE_GROUP_NO_CMN_LANE 0x00
+
+#define V_PCH_HSIO_FUNCTION_NO_PCS 0x00
+#define V_PCH_HSIO_FUNCTION_NO_TX 0x01
+#define V_PCH_HSIO_FUNCTION_NO_RX 0x02
+
+#define V_PCH_HSIO_FUNCTION_NO_CMNDIG 0x00
+#define V_PCH_HSIO_FUNCTION_NO_CMNANA 0x01
+#define V_PCH_HSIO_FUNCTION_NO_PLL 0x02
+
+#define R_PCH_HSIO_PCS_DWORD0 0x0
+
+#define R_PCH_HSIO_PCS_DWORD1 0x4
+
+#define R_PCH_HSIO_PCS_DWORD4 0x10
+
+#define R_PCH_HSIO_PCS_DWORD8 0x20
+#define B_PCH_HSIO_PCS_DWORD8_CRI_RXEB_PTR_INIT_4_0 0x1F000000
+#define B_PCH_HSIO_PCS_DWORD8_CRI_RXEB_LOWATER_4_0 0x001F0000
+#define N_PCH_HSIO_PCS_DWORD8_CRI_RXEB_LOWATER_4_0 16
+#define B_PCH_HSIO_PCS_DWORD8_CRI_RXEB_HIWATER_4_0 0x00001F00
+#define N_PCH_HSIO_PCS_DWORD8_CRI_RXEB_HIWATER_4_0 8
+
+#define R_PCH_HSIO_PCS_DWORD9 0x24
+#define B_PCH_HSIO_PCS_DWORD9_REG_ENABLE_PWR_GATING BIT29
+
+#define R_PCH_HSIO_RX_DWORD8 0x120
+#define B_PCH_HSIO_RX_DWORD8_ICFGDFETAP3_EN BIT10
+
+#define R_PCH_HSIO_RX_DWORD9 0x124
+#define B_PCH_HSIO_RX_DWORD9_CFGDFETAP4_OVERRIDE_EN BIT24
+#define B_PCH_HSIO_RX_DWORD9_CFGDFETAP3_OVERRIDE_EN BIT26
+#define B_PCH_HSIO_RX_DWORD9_CFGDFETAP2_OVERRIDE_EN BIT28
+#define B_PCH_HSIO_RX_DWORD9_CFGDFETAP1_OVERRIDE_EN BIT30
+
+#define R_PCH_HSIO_RX_DWORD12 0x130
+#define B_PCH_HSIO_RX_DWORD12_O_CFGEWMARGINSEL BIT14
+
+#define R_PCH_HSIO_RX_DWORD15 0x13C
+
+#define R_PCH_HSIO_RX_DWORD20 0x150
+#define B_PCH_HSIO_RX_DWORD20_ICFGCTLEDATATAP_FULLRATE_5_0 (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24)
+#define N_PCH_HSIO_RX_DWORD20_ICFGCTLEDATATAP_FULLRATE_5_0 24
+
+#define R_PCH_HSIO_RX_DWORD21 0x154
+#define B_PCH_HSIO_RX_DWORD21_ICFGCTLEDATATAP_QUATRATE_5_0 (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_HSIO_RX_DWORD21_ICFGCTLEDATATAP_QUATRATE_5_0 8
+#define B_PCH_HSIO_RX_DWORD21_ICFGCTLEDATATAP_HALFRATE_5_0 (BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+#define N_PCH_HSIO_RX_DWORD21_ICFGCTLEDATATAP_HALFRATE_5_0 0
+
+#define R_PCH_HSIO_RX_DWORD23 0x15C
+#define B_PCH_HSIO_RX_DWORD23_ICFGVGABLWTAP_OVERRIDE_EN BIT2
+#define B_PCH_HSIO_RX_DWORD23_CFGVGATAP_ADAPT_OVERRIDE_EN BIT4
+
+#define R_PCH_HSIO_RX_DWORD25 0x164
+#define B_PCH_HSIO_RX_DWORD25_RX_TAP_CFG_CTRL BIT3
+#define B_PCH_HSIO_RX_DWORD25_CTLE_ADAPT_OFFSET_CFG_4_0 0x1F0000
+#define N_PCH_HSIO_RX_DWORD25_CTLE_ADAPT_OFFSET_CFG_4_0 16
+
+#define R_PCH_HSIO_RX_DWORD26 0x168
+#define B_PCH_HSIO_RX_DWORD26_SATA_EQ_DIS BIT16
+
+#define R_PCH_HSIO_RX_DWORD34 0x188
+#define B_PCH_HSIO_RX_DWORD34_MM_PH_OFC_SCALE_2_0 (BIT14 | BIT13 | BIT12)
+#define N_PCH_HSIO_RX_DWORD34_MM_PH_OFC_SCALE_2_0 12
+
+#define R_PCH_HSIO_RX_DWORD44 0x1B0
+#define B_PCH_HSIO_RX_DWORD44_0_DFE_DATASUMCAL0_7_0 0xFF0000
+#define N_PCH_HSIO_RX_DWORD44_0_DFE_DATASUMCAL0_7_0 16
+
+#define R_PCH_HSIO_RX_DWORD56 0x1E0
+#define B_PCH_HSIO_RX_DWORD56_ICFGPIDACCFGVALID BIT16
+
+#define R_PCH_HSIO_RX_DWORD57 0x1E4
+#define B_PCH_HSIO_RX_DWORD57_JIM_COURSE BIT30
+#define B_PCH_HSIO_RX_DWORD57_JIM_ENABLE BIT29
+#define B_PCH_HSIO_RX_DWORD57_JIMMODE BIT28
+#define B_PCH_HSIO_RX_DWORD57_JIMNUMCYCLES_3_0 0x0F000000
+#define N_PCH_HSIO_RX_DWORD57_JIMNUMCYCLES_3_0 24
+#define B_PCH_HSIO_RX_DWORD57_ICFGMARGINEN BIT0
+
+#define R_PCH_HSIO_RX_DWORD59 0x1EC
+#define R_PCH_HSIO_RX_DWORD60 0x1F0
+
+#define R_PCH_HSIO_TX_DWORD5 0x94
+#define B_PCH_HSIO_TX_DWORD5_OW2TAPGEN2DEEMPH3P5_5_0 (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_HSIO_TX_DWORD5_OW2TAPGEN2DEEMPH3P5_5_0 16
+#define B_PCH_HSIO_TX_DWORD5_OW2TAPGEN1DEEMPH3P5_5_0 (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_HSIO_TX_DWORD5_OW2TAPGEN1DEEMPH3P5_5_0 8
+
+#define R_PCH_HSIO_TX_DWORD6 0x98
+#define B_PCH_HSIO_TX_DWORD6_OW2TAPGEN3DEEMPH6P0_5_0 (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_HSIO_TX_DWORD6_OW2TAPGEN3DEEMPH6P0_5_0 16
+#define B_PCH_HSIO_TX_DWORD6_OW2TAPGEN2DEEMPH6P0_5_0 (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_HSIO_TX_DWORD6_OW2TAPGEN2DEEMPH6P0_5_0 8
+#define B_PCH_HSIO_TX_DWORD6_OW2TAPGEN1DEEMPH6P0_5_0 (BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+
+#define R_PCH_HSIO_TX_DWORD8 0xA0
+#define B_PCH_HSIO_TX_DWORD8_ORATE10MARGIN_5_0 (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24)
+#define N_PCH_HSIO_TX_DWORD8_ORATE10MARGIN_5_0 24
+#define B_PCH_HSIO_TX_DWORD8_ORATE01MARGIN_5_0 (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_HSIO_TX_DWORD8_ORATE01MARGIN_5_0 16
+#define B_PCH_HSIO_TX_DWORD8_ORATE00MARGIN_5_0 (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_HSIO_TX_DWORD8_ORATE00MARGIN_5_0 8
+
+#define R_PCH_HSIO_TX_DWORD19 0xCC
+
+#define R_PCH_HSIO_TX_DWORD23 0xDC
+
+#define R_PCH_LP_HSIO_LANE10_PCS_DWORD8 0x020
+#define R_PCH_LP_HSIO_LANE11_PCS_DWORD8 0x220
+#define R_PCH_LP_HSIO_LANE14_PCS_DWORD8 0x820
+#define R_PCH_LP_HSIO_LANE15_PCS_DWORD8 0xA20
+#define R_PCH_H_HSIO_LANE18_PCS_DWORD8 0x820
+#define R_PCH_H_HSIO_LANE19_PCS_DWORD8 0xA20
+#define R_PCH_H_HSIO_LANE22_PCS_DWORD8 0x020
+#define R_PCH_H_HSIO_LANE23_PCS_DWORD8 0x220
+#define R_PCH_H_HSIO_LANE24_PCS_DWORD8 0x420
+#define R_PCH_H_HSIO_LANE25_PCS_DWORD8 0x620
+#define R_PCH_H_HSIO_LANE26_PCS_DWORD8 0x820
+#define R_PCH_H_HSIO_LANE27_PCS_DWORD8 0xA20
+#define R_PCH_H_HSIO_LANE28_PCS_DWORD8 0xC20
+#define R_PCH_H_HSIO_LANE29_PCS_DWORD8 0xE20
+
+#define R_PCH_HSIO_CLANE0_CMN_ANA_DWORD2 0x8088
+#define B_PCH_HSIO_CLANE0_CMN_ANA_DWORD2_O_DTPLL1_lC_PLLEN_H_OVRDEN BIT5
+#define B_PCH_HSIO_CLANE0_CMN_ANA_DWORD2_O_DTPLL1_lC_FULLCALRESET_L_OVERDEN BIT3
+
+#define R_PCH_HSIO_PLL_SSC_DWORD2 0x8108
+#define B_PCH_HSIO_PLL_SSC_DWORD2_SSCSTEPSIZE_7_0 (BIT23 | BIT22 | BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_HSIO_PLL_SSC_DWORD2_SSCSTEPSIZE_7_0 16
+#define B_PCH_HSIO_PLL_SSC_DWORD2_SSCSEN BIT10
+#define N_PCH_HSIO_PLL_SSC_DWORD2_SSCSEN 10
+
+#define R_PCH_HSIO_PLL_SSC_DWORD3 0x810C
+#define B_PCH_HSIO_PLL_SSC_DWORD3_SSC_PROPAGATE BIT0
+
+#define R_PCH_PCR_MODPHY0_COM0_CMN_DIG_DWORD12 0x8030
+#define B_PCH_PCR_MODPHY0_COM0_CMN_DIG_DWORD12_O_CFG_PWR_GATING_CTRL BIT0
+
+//
+// xHCI SSIC Private Configuration Register, but with opcode 4/5 for read/write access
+//
+#define R_PCH_PCR_MMP0_LANE_0_OFFSET 0x0
+#define R_PCH_PCR_MMP0_LANE_1_OFFSET 0x2000
+#define R_PCH_PCR_MMP0_IMPREG21 0x1050
+#define R_PCH_PCR_MMP0_IMPREG22 0x1054
+#define R_PCH_PCR_MMP0_IMPREG23 0x1058
+#define R_PCH_PCR_MMP0_IMPREG24 0x105C
+#define R_PCH_PCR_MMP0_IMPREG25 0x1060
+#define R_PCH_PCR_MMP0_CMNREG4 0xF00C
+#define R_PCH_PCR_MMP0_CMNREG15 0xF038
+#define R_PCH_PCR_MMP0_CMNREG16 0xF03C
+
+#endif //_PCH_REGS_HSIO_H_
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsIsh.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsIsh.h
new file mode 100644
index 0000000000..687a153f30
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsIsh.h
@@ -0,0 +1,74 @@
+/** @file
+ Register names for PCH Integrated Sensor Hub (ISH3.0)
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_ISH_H_
+#define _PCH_REGS_ISH_H_
+
+//
+// ISH Controller Registers (D19:F0)
+//
+// PCI Configuration Space Registers
+#define PCI_DEVICE_NUMBER_PCH_ISH 19
+#define PCI_FUNCTION_NUMBER_PCH_ISH 0
+
+#define R_PCH_ISH_BAR0_LOW 0x10
+#define R_PCH_ISH_BAR0_HIGH 0x14
+#define V_PCH_ISH_BAR0_SIZE 0x100000
+#define N_PCH_ISH_BAR0_ALIGNMENT 20
+#define R_PCH_ISH_BAR1_LOW 0x18
+#define R_PCH_ISH_BAR1_HIGH 0x1C
+#define V_PCH_ISH_BAR1_SIZE 0x1000
+#define N_PCH_ISH_BAR1_ALIGNMENT 12
+
+//
+// ISH Private Configuration Space Registers (IOSF2OCP)
+// (PID:ISH)
+//
+#define R_PCH_PCR_ISH_PMCTL 0x1D0 ///< Power Management
+#define R_PCH_PCR_ISH_PCICFGCTRL 0x200 ///< PCI Configuration Control
+#define B_PCH_PCR_ISH_PCICFGCTR_PCI_IRQ 0x0FF00000 ///< PCI IRQ number
+#define N_PCH_PCR_ISH_PCICFGCTR_PCI_IRQ 20
+#define B_PCH_PCR_ISH_PCICFGCTR_ACPI_IRQ 0x000FF000 ///< ACPI IRQ number
+#define N_PCH_PCR_ISH_PCICFGCTR_ACPI_IRQ 12
+#define B_PCH_PCR_ISH_PCICFGCTR_IPIN1 (BIT11 | BIT10 | BIT9 | BIT8) ///< Interrupt Pin
+#define N_PCH_PCR_ISH_PCICFGCTR_IPIN1 8
+#define B_PCH_PCR_ISH_PCICFGCTRL_BAR1DIS BIT7 ///< BAR1 Disable
+
+//
+// Number of pins used by ISH controllers
+//
+#define PCH_ISH_PINS_PER_I2C_CONTROLLER 2
+#define PCH_ISH_PINS_PER_UART_CONTROLLER 4
+#define PCH_ISH_PINS_PER_SPI_CONTROLLER 4
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsItss.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsItss.h
new file mode 100644
index 0000000000..21269155b5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsItss.h
@@ -0,0 +1,94 @@
+/** @file
+ Register names for ITSS
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_ITSS_H_
+#define _PCH_REGS_ITSS_H_
+
+//
+// ITSS PCRs (PID:ITSS)
+//
+#define R_PCH_PCR_ITSS_PIRQA_ROUT 0x3100 ///< PIRQA Routing Control register
+#define R_PCH_PCR_ITSS_PIRQB_ROUT 0x3101 ///< PIRQB Routing Control register
+#define R_PCH_PCR_ITSS_PIRQC_ROUT 0x3102 ///< PIRQC Routing Control register
+#define R_PCH_PCR_ITSS_PIRQD_ROUT 0x3103 ///< PIRQD Routing Control register
+#define R_PCH_PCR_ITSS_PIRQE_ROUT 0x3104 ///< PIRQE Routing Control register
+#define R_PCH_PCR_ITSS_PIRQF_ROUT 0x3105 ///< PIRQF Routing Control register
+#define R_PCH_PCR_ITSS_PIRQG_ROUT 0x3106 ///< PIRQG Routing Control register
+#define R_PCH_PCR_ITSS_PIRQH_ROUT 0x3107 ///< PIRQH Routing Control register
+#define B_PCH_PCR_ITSS_PIRQX_ROUT_REN 0x80 ///< Interrupt Routing Enable
+#define B_PCH_PCR_ITSS_PIRQX_ROUT_IR 0x0F ///< IRQ Routng
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_3 0x03 ///< Route PIRQx to IRQ3
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_4 0x04 ///< Route PIRQx to IRQ4
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_5 0x05 ///< Route PIRQx to IRQ5
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_6 0x06 ///< Route PIRQx to IRQ6
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_7 0x07 ///< Route PIRQx to IRQ7
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_9 0x09 ///< Route PIRQx to IRQ9
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_10 0x0A ///< Route PIRQx to IRQ10
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_11 0x0B ///< Route PIRQx to IRQ11
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_12 0x0C ///< Route PIRQx to IRQ12
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_14 0x0E ///< Route PIRQx to IRQ14
+#define V_PCH_PCR_ITSS_PIRQX_ROUT_IRQ_15 0x0F ///< Route PIRQx to IRQ15
+
+#define R_PCH_PCR_ITSS_PIR0 0x3140 ///< PCI Interrupt Route 0
+#define R_PCH_PCR_ITSS_PIR1 0x3142 ///< PCI Interrupt Route 1
+#define R_PCH_PCR_ITSS_PIR2 0x3144 ///< PCI Interrupt Route 2
+#define R_PCH_PCR_ITSS_PIR3 0x3146 ///< PCI Interrupt Route 3
+#define R_PCH_PCR_ITSS_PIR4 0x3148 ///< PCI Interrupt Route 4
+#define R_PCH_PCR_ITSS_PIR5 0x314A ///< PCI Interrupt Route 5
+#define R_PCH_PCR_ITSS_PIR6 0x314C ///< PCI Interrupt Route 6
+#define R_PCH_PCR_ITSS_PIR7 0x314E ///< PCI Interrupt Route 7
+#define R_PCH_PCR_ITSS_PIR8 0x3150 ///< PCI Interrupt Route 8
+#define R_PCH_PCR_ITSS_PIR9 0x3152 ///< PCI Interrupt Route 9
+#define R_PCH_PCR_ITSS_PIR10 0x3154 ///< PCI Interrupt Route 10
+#define R_PCH_PCR_ITSS_PIR11 0x3156 ///< PCI Interrupt Route 11
+#define R_PCH_PCR_ITSS_PIR12 0x3158 ///< PCI Interrupt Route 12
+
+#define R_PCH_PCR_ITSS_GIC 0x31FC ///< General Interrupt Control
+#define B_PCH_PCR_ITSS_GIC_MAX_IRQ_24 BIT9 ///< Max IRQ entry size, 1 = 24 entry size, 0 = 120 entry size
+#define B_PCH_PCR_ITSS_GIC_AME BIT17 ///< Alternate Access Mode Enable
+#define B_PCH_PCR_ITSS_GIC_SPS BIT16 ///< Shutdown Policy Select
+#define R_PCH_PCR_ITSS_IPC0 0x3200 ///< Interrupt Polarity Control 0
+#define R_PCH_PCR_ITSS_IPC1 0x3204 ///< Interrupt Polarity Control 1
+#define R_PCH_PCR_ITSS_IPC2 0x3208 ///< Interrupt Polarity Control 2
+#define R_PCH_PCR_ITSS_IPC3 0x320C ///< Interrupt Polarity Control 3
+#define R_PCH_PCR_ITSS_ITSSPRC 0x3300 ///< ITSS Power Reduction Control
+#define B_PCH_PCR_ITSS_ITSSPRC_PGCBDCGE BIT4 ///< PGCB Dynamic Clock Gating Enable
+#define B_PCH_PCR_ITSS_ITSSPRC_HPETDCGE BIT3 ///< HPET Dynamic Clock Gating Enable
+#define B_PCH_PCR_ITSS_ITSSPRC_8254CGE BIT2 ///< 8254 Static Clock Gating Enable
+#define B_PCH_PCR_ITSS_ITSSPRC_IOSFICGE BIT1 ///< IOSF-Sideband Interface Clock Gating Enable
+#define B_PCH_PCR_ITSS_ITSSPRC_ITSSCGE BIT0 ///< ITSS Clock Gate Enable
+
+#define R_PCH_PCR_ITSS_MMC 0x3334 ///< Master Message Control
+#define B_PCH_PCR_ITSS_MMC_MSTRMSG_EN BIT0 ///< Master Message Enable
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLan.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLan.h
new file mode 100644
index 0000000000..bb4c2c15a9
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLan.h
@@ -0,0 +1,148 @@
+/** @file
+ Register names for PCH LAN device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_LAN_H_
+#define _PCH_REGS_LAN_H_
+
+//
+// Gigabit LAN Controller configuration registers (D31:F6)
+//
+#define PCI_DEVICE_NUMBER_PCH_LAN 31
+#define PCI_FUNCTION_NUMBER_PCH_LAN 6
+
+#define R_PCH_LAN_MBARA 0x10
+#define B_PCH_LAN_MBARA_BA 0xFFFE0000
+#define N_PCH_LAN_MBARA_ALIGN 17
+#define R_PCH_LAN_LTR_CAP 0xA8
+#define R_PCH_LAN_CLIST1 0xC8
+#define B_PCH_LAN_CLIST1_NEXT 0xFF00
+#define B_PCH_LAN_CLIST1_CID 0x00FF
+#define R_PCH_LAN_PMC 0xCA
+#define B_PCH_LAN_PMC_PMES 0xF800
+#define B_PCH_LAN_PMC_D2S BIT10
+#define B_PCH_LAN_PMC_D1S BIT9
+#define B_PCH_LAN_PMC_AC (BIT8 | BIT7 | BIT6)
+#define B_PCH_LAN_PMC_DSI BIT5
+#define B_PCH_LAN_PMC_PMEC BIT3
+#define B_PCH_LAN_PMC_VS (BIT2 | BIT1 | BIT0)
+#define R_PCH_LAN_PMCS 0xCC
+#define B_PCH_LAN_PMCS_PMES BIT15
+#define B_PCH_LAN_PMCS_DSC (BIT14 | BIT13)
+#define B_PCH_LAN_PMCS_DSL 0x1E00
+#define V_PCH_LAN_PMCS_DSL0 0x0000
+#define V_PCH_LAN_PMCS_DSL3 0x0600
+#define V_PCH_LAN_PMCS_DSL4 0x0800
+#define V_PCH_LAN_PMCS_DSL7 0x0E00
+#define V_PCH_LAN_PMCS_DSL8 0x1000
+#define B_PCH_LAN_PMCS_PMEE BIT8
+#define B_PCH_LAN_PMCS_PS (BIT1 | BIT0)
+#define V_PCH_LAN_PMCS_PS0 0x00
+#define V_PCH_LAN_PMCS_PS3 0x03
+#define R_PCH_LAN_DR 0xCF
+#define B_PCH_LAN_DR 0xFF
+#define R_PCH_LAN_CLIST2 0xD0
+#define B_PCH_LAN_CLIST2_NEXT 0xFF00
+#define B_PCH_LAN_CLIST2_CID 0x00FF
+#define R_PCH_LAN_MCTL 0xD2
+#define B_PCH_LAN_MCTL_CID BIT7
+#define B_PCH_LAN_MCTL_MME (BIT6 | BIT5 | BIT4)
+#define B_PCH_LAN_MCTL_MMC (BIT3 | BIT2 | BIT1)
+#define B_PCH_LAN_MCTL_MSIE BIT0
+#define R_PCH_LAN_MADDL 0xD4
+#define B_PCH_LAN_MADDL 0xFFFFFFFF
+#define R_PCH_LAN_MADDH 0xD8
+#define B_PCH_LAN_MADDH 0xFFFFFFFF
+#define R_PCH_LAN_MDAT 0xDC
+#define B_PCH_LAN_MDAT 0xFFFFFFFF
+#define R_PCH_LAN_FLRCAP 0xE0
+#define B_PCH_LAN_FLRCAP_NEXT 0xFF00
+#define B_PCH_LAN_FLRCAP_CID 0x00FF
+#define V_PCH_LAN_FLRCAP_CID_SSEL0 0x13
+#define V_PCH_LAN_FLRCAP_CID_SSEL1 0x09
+#define R_PCH_LAN_FLRCLV 0xE2
+#define B_PCH_LAN_FLRCLV_FLRC_SSEL0 BIT9
+#define B_PCH_LAN_FLRCLV_TXP_SSEL0 BIT8
+#define B_PCH_LAN_FLRCLV_VSCID_SSEL1 0xF000
+#define B_PCH_LAN_FLRCLV_CAPVER_SSEL1 0x0F00
+#define B_PCH_LAN_FLRCLV_CAPLNG 0x00FF
+#define R_PCH_LAN_DEVCTRL 0xE4
+#define B_PCH_LAN_DEVCTRL BIT0
+#define R_PCH_LAN_CPCE 0x80
+#define B_PCH_LAN_CPCE_HAE BIT5
+#define B_PCH_LAN_CPCE_SE BIT3
+#define B_PCH_LAN_CPCE_D3HE BIT2
+#define B_PCH_LAN_CPCE_I3E BIT1
+#define B_PCH_LAN_CPCE_PCMCRE BIT0
+#define R_PCH_LAN_CD0I3 0x84
+#define B_PCH_LAN_CD0I3_RR BIT3
+#define B_PCH_LAN_CD0I3_D0I3 BIT2
+#define R_PCH_LAN_CLCTL 0x94
+#define R_PCH_LAN_LANDISCTRL 0xA0
+#define B_PCH_LAN_LANDISCTRL_DISABLE BIT0
+#define R_PCH_LAN_LOCKLANDIS 0xA4
+#define B_PCH_LAN_LOCKLANDIS_LOCK BIT0
+//
+// Gigabit LAN Capabilities and Status Registers (Memory space)
+//
+#define R_PCH_LAN_CSR_CTRL 0
+#define B_PCH_LAN_CSR_CTRL_MEHE BIT19
+#define R_PCH_LAN_CSR_STRAP 0x000C
+#define B_PCH_LAN_CSR_STRAP_NVM_VALID BIT11
+#define R_PCH_LAN_CSR_FEXTNVM6 0x0010
+#define R_PCH_LAN_CSR_CTRL_EXT 0x0018
+#define B_PCH_LAN_CSR_CTRL_EXT_FORCE_SMB BIT11
+#define R_PCH_LAN_CSR_MDIC 0x0020
+#define B_PCH_LAN_CSR_MDIC_RB BIT28
+#define B_PCH_LAN_CSR_MDIC_DATA 0xFFFF
+#define R_PCH_LAN_CSR_FEXT 0x002C
+#define B_PCH_LAN_CSR_FEXT_WOL BIT30
+#define B_PCH_LAN_CSR_FEXT_WOL_VALID BIT31
+#define R_PCH_LAN_CSR_EXTCNF_CTRL 0x0F00
+#define B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG BIT5
+#define B_PCH_LAN_CSR_EXTCNF_K1OFF_EN BIT8
+#define R_PCH_LAN_CSR_PHY_CTRL 0x0F10
+#define B_PCH_LAN_CSR_PHY_CTRL_GGD BIT6
+#define B_PCH_LAN_CSR_PHY_CTRL_GBEDIS BIT3
+#define B_PCH_LAN_CSR_PHY_CTRL_LPLUND BIT2
+#define B_PCH_LAN_CSR_PHY_CTRL_LPLUD BIT1
+#define R_PCH_LAN_CSR_F18 0x0F18
+#define B_PCH_LAN_CSR_F18_K1OFF_EN BIT31
+#define R_PCH_LAN_CSR_PBECCSTS 0x100C
+#define B_PCH_LAN_CSR_PBECCSTS_ECC_EN BIT16
+#define R_PCH_LAN_CSR_RAL 0x5400
+#define R_PCH_LAN_CSR_RAH 0x5404
+#define B_PCH_LAN_CSR_RAH_RAH 0x0000FFFF
+#define R_PCH_LAN_CSR_WUC 0x5800
+#define B_PCH_LAN_CSR_WUC_APME BIT0
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h
new file mode 100644
index 0000000000..7c6f639260
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h
@@ -0,0 +1,610 @@
+/** @file
+ Register names for PCH LPC/eSPI device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_LPC_H_
+#define _PCH_REGS_LPC_H_
+
+//
+// PCI to LPC Bridge Registers (D31:F0)
+//
+#define PCI_DEVICE_NUMBER_PCH_LPC 31
+#define PCI_FUNCTION_NUMBER_PCH_LPC 0
+
+typedef enum {
+ PchHB0 = 0x01,
+ PchHC0,
+ PchHD0,
+ PchHD1,
+ PchLpB0 = 0x23,
+ PchLpB1,
+ PchLpC0,
+ PchLpC1,
+ KblPchHA0 = 0x40,
+ PchSteppingMax
+} PCH_STEPPING;
+
+#define SKL_PCH_H_MIN_SUPPORTED_STEPPING PchHB0
+#define KBL_PCH_H_MIN_SUPPORTED_STEPPING KblPchHA0
+#define PCH_LP_MIN_SUPPORTED_STEPPING PchLpB0
+
+#define V_PCH_LPC_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+
+//
+//
+// SKL PCH Server/WS LPC Device IDs
+//
+#define V_SKL_PCH_H_LPC_DEVICE_ID_SVR_0 0xA149 ///< Server SKU Intel C236 Chipset
+#define V_SKL_PCH_H_LPC_DEVICE_ID_SVR_1 0xA14A ///< Server SKU Intel C232 Chipset
+#define V_SKL_PCH_H_LPC_DEVICE_ID_SVR_2 0xA150 ///< Server SKU Intel CM236 Chipset
+#define V_SKL_PCH_H_LPC_DEVICE_ID_A14B 0xA14B ///< Super SKU Unlocked
+
+//
+// SKL PCH-H Desktop LPC Device IDs
+//
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU 0xA141 ///< PCH H Desktop Super SKU unlocked
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_0 0xA142 ///< PCH H Desktop Super SKU locked
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_1 0xA143 ///< PCH H Desktop H110
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_2 0xA144 ///< PCH H Desktop H170
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_3 0xA145 ///< PCH H Desktop Z170
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_4 0xA146 ///< PCH H Desktop Q170
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_5 0xA147 ///< PCH H Desktop Q150
+#define V_SKL_PCH_H_LPC_DEVICE_ID_DT_6 0xA148 ///< PCH H Desktop B150
+//
+// SKL PCH-H Mobile LPC Device IDs
+//
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_SUPER_SKU 0xA141 ///< PCH H Mobile Super SKU unlocked
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_0 0xA14D ///< PCH H Mobile QM170
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_1 0xA14E ///< PCH H Mobile HM170
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_3 0xA151 ///< PCH H Mobile QMS180 (SFF)
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_4 0xA152 ///< KBL PCH H Mobile HM175
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_5 0xA153 ///< KBL PCH H Mobile QM175
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_6 0xA154 ///< KBL PCH H Mobile CM238
+#define V_SKL_PCH_H_LPC_DEVICE_ID_MB_8 0xA156 ///< KBL PCH H Mobile QMS185 (SFF)
+
+//
+// SKL PCH-LP LPC Device IDs
+//
+#define V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU 0x9D41 ///< PCH LP Mobile Super SKU unlocked
+#define V_PCH_LP_LPC_DEVICE_ID_MB_0 0x9D42 ///< PCH LP Mobile Super SKU locked
+#define V_PCH_LP_LPC_DEVICE_ID_MB_1 0x9D43 ///< PCH LP Mobile (U) Base SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_2 0x9D46 ///< PCH LP Mobile (Y) Premium SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_3 0x9D48 ///< PCH LP Mobile (U) Premium SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU_1 0x9D51 ///< KBL PCH LP Mobile Super SKU unlocked
+#define V_PCH_LP_LPC_DEVICE_ID_MB_4 0x9D52 ///< KBL PCH LP Mobile Super SKU locked
+#define V_PCH_LP_LPC_DEVICE_ID_MB_5 0x9D53 ///< KBL PCH LP Mobile (U) Base SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_6 0x9D56 ///< KBL PCH LP Mobile (Y) Premium SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_7 0x9D58 ///< KBL PCH LP Mobile (U) Premium SKU
+#define V_PCH_LP_LPC_DEVICE_ID_MB_8 0x9D4B ///< KBL PCH LP Mobile (Y) iHDCP 2.2 Premium
+#define V_PCH_LP_LPC_DEVICE_ID_MB_9 0x9D4E ///< KBL PCH LP Mobile (U) iHDCP 2.2 Premium
+#define V_PCH_LP_LPC_DEVICE_ID_MB_10 0x9D50 ///< KBL PCH LP Mobile (U) iHDCP 2.2 Base
+
+
+
+//
+// KBL PCH Server/WS LPC Device IDs
+//
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_ES_SUPER_SKU 0xA2D0 ///< ES Super SKU Unlocked. This is SKL-PCH-H in KBL-PCH-H package
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_SUPER_SKU 0xA2D1 ///< Super SKU Unlocked
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_0 0xA2D2 ///< Server SKU X290
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_1 0xA2D3 ///< Server SKU C6xx
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_2 0xA2CE ///< Server SKU ES SuperSKU Server
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_3 0xA2CF ///< Server SKU SuperSKU Server
+#define V_KBL_PCH_H_LPC_DEVICE_ID_SVR_4 0xA2D4 ///< Server SKU C422B
+
+
+//
+// KBL PCH-H Desktop LPC Device IDs
+//
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_ES_SUPER_SKU 0xA2C0 ///< PCH H Desktop ES Super SKU unlocked. This is SKL-PCH-H in KBL-PCH-H package
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU 0xA2C1 ///< PCH H Desktop Super SKU unlocked
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_H270 0xA2C4 ///< PCH H Desktop H270
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z270 0xA2C5 ///< PCH H Desktop Z270
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q270 0xA2C6 ///< PCH H Desktop Q270
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q250 0xA2C7 ///< PCH H Desktop Q250
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_B250 0xA2C8 ///< PCH H Desktop B250
+
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_H215 0xA2C3 ///< PCH H Desktop H215
+#define V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z370 0xA2C9 ///< PCH H Desktop Z370
+
+#define V_PCH_LPC_RID_0 0x00
+#define V_PCH_LPC_RID_1 0x01
+#define V_PCH_LPC_RID_9 0x09
+#define V_PCH_LPC_RID_10 0x10
+#define V_PCH_LPC_RID_11 0x11
+#define V_PCH_LPC_RID_20 0x20
+#define V_PCH_LPC_RID_21 0x21
+#define V_PCH_LPC_RID_30 0x30
+#define V_PCH_LPC_RID_31 0x31
+#define R_PCH_LPC_SERIRQ_CNT 0x64
+#define B_PCH_LPC_SERIRQ_CNT_SIRQEN 0x80
+#define B_PCH_LPC_SERIRQ_CNT_SIRQMD 0x40
+#define B_PCH_LPC_SERIRQ_CNT_SIRQSZ 0x3C
+#define N_PCH_LPC_SERIRQ_CNT_SIRQSZ 2
+#define B_PCH_LPC_SERIRQ_CNT_SFPW 0x03
+#define N_PCH_LPC_SERIRQ_CNT_SFPW 0
+#define V_PCH_LPC_SERIRQ_CNT_SFPW_4CLK 0x00
+#define V_PCH_LPC_SERIRQ_CNT_SFPW_6CLK 0x01
+#define V_PCH_LPC_SERIRQ_CNT_SFPW_8CLK 0x02
+#define R_PCH_LPC_IOD 0x80
+#define B_PCH_LPC_IOD_FDD 0x1000
+#define N_PCH_LPC_IOD_FDD 12
+#define V_PCH_LPC_IOD_FDD_3F0 0
+#define V_PCH_LPC_IOD_FDD_370 1
+#define B_PCH_LPC_IOD_LPT 0x0300
+#define N_PCH_LPC_IOD_LPT 8
+#define V_PCH_LPC_IOD_LPT_378 0
+#define V_PCH_LPC_IOD_LPT_278 1
+#define V_PCH_LPC_IOD_LPT_3BC 2
+#define B_PCH_LPC_IOD_COMB 0x0070
+#define N_PCH_LPC_IOD_COMB 4
+#define V_PCH_LPC_IOD_COMB_3F8 0
+#define V_PCH_LPC_IOD_COMB_2F8 1
+#define V_PCH_LPC_IOD_COMB_220 2
+#define V_PCH_LPC_IOD_COMB_228 3
+#define V_PCH_LPC_IOD_COMB_238 4
+#define V_PCH_LPC_IOD_COMB_2E8 5
+#define V_PCH_LPC_IOD_COMB_338 6
+#define V_PCH_LPC_IOD_COMB_3E8 7
+#define B_PCH_LPC_IOD_COMA 0x0007
+#define N_PCH_LPC_IOD_COMA 0
+#define V_PCH_LPC_IOD_COMA_3F8 0
+#define V_PCH_LPC_IOD_COMA_2F8 1
+#define V_PCH_LPC_IOD_COMA_220 2
+#define V_PCH_LPC_IOD_COMA_228 3
+#define V_PCH_LPC_IOD_COMA_238 4
+#define V_PCH_LPC_IOD_COMA_2E8 5
+#define V_PCH_LPC_IOD_COMA_338 6
+#define V_PCH_LPC_IOD_COMA_3E8 7
+#define R_PCH_LPC_IOE 0x82
+#define B_PCH_LPC_IOE_ME2 BIT13 ///< Microcontroller Enable #2, Enables decoding of I/O locations 4Eh and 4Fh to LPC
+#define B_PCH_LPC_IOE_SE BIT12 ///< Super I/O Enable, Enables decoding of I/O locations 2Eh and 2Fh to LPC.
+#define B_PCH_LPC_IOE_ME1 BIT11 ///< Microcontroller Enable #1, Enables decoding of I/O locations 62h and 66h to LPC.
+#define B_PCH_LPC_IOE_KE BIT10 ///< Keyboard Enable, Enables decoding of the keyboard I/O locations 60h and 64h to LPC.
+#define B_PCH_LPC_IOE_HGE BIT9 ///< High Gameport Enable, Enables decoding of the I/O locations 208h to 20Fh to LPC.
+#define B_PCH_LPC_IOE_LGE BIT8 ///< Low Gameport Enable, Enables decoding of the I/O locations 200h to 207h to LPC.
+#define B_PCH_LPC_IOE_FDE BIT3 ///< Floppy Drive Enable, Enables decoding of the FDD range to LPC. Range is selected by LIOD.FDE
+#define B_PCH_LPC_IOE_PPE BIT2 ///< Parallel Port Enable, Enables decoding of the LPT range to LPC. Range is selected by LIOD.LPT.
+#define B_PCH_LPC_IOE_CBE BIT1 ///< Com Port B Enable, Enables decoding of the COMB range to LPC. Range is selected LIOD.CB.
+#define B_PCH_LPC_IOE_CAE BIT0 ///< Com Port A Enable, Enables decoding of the COMA range to LPC. Range is selected LIOD.CA.
+#define R_PCH_LPC_GEN1_DEC 0x84
+#define R_PCH_LPC_GEN2_DEC 0x88
+#define R_PCH_LPC_GEN3_DEC 0x8C
+#define R_PCH_LPC_GEN4_DEC 0x90
+#define B_PCH_LPC_GENX_DEC_IODRA 0x00FC0000
+#define B_PCH_LPC_GENX_DEC_IOBAR 0x0000FFFC
+#define B_PCH_LPC_GENX_DEC_EN 0x00000001
+#define R_PCH_LPC_ULKMC 0x94
+#define B_PCH_LPC_ULKMC_SMIBYENDPS BIT15
+#define B_PCH_LPC_ULKMC_TRAPBY64W BIT11
+#define B_PCH_LPC_ULKMC_TRAPBY64R BIT10
+#define B_PCH_LPC_ULKMC_TRAPBY60W BIT9
+#define B_PCH_LPC_ULKMC_TRAPBY60R BIT8
+#define B_PCH_LPC_ULKMC_SMIATENDPS BIT7
+#define B_PCH_LPC_ULKMC_PSTATE BIT6
+#define B_PCH_LPC_ULKMC_A20PASSEN BIT5
+#define B_PCH_LPC_ULKMC_USBSMIEN BIT4
+#define B_PCH_LPC_ULKMC_64WEN BIT3
+#define B_PCH_LPC_ULKMC_64REN BIT2
+#define B_PCH_LPC_ULKMC_60WEN BIT1
+#define B_PCH_LPC_ULKMC_60REN BIT0
+#define R_PCH_LPC_LGMR 0x98
+#define B_PCH_LPC_LGMR_MA 0xFFFF0000
+#define B_PCH_LPC_LGMR_LMRD_EN BIT0
+
+#define R_PCH_LPC_FWH_BIOS_SEL 0xD0
+#define B_PCH_LPC_FWH_BIOS_SEL_F8 0xF0000000
+#define B_PCH_LPC_FWH_BIOS_SEL_F0 0x0F000000
+#define B_PCH_LPC_FWH_BIOS_SEL_E8 0x00F00000
+#define B_PCH_LPC_FWH_BIOS_SEL_E0 0x000F0000
+#define B_PCH_LPC_FWH_BIOS_SEL_D8 0x0000F000
+#define B_PCH_LPC_FWH_BIOS_SEL_D0 0x00000F00
+#define B_PCH_LPC_FWH_BIOS_SEL_C8 0x000000F0
+#define B_PCH_LPC_FWH_BIOS_SEL_C0 0x0000000F
+#define R_PCH_LPC_FWH_BIOS_SEL2 0xD4
+#define B_PCH_LPC_FWH_BIOS_SEL2_70 0xF000
+#define B_PCH_LPC_FWH_BIOS_SEL2_60 0x0F00
+#define B_PCH_LPC_FWH_BIOS_SEL2_50 0x00F0
+#define B_PCH_LPC_FWH_BIOS_SEL2_40 0x000F
+#define R_PCH_LPC_BDE 0xD8 ///< BIOS decode enable
+#define B_PCH_LPC_BDE_F8 0x8000
+#define B_PCH_LPC_BDE_F0 0x4000
+#define B_PCH_LPC_BDE_E8 0x2000
+#define B_PCH_LPC_BDE_E0 0x1000
+#define B_PCH_LPC_BDE_D8 0x0800
+#define B_PCH_LPC_BDE_D0 0x0400
+#define B_PCH_LPC_BDE_C8 0x0200
+#define B_PCH_LPC_BDE_C0 0x0100
+#define B_PCH_LPC_BDE_LEG_F 0x0080
+#define B_PCH_LPC_BDE_LEG_E 0x0040
+#define B_PCH_LPC_BDE_70 0x0008
+#define B_PCH_LPC_BDE_60 0x0004
+#define B_PCH_LPC_BDE_50 0x0002
+#define B_PCH_LPC_BDE_40 0x0001
+#define R_PCH_LPC_PCC 0xE0
+#define B_PCH_LPC_PCC_CLKRUN_EN 0x0001
+#define B_PCH_LPC_FVEC0_USB_PORT_CAP 0x00000C00
+#define V_PCH_LPC_FVEC0_USB_14_PORT 0x00000000
+#define V_PCH_LPC_FVEC0_USB_12_PORT 0x00000400
+#define V_PCH_LPC_FVEC0_USB_10_PORT 0x00000800
+#define B_PCH_LPC_FVEC0_SATA_RAID_CAP 0x00000080
+#define B_PCH_LPC_FVEC0_SATA_PORT23_CAP 0x00000040
+#define B_PCH_LPC_FVEC0_SATA_PORT1_6GB_CAP 0x00000008
+#define B_PCH_LPC_FVEC0_SATA_PORT0_6GB_CAP 0x00000004
+#define B_PCH_LPC_FVEC0_PCI_CAP 0x00000002
+#define R_PCH_LPC_FVEC1 0x01
+#define B_PCH_LPC_FVEC1_USB_R_CAP 0x00400000
+#define R_PCH_LPC_FVEC2 0x02
+#define V_PCH_LPC_FVEC2_PCIE_PORT78_CAP 0x00200000
+#define V_PCH_LPC_FVEC2_PCH_IG_SUPPORT_CAP 0x00020000 ///< PCH Integrated Graphics Support Capability
+#define R_PCH_LPC_FVEC3 0x03
+#define B_PCH_LPC_FVEC3_DCMI_CAP 0x00002000 ///< Data Center Manageability Interface (DCMI) Capability
+#define B_PCH_LPC_FVEC3_NM_CAP 0x00001000 ///< Node Manager Capability
+
+#define R_PCH_LPC_MDAP 0xC0
+#define B_PCH_LPC_MDAP_POLICY_EN BIT31
+#define B_PCH_LPC_MDAP_PDMA_EN BIT30
+#define B_PCH_LPC_MDAP_VALUE 0x0001FFFF
+
+//
+// APM Registers
+//
+#define R_PCH_APM_CNT 0xB2
+#define R_PCH_APM_STS 0xB3
+
+#define R_PCH_LPC_BC 0xDC ///< Bios Control
+#define S_PCH_LPC_BC 1
+#define B_PCH_LPC_BC_BILD BIT7 ///< BIOS Interface Lock-Down
+#define B_PCH_LPC_BC_BBS BIT6 ///< Boot BIOS strap
+#define N_PCH_LPC_BC_BBS 6
+#define V_PCH_LPC_BC_BBS_SPI 0 ///< Boot BIOS strapped to SPI
+#define V_PCH_LPC_BC_BBS_LPC 1 ///< Boot BIOS strapped to LPC
+#define B_PCH_LPC_BC_EISS BIT5 ///< Enable InSMM.STS
+#define B_PCH_LPC_BC_TS BIT4 ///< Top Swap
+#define B_PCH_LPC_BC_LE BIT1 ///< Lock Enable
+#define N_PCH_LPC_BC_LE 1
+#define B_PCH_LPC_BC_WPD BIT0 ///< Write Protect Disable
+
+#define R_PCH_ESPI_PCBC 0xDC ///< Peripheral Channel BIOS Control
+#define S_PCH_ESPI_PCBC 4 ///< Peripheral Channel BIOS Control register size
+#define B_PCH_ESPI_PCBC_BWRE BIT11 ///< BIOS Write Report Enable
+#define N_PCH_ESPI_PCBC_BWRE 11 ///< BIOS Write Report Enable bit position
+#define B_PCH_ESPI_PCBC_BWRS BIT10 ///< BIOS Write Report Status
+#define N_PCH_ESPI_PCBC_BWRS 10 ///< BIOS Write Report Status bit position
+#define B_PCH_ESPI_PCBC_BWPDS BIT8 ///< BIOS Write Protect Disable Status
+#define N_PCH_ESPI_PCBC_BWPDS 8 ///< BIOS Write Protect Disable Status bit position
+#define B_PCH_ESPI_PCBC_ESPI_EN BIT2 ///< eSPI Enable Pin Strap
+#define B_PCH_ESPI_PCBC_LE BIT1 ///< Lock Enable
+#define N_PCH_ESPI_PCBC_LE 1
+
+//
+// eSPI slave registers
+//
+#define R_ESPI_SLAVE_CHA_0_CAP_AND_CONF 0x10 ///< Channel 0 Capabilities and Configurations
+#define B_ESPI_SLAVE_CHA_0_CAP_AND_CONF_BME BIT2 ///< Bus Master Enable
+
+//
+// Processor interface registers
+//
+#define R_PCH_NMI_SC 0x61
+#define B_PCH_NMI_SC_SERR_NMI_STS BIT7
+#define B_PCH_NMI_SC_IOCHK_NMI_STS BIT6
+#define B_PCH_NMI_SC_TMR2_OUT_STS BIT5
+#define B_PCH_NMI_SC_REF_TOGGLE BIT4
+#define B_PCH_NMI_SC_IOCHK_NMI_EN BIT3
+#define B_PCH_NMI_SC_PCI_SERR_EN BIT2
+#define B_PCH_NMI_SC_SPKR_DAT_EN BIT1
+#define B_PCH_NMI_SC_TIM_CNT2_EN BIT0
+#define R_PCH_NMI_EN 0x70
+#define B_PCH_NMI_EN_NMI_EN BIT7
+
+//
+// Reset Generator I/O Port
+//
+#define R_PCH_RST_CNT 0xCF9
+#define B_PCH_RST_CNT_FULL_RST BIT3
+#define B_PCH_RST_CNT_RST_CPU BIT2
+#define B_PCH_RST_CNT_SYS_RST BIT1
+#define V_PCH_RST_CNT_FULLRESET 0x0E
+#define V_PCH_RST_CNT_HARDRESET 0x06
+#define V_PCH_RST_CNT_SOFTRESET 0x04
+#define V_PCH_RST_CNT_HARDSTARTSTATE 0x02
+#define V_PCH_RST_CNT_SOFTSTARTSTATE 0x00
+
+//
+// RTC register
+//
+#define R_PCH_RTC_INDEX 0x70
+#define R_PCH_RTC_TARGET 0x71
+#define R_PCH_RTC_EXT_INDEX 0x72
+#define R_PCH_RTC_EXT_TARGET 0x73
+#define R_PCH_RTC_INDEX_ALT 0x74
+#define R_PCH_RTC_TARGET_ALT 0x75
+#define R_PCH_RTC_EXT_INDEX_ALT 0x76
+#define R_PCH_RTC_EXT_TARGET_ALT 0x77
+#define R_PCH_RTC_REGA 0x0A
+#define B_PCH_RTC_REGA_UIP 0x80
+#define R_PCH_RTC_REGB 0x0B
+#define B_PCH_RTC_REGB_SET 0x80
+#define B_PCH_RTC_REGB_PIE 0x40
+#define B_PCH_RTC_REGB_AIE 0x20
+#define B_PCH_RTC_REGB_UIE 0x10
+#define B_PCH_RTC_REGB_DM 0x04
+#define B_PCH_RTC_REGB_HOURFORM 0x02
+#define R_PCH_RTC_REGC 0x0C
+#define R_PCH_RTC_REGD 0x0D
+
+//
+// Private Configuration Register
+// RTC PCRs (PID:RTC)
+//
+#define R_PCH_PCR_RTC_CONF 0x3400 ///< RTC Configuration register
+#define S_PCH_PCR_RTC_CONF 4
+#define B_PCH_PCR_RTC_CONF_UCMOS_LOCK BIT4
+#define B_PCH_PCR_RTC_CONF_LCMOS_LOCK BIT3
+#define B_PCH_PCR_RTC_CONF_RESERVED BIT31
+#define B_PCH_PCR_RTC_CONF_UCMOS_EN BIT2 ///< Upper CMOS bank enable
+#define R_PCH_PCR_RTC_BUC 0x3414 ///< Backed Up Control
+#define B_PCH_PCR_RTC_BUC_TS BIT0 ///< Top Swap
+#define R_PCH_PCR_RTC_RTCDCG 0x3418 ///< RTC Dynamic Clock Gating Control
+#define R_PCH_PCR_RTC_RTCDCG_RTCPCICLKDCGEN BIT1 ///< ipciclk_clk (24 MHz) Dynamic Clock Gate Enable
+#define R_PCH_PCR_RTC_RTCDCG_RTCROSIDEDCGEN BIT0 ///< rosc_side_clk (120 MHz) Dynamic Clock Gate Enable
+#define R_PCH_PCR_RTC_3F00 0x3F00
+#define R_PCH_PCR_RTC_UIPSMI 0x3F04 ///< RTC Update In Progress SMI Control
+
+//
+// LPC PCR Registers
+//
+#define R_PCH_PCR_LPC_HVMTCTL 0x3410
+#define R_PCH_PCR_LPC_GCFD 0x3418
+#define R_PCH_PCR_LPC_PRC 0x341C
+#define R_PCH_PCR_LPC_PCT 0x3420
+#define R_PCH_PCR_LPC_SCT 0x3424
+#define R_PCH_PCR_LPC_LPCCT 0x3428
+#define R_PCH_PCR_LPC_ULTOR 0x3500
+
+//
+// eSPI PCR Registers
+//
+#define R_PCH_PCR_ESPI_SLV_CFG_REG_CTL 0x4000 ///< Slave Configuration Register and Link Control
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRE BIT31 ///< Slave Configuration Register Access Enable
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRS (BIT30 | BIT29 | BIT28) ///< Slave Configuration Register Access Status
+#define N_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRS 28 ///< Slave Configuration Register Access Status bit position
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SBLCL BIT27 ///< IOSF-SB eSPI Link Configuration Lock
+#define V_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRS_NOERR 7 ///< No errors (transaction completed successfully)
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SID (BIT20 | BIT19) ///< Slave ID
+#define N_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SID 19 ///< Slave ID bit position
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT (BIT17 | BIT16) ///< Slave Configuration Register Access Type
+#define N_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT 16 ///< Slave Configuration Register Access Type bit position
+#define V_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT_RD 0 ///< Slave Configuration register read from address SCRA[11:0]
+#define V_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT_WR 1 ///< Slave Configuration register write to address SCRA[11:0]
+#define V_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT_STS 2 ///< Slave Status register read
+#define V_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRT_RS 3 ///< In-Band reset
+#define B_PCH_PCR_ESPI_SLV_CFG_REG_CTL_SCRA 0x00000FFF ///< Slave Configuration Register Address
+#define R_PCH_PCR_ESPI_SLV_CFG_REG_DATA 0x4004 ///< Slave Configuration Register Data
+
+#define R_PCH_PCR_ESPI_PCERR_SLV0 0x4020 ///< Peripheral Channel Error for Slave 0
+#define R_PCH_PCR_ESPI_PCERR_SLV1 0x4024 ///< Peripheral Channel Error for Slave 1
+#define R_PCH_PCR_ESPI_VWERR_SLV0 0x4030 ///< Virtual Wire Channel Error for Slave 0
+#define R_PCH_PCR_ESPI_VWERR_SLV1 0x4034 ///< Virtual Wire Channel Error for Slave 1
+#define R_PCH_PCR_ESPI_FCERR_SLV0 0x4040 ///< Flash Access Channel Error for Slave 0
+#define B_PCH_PCR_ESPI_XERR_XNFEE (BIT14 | BIT13) ///< Non-Fatal Error Reporting Enable bits
+#define N_PCH_PCR_ESPI_XERR_XNFEE 13 ///< Non-Fatal Error Reporting Enable bit position
+#define V_PCH_PCR_ESPI_XERR_XNFEE_SMI 3 ///< Enable Non-Fatal Error Reporting as SMI
+#define B_PCH_PCR_ESPI_XERR_XNFES BIT12 ///< Fatal Error Status
+#define B_PCH_PCR_ESPI_XERR_XFEE (BIT6 | BIT5) ///< Fatal Error Reporting Enable bits
+#define N_PCH_PCR_ESPI_XERR_XFEE 5 ///< Fatal Error Reporting Enable bit position
+#define V_PCH_PCR_ESPI_XERR_XFEE_SMI 3 ///< Enable Fatal Error Reporting as SMI
+#define B_PCH_PCR_ESPI_XERR_XFES BIT4 ///< Fatal Error Status
+#define B_PCH_PCR_ESPI_PCERR_SLV0_PCURD BIT24 ///< Peripheral Channel Unsupported Request Detected
+#define R_PCH_PCR_ESPI_LNKERR_SLV0 0x4050 ///< Link Error for Slave 0
+#define S_PCH_PCR_ESPI_LNKERR_SLV0 4 ///< Link Error for Slave 0 register size
+#define B_PCH_PCR_ESPI_LNKERR_SLV0_SLCRR BIT31 ///< eSPI Link and Slave Channel Recovery Required
+#define B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E (BIT22 | BIT21) ///< Fatal Error Type 1 Reporting Enable
+#define N_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E 21 ///< Fatal Error Type 1 Reporting Enable bit position
+#define V_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E_SMI 3 ///< Enable Fatal Error Type 1 Reporting as SMI
+#define B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S BIT20 ///< Link Fatal Error Type 1 Status
+#define R_PCH_PCR_ESPI_CFG_VAL 0xC00C ///< ESPI Enabled Strap
+#define B_PCH_PCR_ESPI_ENABLE_STRAP BIT0 ///< ESPI Enabled Strap bit position
+
+
+
+//
+// LPC Device ID macros
+//
+//
+// Device IDs that are SKL PCH-H Desktop specific
+//
+#define IS_SKL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ ( \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_0) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_1) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_2) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_3) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_4) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_5) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_6) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_ES_SUPER_SKU /* SKL-PCH-H in KBL-PCH-H package */) \
+ )
+
+//
+// Device IDs that are KBL PCH-H Desktop specific
+//
+#define IS_KBL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ ( \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_H215) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z370) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_H270) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z270) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q270) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q250) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_B250) \
+ )
+
+//
+// Device IDs that are PCH-H Desktop specific
+//
+#define IS_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ ( \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) || \
+ IS_KBL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ )
+
+#define IS_PCH_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ ( \
+ IS_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ )
+
+//
+// Device IDs that are PCH-H Mobile specific
+//
+
+#define IS_PCH_H_LPC_DEVICE_ID_MOBILE(DeviceId) \
+ ( \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_0) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_1) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_3) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_4) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_5) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_6) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_SUPER_SKU) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_MB_8) \
+ )
+
+//
+// Device IDs that are PCH-LP Mobile specific
+//
+#define IS_PCH_LP_LPC_DEVICE_ID_MOBILE(DeviceId) \
+ ( \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_0) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_1) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_2) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_3) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU_1) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_4) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_5) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_6) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_7) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_8) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_9) || \
+ (DeviceId == V_PCH_LP_LPC_DEVICE_ID_MB_10) \
+ )
+
+#define IS_PCH_LPC_DEVICE_ID_MOBILE(DeviceId) \
+ ( \
+ IS_PCH_H_LPC_DEVICE_ID_MOBILE(DeviceId) || \
+ IS_PCH_LP_LPC_DEVICE_ID_MOBILE(DeviceId) \
+ )
+
+//
+// Device IDS that are SKL PCH Server\Workstation specific
+//
+#define IS_SKL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ ( \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_ES_SUPER_SKU) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_SVR_0) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_SVR_1) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_SVR_2) || \
+ (DeviceId == V_SKL_PCH_H_LPC_DEVICE_ID_A14B) \
+ )
+
+//
+// Device IDS that are KBL PCH Server\Workstation specific
+//
+#define IS_KBL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ ( \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_SUPER_SKU) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_0) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_1) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_2) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_3) || \
+ (DeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_4) \
+ )
+
+
+#define IS_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ ( \
+ IS_KBL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) || \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ )
+
+#define IS_PCH_LPC_DEVICE_ID_SERVER(DeviceId) \
+ ( \
+ IS_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ )
+
+#define IS_PCH_H_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) || \
+ IS_PCH_H_LPC_DEVICE_ID_MOBILE(DeviceId) || \
+ IS_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ )
+
+#define IS_SKL_PCH_H_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) || \
+ IS_PCH_H_LPC_DEVICE_ID_MOBILE(DeviceId) || \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ )
+
+#define IS_KBL_PCH_H_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_KBL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) || \
+ IS_KBL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) \
+ )
+
+#define IS_PCH_LP_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_LP_LPC_DEVICE_ID_MOBILE(DeviceId) \
+ )
+
+#define IS_PCH_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_LPC_DEVICE_ID(DeviceId) || \
+ IS_PCH_LP_LPC_DEVICE_ID(DeviceId) \
+ )
+
+#define IS_SKL_PCH_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_DESKTOP(DeviceId) || \
+ IS_PCH_LPC_DEVICE_ID_MOBILE(DeviceId) || \
+ IS_SKL_PCH_H_LPC_DEVICE_ID_SERVER(DeviceId) \
+ )
+
+#define IS_KBL_PCH_LPC_DEVICE_ID(DeviceId) \
+ ( \
+ IS_KBL_PCH_H_LPC_DEVICE_ID(DeviceId) \
+ )
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsP2sb.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsP2sb.h
new file mode 100644
index 0000000000..b2779ab0ce
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsP2sb.h
@@ -0,0 +1,138 @@
+/** @file
+ Register names for PCH P2SB device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_P2SB_H_
+#define _PCH_REGS_P2SB_H_
+
+//
+// PCI to P2SB Bridge Registers (D31:F1)
+//
+#define PCI_DEVICE_NUMBER_PCH_P2SB 31
+#define PCI_FUNCTION_NUMBER_PCH_P2SB 1
+
+#define V_PCH_P2SB_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+#define R_PCH_P2SB_SBREG_BAR 0x10
+#define B_PCH_P2SB_SBREG_RBA 0xFF000000
+#define R_PCH_P2SB_SBREG_BARH 0x14
+#define B_PCH_P2SB_SBREG_RBAH 0xFFFFFFFF
+#define R_PCH_P2SB_VBDF 0x50
+#define B_PCH_P2SB_VBDF_BUF 0xFF00
+#define B_PCH_P2SB_VBDF_DEV 0x00F8
+#define B_PCH_P2SB_VBDF_FUNC 0x0007
+#define R_PCH_P2SB_ESMBDF 0x52
+#define B_PCH_P2SB_ESMBDF_BUF 0xFF00
+#define B_PCH_P2SB_ESMBDF_DEV 0x00F8
+#define B_PCH_P2SB_ESMBDF_FUNC 0x0007
+#define R_PCH_P2SB_RCFG 0x54
+#define B_PCH_P2SB_RCFG_RPRID 0x0000FF00
+#define B_PCH_P2SB_RCFG_RSE BIT0
+#define R_PCH_P2SB_HPTC 0x60
+#define B_PCH_P2SB_HPTC_AE BIT7
+#define B_PCH_P2SB_HPTC_AS 0x0003
+#define N_PCH_HPET_ADDR_ASEL 12
+#define V_PCH_HPET_BASE0 0xFED00000
+#define V_PCH_HPET_BASE1 0xFED01000
+#define V_PCH_HPET_BASE2 0xFED02000
+#define V_PCH_HPET_BASE3 0xFED03000
+#define R_PCH_P2SB_IOAC 0x64
+#define B_PCH_P2SB_IOAC_AE BIT8
+#define B_PCH_P2SB_IOAC_ASEL 0x00FF
+#define N_PCH_IO_APIC_ASEL 12
+#define R_PCH_IO_APIC_INDEX 0xFEC00000
+#define R_PCH_IO_APIC_DATA 0xFEC00010
+#define R_PCH_IO_APIC_EOI 0xFEC00040
+#define R_PCH_P2SB_IBDF 0x6C
+#define B_PCH_P2SB_IBDF_BUF 0xFF00
+#define B_PCH_P2SB_IBDF_DEV 0x00F8
+#define B_PCH_P2SB_IBDF_FUNC 0x0007
+#define R_PCH_P2SB_HBDF 0x70
+#define B_PCH_P2SB_HBDF_BUF 0xFF00
+#define B_PCH_P2SB_HBDF_DEV 0x00F8
+#define B_PCH_P2SB_HBDF_FUNC 0x0007
+#define R_PCH_P2SB_80 0x80
+#define R_PCH_P2SB_84 0x84
+#define R_PCH_P2SB_88 0x88
+#define R_PCH_P2SB_8C 0x8C
+#define R_PCH_P2SB_90 0x90
+#define R_PCH_P2SB_94 0x94
+#define R_PCH_P2SB_98 0x98
+#define R_PCH_P2SB_9C 0x9C
+
+#define R_PCH_P2SB_DISPBDF 0xA0
+#define B_PCH_P2SB_DISPBDF_DTBLK 0x00070000
+#define B_PCH_P2SB_DISPBDF_BUF 0x0000FF00
+#define B_PCH_P2SB_DISPBDF_DEV 0x000000F8
+#define B_PCH_P2SB_DISPBDF_FUNC 0x00000007
+#define R_PCH_P2SB_ICCOS 0xA4
+#define B_PCH_P2SB_ICCOS_MODBASE 0xFF00
+#define B_PCH_P2SB_ICCOS_BUFBASE 0x00FF
+#define R_PCH_P2SB_EPMASK0 0xB0
+#define R_PCH_P2SB_EPMASK1 0xB4
+#define R_PCH_P2SB_EPMASK2 0xB8
+#define R_PCH_P2SB_EPMASK3 0xBC
+#define R_PCH_P2SB_EPMASK4 0xC0
+#define R_PCH_P2SB_EPMASK5 0xC4
+#define R_PCH_P2SB_EPMASK6 0xC8
+#define R_PCH_P2SB_EPMASK7 0xCC
+
+//
+// Definition for SBI
+//
+#define R_PCH_P2SB_SBIADDR 0xD0
+#define B_PCH_P2SB_SBIADDR_DESTID 0xFF000000
+#define B_PCH_P2SB_SBIADDR_RS 0x000F0000
+#define B_PCH_P2SB_SBIADDR_OFFSET 0x0000FFFF
+#define R_PCH_P2SB_SBIDATA 0xD4
+#define B_PCH_P2SB_SBIDATA_DATA 0xFFFFFFFF
+#define R_PCH_P2SB_SBISTAT 0xD8
+#define B_PCH_P2SB_SBISTAT_OPCODE 0xFF00
+#define B_PCH_P2SB_SBISTAT_POSTED BIT7
+#define B_PCH_P2SB_SBISTAT_RESPONSE 0x0006
+#define N_PCH_P2SB_SBISTAT_RESPONSE 1
+#define B_PCH_P2SB_SBISTAT_INITRDY BIT0
+#define R_PCH_P2SB_SBIRID 0xDA
+#define B_PCH_P2SB_SBIRID_FBE 0xF000
+#define B_PCH_P2SB_SBIRID_BAR 0x0700
+#define B_PCH_P2SB_SBIRID_FID 0x00FF
+#define R_PCH_P2SB_SBIEXTADDR 0xDC
+#define B_PCH_P2SB_SBIEXTADDR_ADDR 0xFFFFFFFF
+
+//
+// Others
+//
+#define R_PCH_P2SB_E0 0xE0
+#define R_PCH_P2SB_E4 0xE4
+#define R_PCH_P2SB_E8 0xE8
+#define R_PCH_P2SB_EA 0xEA
+#define R_PCH_P2SB_F4 0xF4
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcie.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcie.h
new file mode 100644
index 0000000000..704f77c52f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcie.h
@@ -0,0 +1,524 @@
+/** @file
+ Register names for PCH PCI-E root port devices
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_PCIE_H_
+#define _PCH_REGS_PCIE_H_
+
+//
+// PCH PCI Express Root Ports (D28:F0..7, D29:F0..7, D27:F0..7)
+//
+#define PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1 28
+#define PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2 29
+#define PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3 27
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS 28
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 0
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2 1
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3 2
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4 3
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5 4
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6 5
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_7 6
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_8 7
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_9 0
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_10 1
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_11 2
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_12 3
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_13 4
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_14 5
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_15 6
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_16 7
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_17 0
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_18 1
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_19 2
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_20 3
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_21 4
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_22 5
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_23 6
+#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_24 7
+
+#define V_PCH_PCIE_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT1 0xA110 ///< PCI Express Root Port #1, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT2 0xA111 ///< PCI Express Root Port #2, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT3 0xA112 ///< PCI Express Root Port #3, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT4 0xA113 ///< PCI Express Root Port #4, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT5 0xA114 ///< PCI Express Root Port #5, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT6 0xA115 ///< PCI Express Root Port #6, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT7 0xA116 ///< PCI Express Root Port #7, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT8 0xA117 ///< PCI Express Root Port #8, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT9 0xA118 ///< PCI Express Root Port #9, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT10 0xA119 ///< PCI Express Root Port #10, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT11 0xA11A ///< PCI Express Root Port #11, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT12 0xA11B ///< PCI Express Root Port #12, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT13 0xA11C ///< PCI Express Root Port #13, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT14 0xA11D ///< PCI Express Root Port #14, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT15 0xA11E ///< PCI Express Root Port #15, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT16 0xA11F ///< PCI Express Root Port #16, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT17 0xA167 ///< PCI Express Root Port #17, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT18 0xA168 ///< PCI Express Root Port #18, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT19 0xA169 ///< PCI Express Root Port #19, SKL PCH H
+#define V_SKL_PCH_H_PCIE_DEVICE_ID_PORT20 0xA16A ///< PCI Express Root Port #20, SKL PCH H
+
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT1 0xA290 ///< PCI Express Root Port #1, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT2 0xA291 ///< PCI Express Root Port #2, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT3 0xA292 ///< PCI Express Root Port #3, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT4 0xA293 ///< PCI Express Root Port #4, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT5 0xA294 ///< PCI Express Root Port #5, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT6 0xA295 ///< PCI Express Root Port #6, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT7 0xA296 ///< PCI Express Root Port #7, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT8 0xA297 ///< PCI Express Root Port #8, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT9 0xA298 ///< PCI Express Root Port #9, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT10 0xA299 ///< PCI Express Root Port #10, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT11 0xA29A ///< PCI Express Root Port #11, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT12 0xA29B ///< PCI Express Root Port #12, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT13 0xA29C ///< PCI Express Root Port #13, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT14 0xA29D ///< PCI Express Root Port #14, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT15 0xA29E ///< PCI Express Root Port #15, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT16 0xA29F ///< PCI Express Root Port #16, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT17 0xA2E7 ///< PCI Express Root Port #17, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT18 0xA2E8 ///< PCI Express Root Port #18, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT19 0xA2E9 ///< PCI Express Root Port #19, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT20 0xA2EA ///< PCI Express Root Port #20, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT21 0xA2EB ///< PCI Express Root Port #21, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT22 0xA2EC ///< PCI Express Root Port #22, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT23 0xA2ED ///< PCI Express Root Port #23, KBL PCH H
+#define V_KBL_PCH_H_PCIE_DEVICE_ID_PORT24 0xA2EE ///< PCI Express Root Port #24, KBL PCH H
+
+
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT1 0x9D10 ///< PCI Express Root Port #1, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT2 0x9D11 ///< PCI Express Root Port #2, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT3 0x9D12 ///< PCI Express Root Port #3, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT4 0x9D13 ///< PCI Express Root Port #4, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT5 0x9D14 ///< PCI Express Root Port #5, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT6 0x9D15 ///< PCI Express Root Port #6, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT7 0x9D16 ///< PCI Express Root Port #7, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT8 0x9D17 ///< PCI Express Root Port #8, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT9 0x9D18 ///< PCI Express Root Port #9, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT10 0x9D19 ///< PCI Express Root Port #10, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT11 0x9D1A ///< PCI Express Root Port #11, SKL PCH LP PCIe Device ID
+#define V_PCH_LP_PCIE_DEVICE_ID_PORT12 0x9D1B ///< PCI Express Root Port #12, SKL PCH LP PCIe Device ID
+
+#define R_PCH_PCIE_CLIST 0x40
+#define R_PCH_PCIE_XCAP (R_PCH_PCIE_CLIST + R_PCIE_XCAP_OFFSET)
+#define R_PCH_PCIE_DCAP (R_PCH_PCIE_CLIST + R_PCIE_DCAP_OFFSET)
+#define R_PCH_PCIE_DCTL (R_PCH_PCIE_CLIST + R_PCIE_DCTL_OFFSET)
+#define R_PCH_PCIE_DSTS (R_PCH_PCIE_CLIST + R_PCIE_DSTS_OFFSET)
+#define R_PCH_PCIE_LCAP (R_PCH_PCIE_CLIST + R_PCIE_LCAP_OFFSET)
+#define B_PCH_PCIE_LCAP_PN 0xFF000000
+#define N_PCH_PCIE_LCAP_PN 24
+#define R_PCH_PCIE_LCTL (R_PCH_PCIE_CLIST + R_PCIE_LCTL_OFFSET)
+#define R_PCH_PCIE_LSTS (R_PCH_PCIE_CLIST + R_PCIE_LSTS_OFFSET)
+#define R_PCH_PCIE_SLCAP (R_PCH_PCIE_CLIST + R_PCIE_SLCAP_OFFSET)
+#define R_PCH_PCIE_SLCTL (R_PCH_PCIE_CLIST + R_PCIE_SLCTL_OFFSET)
+#define R_PCH_PCIE_SLSTS (R_PCH_PCIE_CLIST + R_PCIE_SLSTS_OFFSET)
+#define R_PCH_PCIE_RCTL (R_PCH_PCIE_CLIST + R_PCIE_RCTL_OFFSET)
+#define R_PCH_PCIE_RSTS (R_PCH_PCIE_CLIST + R_PCIE_RSTS_OFFSET)
+#define R_PCH_PCIE_DCAP2 (R_PCH_PCIE_CLIST + R_PCIE_DCAP2_OFFSET)
+#define R_PCH_PCIE_DCTL2 (R_PCH_PCIE_CLIST + R_PCIE_DCTL2_OFFSET)
+#define R_PCH_PCIE_LCTL2 (R_PCH_PCIE_CLIST + R_PCIE_LCTL2_OFFSET)
+#define R_PCH_PCIE_LSTS2 (R_PCH_PCIE_CLIST + R_PCIE_LSTS2_OFFSET)
+
+
+#define R_PCH_PCIE_MID 0x80
+#define S_PCH_PCIE_MID 2
+#define R_PCH_PCIE_MC 0x82
+#define S_PCH_PCIE_MC 2
+#define R_PCH_PCIE_MA 0x84
+#define S_PCH_PCIE_MA 4
+#define R_PCH_PCIE_MD 0x88
+#define S_PCH_PCIE_MD 2
+
+#define R_PCH_PCIE_SVCAP 0x90
+#define S_PCH_PCIE_SVCAP 2
+#define R_PCH_PCIE_SVID 0x94
+#define S_PCH_PCIE_SVID 4
+
+#define R_PCH_PCIE_PMCAP 0xA0
+#define R_PCH_PCIE_PMCS (R_PCH_PCIE_PMCAP + R_PCIE_PMCS_OFFST)
+#define R_PCH_PCIE_MPC2 0xD4
+#define S_PCH_PCIE_MPC2 4
+#define B_PCH_PCIE_MPC2_PTNFAE BIT12
+#define B_PCH_PCIE_MPC2_LSTP BIT6
+#define B_PCH_PCIE_MPC2_IEIME BIT5
+#define B_PCH_PCIE_MPC2_ASPMCOEN BIT4
+#define B_PCH_PCIE_MPC2_ASPMCO (BIT3 | BIT2)
+#define V_PCH_PCIE_MPC2_ASPMCO_DISABLED 0
+#define V_PCH_PCIE_MPC2_ASPMCO_L0S (1 << 2)
+#define V_PCH_PCIE_MPC2_ASPMCO_L1 (2 << 2)
+#define V_PCH_PCIE_MPC2_ASPMCO_L0S_L1 (3 << 2)
+#define B_PCH_PCIE_MPC2_EOIFD BIT1
+
+#define R_PCH_PCIE_MPC 0xD8
+#define S_PCH_PCIE_MPC 4
+#define B_PCH_PCIE_MPC_PMCE BIT31
+#define B_PCH_PCIE_MPC_HPCE BIT30
+#define B_PCH_PCIE_MPC_MMBNCE BIT27
+#define B_PCH_PCIE_MPC_P8XDE BIT26
+#define B_PCH_PCIE_MPC_IRRCE BIT25
+#define B_PCH_PCIE_MPC_SRL BIT23
+#define B_PCH_PCIE_MPC_UCEL (BIT20 | BIT19 | BIT18)
+#define N_PCH_PCIE_MPC_UCEL 18
+#define B_PCH_PCIE_MPC_CCEL (BIT17 | BIT16 | BIT15)
+#define N_PCH_PCIE_MPC_CCEL 15
+#define B_PCH_PCIE_MPC_PCIESD (BIT14 | BIT13)
+#define N_PCH_PCIE_MPC_PCIESD 13
+#define V_PCH_PCIE_MPC_PCIESD_GEN1 1
+#define V_PCH_PCIE_MPC_PCIESD_GEN2 2
+#define B_PCH_PCIE_MPC_MCTPSE BIT3
+#define B_PCH_PCIE_MPC_HPME BIT1
+#define N_PCH_PCIE_MPC_HPME 1
+#define B_PCH_PCIE_MPC_PMME BIT0
+
+#define R_PCH_PCIE_SMSCS 0xDC
+#define S_PCH_PCIE_SMSCS 4
+#define B_PCH_PCIE_SMSCS_PMCS BIT31
+#define N_PCH_PCIE_SMSCS_LERSMIS 5
+#define N_PCH_PCIE_SMSCS_HPLAS 4
+#define N_PCH_PCIE_SMSCS_HPPDM 1
+
+#define R_PCH_PCIE_RPDCGEN 0xE1
+#define S_PCH_PCIE_RPDCGEN 1
+#define B_PCH_PCIE_RPDCGEN_RPSCGEN BIT7
+#define B_PCH_PCIE_RPDCGEN_PTOCGE BIT6
+#define B_PCH_PCIE_RPDCGEN_LCLKREQEN BIT5
+#define B_PCH_PCIE_RPDCGEN_BBCLKREQEN BIT4
+#define B_PCH_PCIE_RPDCGEN_SRDBCGEN BIT2
+#define B_PCH_PCIE_RPDCGEN_RPDLCGEN BIT1
+#define B_PCH_PCIE_RPDCGEN_RPDBCGEN BIT0
+
+
+#define R_PCH_PCIE_PWRCTL 0xE8
+#define B_PCH_PCIE_PWRCTL_LTSSMRTC BIT20
+#define B_PCH_PCIE_PWRCTL_WPDMPGEP BIT17
+#define B_PCH_PCIE_PWRCTL_DBUPI BIT15
+#define B_PCH_PCIE_PWRCTL_TXSWING BIT13
+#define B_PCH_PCIE_PWRCTL_RPL1SQPOL BIT1
+#define B_PCH_PCIE_PWRCTL_RPDTSQPOL BIT0
+
+#define R_PCH_PCIE_DC 0xEC
+#define B_PCH_PCIE_DC_PCIBEM BIT2
+
+#define R_PCH_PCIE_PHYCTL2 0xF5
+#define B_PCH_PCIE_PHYCTL2_TDFT (BIT7 | BIT6)
+#define B_PCH_PCIE_PHYCTL2_TXCFGCHGWAIT (BIT5 | BIT4)
+#define N_PCH_PCIE_PHYCTL2_TXCFGCHGWAIT 4
+#define B_PCH_PCIE_PHYCTL2_PXPG3PLLOFFEN BIT1
+#define B_PCH_PCIE_PHYCTL2_PXPG2PLLOFFEN BIT0
+
+#define R_PCH_PCIE_IOSFSBCS 0xF7
+#define B_PCH_PCIE_IOSFSBCS_SCPTCGE BIT6
+#define B_PCH_PCIE_IOSFSBCS_SIID (BIT3 | BIT2)
+
+#define R_PCH_PCIE_STRPFUSECFG 0xFC
+#define B_PCH_PCIE_STRPFUSECFG_PXIP (BIT27 | BIT26 | BIT25 | BIT24)
+#define N_PCH_PCIE_STRPFUSECFG_PXIP 24
+#define B_PCH_PCIE_STRPFUSECFG_RPC (BIT15 | BIT14)
+#define V_PCH_PCIE_STRPFUSECFG_RPC_1_1_1_1 0
+#define V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1 1
+#define V_PCH_PCIE_STRPFUSECFG_RPC_2_2 2
+#define V_PCH_PCIE_STRPFUSECFG_RPC_4 3
+#define N_PCH_PCIE_STRPFUSECFG_RPC 14
+#define B_PCH_PCIE_STRPFUSECFG_MODPHYIOPMDIS BIT9
+#define B_PCH_PCIE_STRPFUSECFG_PLLSHTDWNDIS BIT8
+#define B_PCH_PCIE_STRPFUSECFG_STPGATEDIS BIT7
+#define B_PCH_PCIE_STRPFUSECFG_ASPMDIS BIT6
+#define B_PCH_PCIE_STRPFUSECFG_LDCGDIS BIT5
+#define B_PCH_PCIE_STRPFUSECFG_LTCGDIS BIT4
+#define B_PCH_PCIE_STRPFUSECFG_CDCGDIS BIT3
+#define B_PCH_PCIE_STRPFUSECFG_DESKTOPMOB BIT2
+
+//
+//PCI Express Extended Capability Registers
+//
+
+#define R_PCH_PCIE_EXCAP_OFFSET 0x100
+
+#define R_PCH_PCIE_EX_AECH 0x100 ///< Advanced Error Reporting Capability Header
+#define V_PCH_PCIE_EX_AEC_CV 0x1
+#define R_PCH_PCIE_EX_UEM (R_PCH_PCIE_EX_AECH + R_PCIE_EX_UEM_OFFSET) // Uncorrectable Error Mask
+
+#define R_PCH_PCIE_EX_CES 0x110 ///< Correctable Error Status
+#define B_PCH_PCIE_EX_CES_BD BIT7 ///< Bad DLLP Status
+#define B_PCH_PCIE_EX_CES_BT BIT6 ///< Bad TLP Status
+#define B_PCH_PCIE_EX_CES_RE BIT0 ///< Receiver Error Status
+
+
+//CES.RE, CES.BT, CES.BD
+
+#define R_PCH_PCIE_EX_ACSECH 0x140 ///< ACS Extended Capability Header
+#define V_PCH_PCIE_EX_ACS_CV 0x1
+#define R_PCH_PCIE_EX_ACSCAPR (R_PCH_PCIE_EX_ACSECH + R_PCIE_EX_ACSCAPR_OFFSET)
+
+#define R_PCH_PCIE_EX_L1SECH 0x200 ///< L1 Sub-States Extended Capability Header
+#define V_PCH_PCIE_EX_L1S_CV 0x1
+#define R_PCH_PCIE_EX_L1SCAP (R_PCH_PCIE_EX_L1SECH + R_PCIE_EX_L1SCAP_OFFSET)
+#define R_PCH_PCIE_EX_L1SCTL1 (R_PCH_PCIE_EX_L1SECH + R_PCIE_EX_L1SCTL1_OFFSET)
+#define R_PCH_PCIE_EX_L1SCTL2 (R_PCH_PCIE_EX_L1SECH + R_PCIE_EX_L1SCTL2_OFFSET)
+
+#define R_PCH_PCIE_EX_SPEECH 0x220 ///< Secondary PCI Express Extended Capability Header
+#define V_PCH_PCIE_EX_SPEECH_CV 0x1
+
+#define R_PCH_PCIE_EX_LCTL3 (R_PCH_PCIE_EX_SPEECH + R_PCIE_EX_LCTL3_OFFSET)
+#define R_PCH_PCIE_EX_LES (R_PCH_PCIE_EX_SPEECH + R_PCIE_EX_LES_OFFSET)
+#define R_PCH_PCIE_EX_LECTL (R_PCH_PCIE_EX_SPEECH + R_PCIE_EX_L01EC_OFFSET)
+#define B_PCH_PCIE_EX_LECTL_UPTPH (BIT14 | BIT13 | BIT12)
+#define N_PCH_PCIE_EX_LECTL_UPTPH 12
+#define B_PCH_PCIE_EX_LECTL_UPTP 0x0F00
+#define N_PCH_PCIE_EX_LECTL_UPTP 8
+#define B_PCH_PCIE_EX_LECTL_DPTPH (BIT6 | BIT5 | BIT4)
+#define N_PCH_PCIE_EX_LECTL_DPTPH 4
+#define B_PCH_PCIE_EX_LECTL_DPTP 0x000F
+#define N_PCH_PCIE_EX_LECTL_DPTP 0
+
+#define R_PCH_PCIE_EX_L01EC (R_PCH_PCIE_EX_SPEECH + R_PCIE_EX_L01EC_OFFSET)
+#define R_PCH_PCIE_EX_L23EC (R_PCH_PCIE_EX_SPEECH + R_PCIE_EX_L23EC_OFFSET)
+
+#define R_PCH_PCIE_PCIERTP1 0x300
+#define R_PCH_PCIE_PCIERTP2 0x304
+#define R_PCH_PCIE_PCIENFTS 0x314
+#define R_PCH_PCIE_PCIEL0SC 0x318
+
+#define R_PCH_PCIE_PCIECFG2 0x320
+#define B_PCH_PCIE_PCIECFG2_LBWSSTE BIT30
+#define B_PCH_PCIE_PCIECFG2_RLLG3R BIT27
+#define B_PCH_PCIE_PCIECFG2_CROAOV BIT24
+#define B_PCH_PCIE_PCIECFG2_CROAOE BIT23
+#define B_PCH_PCIE_PCIECFG2_CRSREN BIT22
+#define B_PCH_PCIE_PCIECFG2_PMET (BIT21 | BIT20)
+#define V_PCH_PCIE_PCIECFG2_PMET 1
+#define N_PCH_PCIE_PCIECFG2_PMET 20
+
+#define R_PCH_PCIE_PCIEDBG 0x324
+#define B_PCH_PCIE_PCIEDBG_USSP (BIT27 | BIT26)
+#define B_PCH_PCIE_PCIEDBG_LGCLKSQEXITDBTIMERS (BIT25 | BIT24)
+#define B_PCH_PCIE_PCIEDBG_CTONFAE BIT14
+#define B_PCH_PCIE_PCIEDBG_SQOL0 BIT7
+#define B_PCH_PCIE_PCIEDBG_SPCE BIT5
+#define B_PCH_PCIE_PCIEDBG_LR BIT4
+
+#define R_PCH_PCIE_PCIESTS1 0x328
+#define B_PCH_PCIE_PCIESTS1_LTSMSTATE 0xFF000000
+#define N_PCH_PCIE_PCIESTS1_LTSMSTATE 24
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_DETRDY 0x01
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_DETRDYECINP1CG 0x0E
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_L0 0x33
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_DISWAIT 0x5E
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_DISWAITPG 0x60
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_RECOVERYSPEEDREADY 0x6C
+#define V_PCH_PCIE_PCIESTS1_LTSMSTATE_RECOVERYLNK2DETECT 0x6F
+
+
+#define B_PCH_PCIE_PCIESTS1_LNKSTAT (BIT22 | BIT21 | BIT20 | BIT19)
+#define N_PCH_PCIE_PCIESTS1_LNKSTAT 19
+#define V_PCH_PCIE_PCIESTS1_LNKSTAT_L0 0x7
+
+#define R_PCH_PCIE_PCIESTS2 0x32C
+#define B_PCH_PCIE_PCIESTS2_P4PNCCWSSCMES BIT31
+#define B_PCH_PCIE_PCIESTS2_P3PNCCWSSCMES BIT30
+#define B_PCH_PCIE_PCIESTS2_P2PNCCWSSCMES BIT29
+#define B_PCH_PCIE_PCIESTS2_P1PNCCWSSCMES BIT28
+#define B_PCH_PCIE_PCIESTS2_CLRE 0x0000F000
+#define N_PCH_PCIE_PCIESTS2_CLRE 12
+
+#define R_PCH_PCIE_PCIEALC 0x338
+#define B_PCH_PCIE_PCIEALC_ITLRCLD BIT29
+#define B_PCH_PCIE_PCIEALC_ILLRCLD BIT28
+#define B_PCH_PCIE_PCIEALC_BLKDQDA BIT26
+#define R_PCH_PCIE_PHYCTL4 0x408
+#define B_PCH_PCIE_PHYCTL4_SQDIS BIT27
+
+#define R_PCH_PCIE_PCIEPMECTL2 0x424
+#define B_PCH_PCIE_PCIEPMECTL2_PHYCLPGE BIT11
+#define B_PCH_PCIE_PCIEPMECTL2_FDCPGE BIT8
+#define B_PCH_PCIE_PCIEPMECTL2_DETSCPGE BIT7
+#define B_PCH_PCIE_PCIEPMECTL2_L23RDYSCPGE BIT6
+#define B_PCH_PCIE_PCIEPMECTL2_DISSCPGE BIT5
+#define B_PCH_PCIE_PCIEPMECTL2_L1SCPGE BIT4
+
+#define R_PCH_PCIE_PCE 0x428
+#define B_PCH_PCIE_PCE_HAE BIT5
+#define B_PCH_PCIE_PCE_PMCRE BIT0
+
+#define R_PCH_PCIE_EQCFG1 0x450
+#define S_PCH_PCIE_EQCFG1 4
+#define B_PCH_PCIE_EQCFG1_REC 0xFF000000
+#define N_PCH_PCIE_EQCFG1_REC 24
+#define B_PCH_PCIE_EQCFG1_REIFECE BIT23
+#define N_PCH_PCIE_EQCFG1_LERSMIE 21
+#define B_PCH_PCIE_EQCFG1_LEP23B BIT18
+#define B_PCH_PCIE_EQCFG1_LEP3B BIT17
+#define B_PCH_PCIE_EQCFG1_RTLEPCEB BIT16
+#define B_PCH_PCIE_EQCFG1_RTPCOE BIT15
+#define B_PCH_PCIE_EQCFG1_HPCMQE BIT13
+#define B_PCH_PCIE_EQCFG1_HAED BIT12
+#define B_PCH_PCIE_EQCFG1_EQTS2IRRC BIT7
+#define B_PCH_PCIE_EQCFG1_TUPP BIT1
+
+#define R_PCH_PCIE_RTPCL1 0x454
+#define B_PCH_PCIE_RTPCL1_PCM BIT31
+#define B_PCH_PCIE_RTPCL1_RTPRECL2PL4 0x3F000000
+#define B_PCH_PCIE_RTPCL1_RTPOSTCL1PL3 0xFC0000
+#define B_PCH_PCIE_RTPCL1_RTPRECL1PL2 0x3F000
+#define B_PCH_PCIE_RTPCL1_RTPOSTCL0PL1 0xFC0
+#define B_PCH_PCIE_RTPCL1_RTPRECL0PL0 0x3F
+
+#define R_PCH_PCIE_RTPCL2 0x458
+#define B_PCH_PCIE_RTPCL2_RTPOSTCL3PL 0x3F000
+#define B_PCH_PCIE_RTPCL2_RTPRECL3PL6 0xFC0
+#define B_PCH_PCIE_RTPCL2_RTPOSTCL2PL5 0x3F
+
+#define R_PCH_PCIE_RTPCL3 0x45C
+#define B_PCH_PCIE_RTPCL3_RTPRECL7 0x3F000000
+#define B_PCH_PCIE_RTPCL3_RTPOSTCL6 0xFC0000
+#define B_PCH_PCIE_RTPCL3_RTPRECL6 0x3F000
+#define B_PCH_PCIE_RTPCL3_RTPOSTCL5 0xFC0
+#define B_PCH_PCIE_RTPCL3_RTPRECL5PL10 0x3F
+
+#define R_PCH_PCIE_RTPCL4 0x460
+#define B_PCH_PCIE_RTPCL4_RTPOSTCL9 0x3F000000
+#define B_PCH_PCIE_RTPCL4_RTPRECL9 0xFC0000
+#define B_PCH_PCIE_RTPCL4_RTPOSTCL8 0x3F000
+#define B_PCH_PCIE_RTPCL4_RTPRECL8 0xFC0
+#define B_PCH_PCIE_RTPCL4_RTPOSTCL7 0x3F
+
+#define R_PCH_PCIE_FOMS 0x464
+#define B_PCH_PCIE_FOMS_I (BIT30 | BIT29)
+#define N_PCH_PCIE_FOMS_I 29
+#define B_PCH_PCIE_FOMS_LN 0x1F000000
+#define N_PCH_PCIE_FOMS_LN 24
+#define B_PCH_PCIE_FOMS_FOMSV 0x00FFFFFF
+#define B_PCH_PCIE_FOMS_FOMSV0 0x000000FF
+#define N_PCH_PCIE_FOMS_FOMSV0 0
+#define B_PCH_PCIE_FOMS_FOMSV1 0x0000FF00
+#define N_PCH_PCIE_FOMS_FOMSV1 8
+#define B_PCH_PCIE_FOMS_FOMSV2 0x00FF0000
+#define N_PCH_PCIE_FOMS_FOMSV2 16
+
+#define R_PCH_PCIE_HAEQ 0x468
+#define B_PCH_PCIE_HAEQ_HAPCCPI (BIT31 | BIT30 | BIT29 | BIT28)
+#define N_PCH_PCIE_HAEQ_HAPCCPI 28
+#define B_PCH_PCIE_HAEQ_MACFOMC BIT19
+
+#define R_PCH_PCIE_LTCO1 0x470
+#define B_PCH_PCIE_LTCO1_L1TCOE BIT25
+#define B_PCH_PCIE_LTCO1_L0TCOE BIT24
+#define B_PCH_PCIE_LTCO1_L1TPOSTCO 0xFC0000
+#define N_PCH_PCIE_LTCO1_L1TPOSTCO 18
+#define B_PCH_PCIE_LTCO1_L1TPRECO 0x3F000
+#define N_PCH_PCIE_LTCO1_L1TPRECO 12
+#define B_PCH_PCIE_LTCO1_L0TPOSTCO 0xFC0
+#define N_PCH_PCIE_LTCO1_L0TPOSTCO 6
+#define B_PCH_PCIE_LTCO1_L0TPRECO 0x3F
+#define N_PCH_PCIE_LTCO1_L0TPRECO 0
+
+#define R_PCH_PCIE_LTCO2 0x474
+#define B_PCH_PCIE_LTCO2_L3TCOE BIT25
+#define B_PCH_PCIE_LTCO2_L2TCOE BIT24
+#define B_PCH_PCIE_LTCO2_L3TPOSTCO 0xFC0000
+#define B_PCH_PCIE_LTCO2_L3TPRECO 0x3F000
+#define B_PCH_PCIE_LTCO2_L2TPOSTCO 0xFC0
+#define B_PCH_PCIE_LTCO2_L2TPRECO 0x3F
+
+#define R_PCH_PCIE_G3L0SCTL 0x478
+#define B_PCH_PCIE_G3L0SCTL_G3UCNFTS 0x0000FF00
+#define B_PCH_PCIE_G3L0SCTL_G3CCNFTS 0x000000FF
+
+#define R_PCH_PCIE_EQCFG2 0x47C
+#define B_PCH_PCIE_EQCFG2_NTIC 0xFF000000
+#define B_PCH_PCIE_EQCFG2_EMD BIT23
+#define B_PCH_PCIE_EQCFG2_NTSS (BIT22 | BIT21 | BIT20)
+#define B_PCH_PCIE_EQCFG2_PCET (BIT19 | BIT18 | BIT17 | BIT16)
+#define N_PCH_PCIE_EQCFG2_PCET 16
+#define B_PCH_PCIE_EQCFG2_HAPCSB (BIT15 | BIT14 | BIT13 | BIT12)
+#define N_PCH_PCIE_EQCFG2_HAPCSB 12
+#define B_PCH_PCIE_EQCFG2_NTEME BIT11
+#define B_PCH_PCIE_EQCFG2_MPEME BIT10
+#define B_PCH_PCIE_EQCFG2_REWMETM (BIT9 | BIT8)
+#define B_PCH_PCIE_EQCFG2_REWMET 0xFF
+
+#define R_PCH_PCIE_MM 0x480
+#define B_PCH_PCIE_MM_MSST 0xFFFFFF00
+#define N_PCH_PCIE_MM_MSST 8
+#define B_PCH_PCIE_MM_MSS 0xFF
+
+//
+//PCI Express Extended End Point Capability Registers
+//
+
+#define R_PCH_PCIE_LTRECH_OFFSET 0
+#define R_PCH_PCIE_LTRECH_CID 0x0018
+#define R_PCH_PCIE_LTRECH_MSLR_OFFSET 0x04
+#define R_PCH_PCIE_LTRECH_MNSLR_OFFSET 0x06
+
+
+//
+// PCIE PCRs (PID:SPA SPB SPC SPD SPE SPF)
+//
+#define R_PCH_PCR_SPX_PCD 0 ///< Port configuration and disable
+#define B_PCH_PCR_SPX_PCD_RP1FN (BIT2 | BIT1 | BIT0) ///< Port 1 Function Number
+#define B_PCH_PCR_SPX_PCD_RP1CH BIT3 ///< Port 1 config hide
+#define B_PCH_PCR_SPX_PCD_RP2FN (BIT6 | BIT5 | BIT4) ///< Port 2 Function Number
+#define B_PCH_PCR_SPX_PCD_RP2CH BIT7 ///< Port 2 config hide
+#define B_PCH_PCR_SPX_PCD_RP3FN (BIT10 | BIT9 | BIT8) ///< Port 3 Function Number
+#define B_PCH_PCR_SPX_PCD_RP3CH BIT11 ///< Port 3 config hide
+#define B_PCH_PCR_SPX_PCD_RP4FN (BIT14 | BIT13 | BIT12) ///< Port 4 Function Number
+#define B_PCH_PCR_SPX_PCD_RP4CH BIT15 ///< Port 4 config hide
+#define S_PCH_PCR_SPX_PCD_RP_FIELD 4 ///< 4 bits for each RP FN
+#define B_PCH_PCR_SPX_PCD_P1D BIT16 ///< Port 1 disable
+#define B_PCH_PCR_SPX_PCD_P2D BIT17 ///< Port 2 disable
+#define B_PCH_PCR_SPX_PCD_P3D BIT18 ///< Port 3 disable
+#define B_PCH_PCR_SPX_PCD_P4D BIT19 ///< Port 4 disable
+#define B_PCH_PCR_SPX_PCD_SRL BIT31 ///< Secured Register Lock
+
+#define R_PCH_PCR_SPX_PCIEHBP 0x0004 ///< PCI Express high-speed bypass
+#define B_PCH_PCR_SPX_PCIEHBP_PCIEHBPME BIT0 ///< PCIe HBP mode enable
+#define B_PCH_PCR_SPX_PCIEHBP_PCIEGMO (BIT2 | BIT1) ///< PCIe gen mode override
+#define B_PCH_PCR_SPX_PCIEHBP_PCIETIL0O BIT3 ///< PCIe transmitter-in-L0 override
+#define B_PCH_PCR_SPX_PCIEHBP_PCIERIL0O BIT4 ///< PCIe receiver-in-L0 override
+#define B_PCH_PCR_SPX_PCIEHBP_PCIELRO BIT5 ///< PCIe link recovery override
+#define B_PCH_PCR_SPX_PCIEHBP_PCIELDO BIT6 ///< PCIe link down override
+#define B_PCH_PCR_SPX_PCIEHBP_PCIESSM BIT7 ///< PCIe SKP suppression mode
+#define B_PCH_PCR_SPX_PCIEHBP_PCIESST BIT8 ///< PCIe suppress SKP transmission
+#define B_PCH_PCR_SPX_PCIEHBP_PCIEHBPPS (BIT13 | BIT12) ///< PCIe HBP port select
+#define B_PCH_PCR_SPX_PCIEHBP_CRCSEL (BIT15 | BIT14) ///< CRC select
+#define B_PCH_PCR_SPX_PCIEHBP_PCIEHBPCRC 0xFFFF0000 ///< PCIe HBP CRC
+
+
+//
+// ICC PCR (PID: ICC)
+//
+#define R_PCH_PCR_ICC_TMCSRCCLK 0x1000 ///< Timing Control SRC Clock Register
+#define R_PCH_PCR_ICC_TMCSRCCLK2 0x1004 ///< Timing Control SRC Clock Register 2
+#define R_PCH_PCR_ICC_MSKCKRQ 0x100C ///< Mask Control CLKREQ
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcr.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcr.h
new file mode 100644
index 0000000000..eac209a149
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPcr.h
@@ -0,0 +1,111 @@
+/** @file
+ Register names for PCH private chipset register
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_PCR_H_
+#define _PCH_REGS_PCR_H_
+
+///
+/// Definition for PCR base address (defined in PchReservedResources.h)
+///
+//#define PCH_PCR_BASE_ADDRESS 0xFD000000
+//#define PCH_PCR_MMIO_SIZE 0x01000000
+/**
+ Definition for PCR address
+ The PCR address is used to the PCR MMIO programming
+**/
+#define PCH_PCR_ADDRESS(Pid, Offset) (PCH_PCR_BASE_ADDRESS | ((UINT8)(Pid) << 16) | (UINT16)(Offset))
+
+/**
+ PCH PCR boot script accessing macro
+ Those macros are only available for DXE phase.
+**/
+#define PCH_PCR_BOOT_SCRIPT_WRITE(Width, Pid, Offset, Count, Buffer) \
+ S3BootScriptSaveMemWrite (Width, PCH_PCR_ADDRESS (Pid, Offset), Count, Buffer); \
+ S3BootScriptSaveMemPoll (Width, PCH_PCR_ADDRESS (Pid, Offset), Buffer, Buffer, 1, 1);
+
+#define PCH_PCR_BOOT_SCRIPT_READ_WRITE(Width, Pid, Offset, DataOr, DataAnd) \
+ S3BootScriptSaveMemReadWrite (Width, PCH_PCR_ADDRESS (Pid, Offset), DataOr, DataAnd); \
+ S3BootScriptSaveMemPoll (Width, PCH_PCR_ADDRESS (Pid, Offset), DataOr, DataOr, 1, 1);
+
+
+/**
+ Definition for SBI PID
+ The PCH_SBI_PID defines the PID for PCR MMIO programming and PCH SBI programming as well.
+**/
+#define PID_DMI 0xEF
+#define PID_ESPISPI 0xEE
+#define PID_OPIPHY 0xEC
+#define PID_MODPHY0 0xEA
+#define PID_MODPHY1 0xE9
+#define PID_OTG 0xE5
+#define PID_SPF 0xC9 // Available only in KBL PCH H
+#define PID_SPE 0xE4 // Reserved in SKL PCH LP
+#define PID_SPD 0xE3 // Reserved in SKL PCH LP
+#define PID_SPC 0xE2
+#define PID_SPB 0xE1
+#define PID_SPA 0xE0
+#define PID_ICC 0xDC
+#define PID_DSP 0xD7
+#define PID_FIA 0xCF
+#define PID_SERIALIO 0xCB
+#define PID_USB2 0xCA
+#define PID_LPC 0xC7
+#define PID_SMB 0xC6
+#define PID_ITSS 0xC4
+#define PID_RTC 0xC3
+#define PID_SCS 0xC0 // Reserved in SKL PCH H
+#define PID_ISHBR 0xBF
+#define PID_ISH 0xBE
+#define PID_PSF4 0xBD
+#define PID_PSF3 0xBC
+#define PID_PSF2 0xBB
+#define PID_PSF1 0xBA
+#define PID_DCI 0xB8
+#define PID_MMP0 0xB0 // for SKL-LP only
+#define PID_MODPHY4 0xB0 // for KBL-H only
+#define PID_GPIOCOM0 0xAF
+#define PID_GPIOCOM1 0xAE
+#define PID_GPIOCOM2 0xAD
+#define PID_GPIOCOM3 0xAC
+#define PID_CAM_FLS 0xAA
+#define PID_MODPHY2 0xA9
+#define PID_MODPHY3 0xA8
+#define PID_CAM_CHC 0xA1
+#define PID_CSME12 0x9C
+#define PID_CSME0 0x90
+#define PID_CSME_PSF 0x8F
+#define PID_PSTH 0x89
+
+typedef UINT8 PCH_SBI_PID;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPmc.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPmc.h
new file mode 100644
index 0000000000..d4c048ffe3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPmc.h
@@ -0,0 +1,652 @@
+/** @file
+ Register names for PCH PMC device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_PMC_H_
+#define _PCH_REGS_PMC_H_
+
+//
+// PMC Registers (D31:F2)
+//
+#define PCI_DEVICE_NUMBER_PCH_PMC 31
+#define PCI_FUNCTION_NUMBER_PCH_PMC 2
+
+#define R_PCH_PMC_PM_DATA_BAR 0x10
+#define B_PCH_PMC_PM_DATA_BAR 0xFFFFC000
+#define R_PCH_PMC_ACPI_BASE 0x40
+#define B_PCH_PMC_ACPI_BASE_BAR 0xFFFC
+#define R_PCH_PMC_ACPI_CNT 0x44
+#define B_PCH_PMC_ACPI_CNT_PWRM_EN BIT8 ///< PWRM enable
+#define B_PCH_PMC_ACPI_CNT_ACPI_EN BIT7 ///< ACPI eanble
+#define B_PCH_PMC_ACPI_CNT_SCIS (BIT2 | BIT1 | BIT0) ///< SCI IRQ select
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ9 0
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ10 1
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ11 2
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ20 4
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ21 5
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ22 6
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ23 7
+#define R_PCH_PMC_PWRM_BASE 0x48
+#define B_PCH_PMC_PWRM_BASE_BAR 0xFFFF0000 ///< PWRM must be 64KB alignment to align the source decode.
+#define R_PCH_PMC_GEN_PMCON_A 0xA0
+#define B_PCH_PMC_GEN_PMCON_A_DC_PP_DIS BIT30
+#define B_PCH_PMC_GEN_PMCON_A_DSX_PP_DIS BIT29
+#define B_PCH_PMC_GEN_PMCON_A_AG3_PP_EN BIT28
+#define B_PCH_PMC_GEN_PMCON_A_SX_PP_EN BIT27
+#define B_PCH_PMC_GEN_PMCON_A_DISB BIT23
+#define B_PCH_PMC_GEN_PMCON_A_MEM_SR BIT21
+#define B_PCH_PMC_GEN_PMCON_A_MS4V BIT18
+#define B_PCH_PMC_GEN_PMCON_A_GBL_RST_STS BIT16
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_OPI_PLL_SD_INC0 BIT13
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_SPXB_CG_INC0 BIT12
+#define B_PCH_PMC_GEN_PMCON_A_BIOS_PCI_EXP_EN BIT10
+#define B_PCH_PMC_GEN_PMCON_A_PWRBTN_LVL BIT9
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_L1LOW_C0 BIT7
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_L1LOW_OPI_ON BIT6
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_L1LOW_BCLKREQ_ON BIT5
+#define B_PCH_PMC_GEN_PMCON_A_SMI_LOCK BIT4
+#define B_PCH_PMC_GEN_PMCON_A_ESPI_SMI_LOCK BIT3 ///< ESPI SMI lock
+#define B_PCH_PMC_GEN_PMCON_A_PER_SMI_SEL 0x0003
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_64S 0x0000
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_32S 0x0001
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_16S 0x0002
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_8S 0x0003
+#define R_PCH_PMC_GEN_PMCON_B 0xA4
+#define B_PCH_PMC_GEN_PMCON_B_SLPSX_STR_POL_LOCK BIT18 ///< Lock down SLP_S3/SLP_S4 Minimum Assertion width
+#define B_PCH_PMC_GEN_PMCON_B_ACPI_BASE_LOCK BIT17 ///< Lock ACPI BASE at 0x40, only cleared by reset when set
+#define B_PCH_PMC_GEN_PMCON_B_PM_DATA_BAR_DIS BIT16
+#define B_PCH_PMC_GEN_PMCON_B_PME_B0_S5_DIS BIT15
+#define B_PCH_PMC_GEN_PMCON_B_SUS_PWR_FLR BIT14
+#define B_PCH_PMC_GEN_PMCON_B_WOL_EN_OVRD BIT13
+#define B_PCH_PMC_GEN_PMCON_B_DISABLE_SX_STRETCH BIT12
+#define B_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW 0xC00
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_60US 0x000
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_1MS 0x400
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_50MS 0x800
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_2S 0xC00
+#define B_PCH_PMC_GEN_PMCON_B_HOST_RST_STS BIT9
+#define B_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL 0xC0
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_64MS 0xC0
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_32MS 0x80
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_16MS 0x40
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_1_5MS 0x00
+#define B_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW 0x30
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_1S 0x30
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_2S 0x20
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_3S 0x10
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_4S 0x00
+#define B_PCH_PMC_GEN_PMCON_B_SLP_S4_ASE BIT3
+#define B_PCH_PMC_GEN_PMCON_B_RTC_PWR_STS BIT2
+#define B_PCH_PMC_GEN_PMCON_B_PWR_FLR BIT1
+#define B_PCH_PMC_GEN_PMCON_B_AFTERG3_EN BIT0
+#define R_PCH_PMC_BM_CX_CNF 0xA8
+#define B_PCH_PMC_BM_CX_CNF_STORAGE_BREAK_EN BIT31
+#define B_PCH_PMC_BM_CX_CNF_PCIE_BREAK_EN BIT30
+#define B_PCH_PMC_BM_CX_CNF_AZ_BREAK_EN BIT24
+#define B_PCH_PMC_BM_CX_CNF_DPSN_BREAK_EN BIT19
+#define B_PCH_PMC_BM_CX_CNF_XHCI_BREAK_EN BIT17
+#define B_PCH_PMC_BM_CX_CNF_SATA3_BREAK_EN BIT16
+#define B_PCH_PMC_BM_CX_CNF_SCRATCHPAD BIT15
+#define B_PCH_PMC_BM_CX_CNF_PHOLD_BM_STS_BLOCK BIT14
+#define B_PCH_PMC_BM_CX_CNF_MASK_CF BIT11
+#define B_PCH_PMC_BM_CX_CNF_BM_STS_ZERO_EN BIT10
+#define B_PCH_PMC_BM_CX_CNF_PM_SYNC_MSG_MODE BIT9
+#define R_PCH_PMC_ETR3 0xAC
+#define B_PCH_PMC_ETR3_CF9LOCK BIT31 ///< CF9h Lockdown
+#define B_PCH_PMC_ETR3_USB_CACHE_DIS BIT21
+#define B_PCH_PMC_ETR3_CF9GR BIT20 ///< CF9h Global Reset
+#define B_PCH_PMC_ETR3_SKIP_HOST_RST_HS BIT19
+#define B_PCH_PMC_ETR3_CWORWRE BIT18
+
+//
+// ACPI and legacy I/O register offsets from ACPIBASE
+//
+#define R_PCH_ACPI_PM1_STS 0x00
+#define S_PCH_ACPI_PM1_STS 2
+#define B_PCH_ACPI_PM1_STS_WAK BIT15
+#define B_PCH_ACPI_PM1_STS_PCIEXP_WAKE_STS BIT14
+#define B_PCH_ACPI_PM1_STS_PRBTNOR BIT11
+#define B_PCH_ACPI_PM1_STS_RTC BIT10
+#define B_PCH_ACPI_PM1_STS_PWRBTN BIT8
+#define B_PCH_ACPI_PM1_STS_GBL BIT5
+#define B_PCH_ACPI_PM1_STS_BM BIT4
+#define B_PCH_ACPI_PM1_STS_TMROF BIT0
+#define N_PCH_ACPI_PM1_STS_WAK 15
+#define N_PCH_ACPI_PM1_STS_PCIEXP_WAKE_STS 14
+#define N_PCH_ACPI_PM1_STS_PRBTNOR 11
+#define N_PCH_ACPI_PM1_STS_RTC 10
+#define N_PCH_ACPI_PM1_STS_PWRBTN 8
+#define N_PCH_ACPI_PM1_STS_GBL 5
+#define N_PCH_ACPI_PM1_STS_BM 4
+#define N_PCH_ACPI_PM1_STS_TMROF 0
+
+#define R_PCH_ACPI_PM1_EN 0x02
+#define S_PCH_ACPI_PM1_EN 2
+#define B_PCH_ACPI_PM1_EN_PCIEXP_WAKE_DIS BIT14
+#define B_PCH_ACPI_PM1_EN_RTC BIT10
+#define B_PCH_ACPI_PM1_EN_PWRBTN BIT8
+#define B_PCH_ACPI_PM1_EN_GBL BIT5
+#define B_PCH_ACPI_PM1_EN_TMROF BIT0
+#define N_PCH_ACPI_PM1_EN_PCIEXP_WAKE_DIS 14
+#define N_PCH_ACPI_PM1_EN_RTC 10
+#define N_PCH_ACPI_PM1_EN_PWRBTN 8
+#define N_PCH_ACPI_PM1_EN_GBL 5
+#define N_PCH_ACPI_PM1_EN_TMROF 0
+
+#define R_PCH_ACPI_PM1_CNT 0x04
+#define S_PCH_ACPI_PM1_CNT 4
+#define B_PCH_ACPI_PM1_CNT_SLP_EN BIT13
+#define B_PCH_ACPI_PM1_CNT_SLP_TYP (BIT12 | BIT11 | BIT10)
+#define V_PCH_ACPI_PM1_CNT_S0 0
+#define V_PCH_ACPI_PM1_CNT_S1 BIT10
+#define V_PCH_ACPI_PM1_CNT_S3 (BIT12 | BIT10)
+#define V_PCH_ACPI_PM1_CNT_S4 (BIT12 | BIT11)
+#define V_PCH_ACPI_PM1_CNT_S5 (BIT12 | BIT11 | BIT10)
+#define B_PCH_ACPI_PM1_CNT_GBL_RLS BIT2
+#define B_PCH_ACPI_PM1_CNT_BM_RLD BIT1
+#define B_PCH_ACPI_PM1_CNT_SCI_EN BIT0
+
+#define R_PCH_ACPI_PM1_TMR 0x08
+#define V_PCH_ACPI_TMR_FREQUENCY 3579545
+#define B_PCH_ACPI_PM1_TMR_VAL 0xFFFFFF
+#define V_PCH_ACPI_PM1_TMR_MAX_VAL 0x1000000 ///< The timer is 24 bit overflow
+
+#define R_PCH_SMI_EN 0x30
+#define S_PCH_SMI_EN 4
+#define B_PCH_SMI_EN_LEGACY_USB3 BIT31
+#define B_PCH_SMI_EN_GPIO_UNLOCK_SMI BIT27
+#define B_PCH_SMI_EN_LEGACY_USB2 BIT17
+#define B_PCH_SMI_EN_PERIODIC BIT14
+#define B_PCH_SMI_EN_TCO BIT13
+#define B_PCH_SMI_EN_MCSMI BIT11
+#define B_PCH_SMI_EN_BIOS_RLS BIT7
+#define B_PCH_SMI_EN_SWSMI_TMR BIT6
+#define B_PCH_SMI_EN_APMC BIT5
+#define B_PCH_SMI_EN_ON_SLP_EN BIT4
+#define B_PCH_SMI_EN_LEGACY_USB BIT3
+#define B_PCH_SMI_EN_BIOS BIT2
+#define B_PCH_SMI_EN_EOS BIT1
+#define B_PCH_SMI_EN_GBL_SMI BIT0
+#define N_PCH_SMI_EN_LEGACY_USB3 31
+#define N_PCH_SMI_EN_ESPI 28
+#define N_PCH_SMI_EN_GPIO_UNLOCK 27
+#define N_PCH_SMI_EN_INTEL_USB2 18
+#define N_PCH_SMI_EN_LEGACY_USB2 17
+#define N_PCH_SMI_EN_PERIODIC 14
+#define N_PCH_SMI_EN_TCO 13
+#define N_PCH_SMI_EN_MCSMI 11
+#define N_PCH_SMI_EN_BIOS_RLS 7
+#define N_PCH_SMI_EN_SWSMI_TMR 6
+#define N_PCH_SMI_EN_APMC 5
+#define N_PCH_SMI_EN_ON_SLP_EN 4
+#define N_PCH_SMI_EN_LEGACY_USB 3
+#define N_PCH_SMI_EN_BIOS 2
+#define N_PCH_SMI_EN_EOS 1
+#define N_PCH_SMI_EN_GBL_SMI 0
+
+#define R_PCH_SMI_STS 0x34
+#define S_PCH_SMI_STS 4
+#define B_PCH_SMI_STS_LEGACY_USB3 BIT31
+#define B_PCH_SMI_STS_GPIO_UNLOCK BIT27
+#define B_PCH_SMI_STS_SPI BIT26
+#define B_PCH_SMI_STS_MONITOR BIT21
+#define B_PCH_SMI_STS_PCI_EXP BIT20
+#define B_PCH_SMI_STS_PATCH BIT19
+#define B_PCH_SMI_STS_INTEL_USB2 BIT18
+#define B_PCH_SMI_STS_LEGACY_USB2 BIT17
+#define B_PCH_SMI_STS_SMBUS BIT16
+#define B_PCH_SMI_STS_SERIRQ BIT15
+#define B_PCH_SMI_STS_PERIODIC BIT14
+#define B_PCH_SMI_STS_TCO BIT13
+#define B_PCH_SMI_STS_DEVMON BIT12
+#define B_PCH_SMI_STS_MCSMI BIT11
+#define B_PCH_SMI_STS_GPIO_SMI BIT10
+#define B_PCH_SMI_STS_GPE0 BIT9
+#define B_PCH_SMI_STS_PM1_STS_REG BIT8
+#define B_PCH_SMI_STS_SWSMI_TMR BIT6
+#define B_PCH_SMI_STS_APM BIT5
+#define B_PCH_SMI_STS_ON_SLP_EN BIT4
+#define B_PCH_SMI_STS_LEGACY_USB BIT3
+#define B_PCH_SMI_STS_BIOS BIT2
+#define N_PCH_SMI_STS_LEGACY_USB3 31
+#define N_PCH_SMI_STS_ESPI 28
+#define N_PCH_SMI_STS_GPIO_UNLOCK 27
+#define N_PCH_SMI_STS_SPI 26
+#define N_PCH_SMI_STS_MONITOR 21
+#define N_PCH_SMI_STS_PCI_EXP 20
+#define N_PCH_SMI_STS_PATCH 19
+#define N_PCH_SMI_STS_INTEL_USB2 18
+#define N_PCH_SMI_STS_LEGACY_USB2 17
+#define N_PCH_SMI_STS_SMBUS 16
+#define N_PCH_SMI_STS_SERIRQ 15
+#define N_PCH_SMI_STS_PERIODIC 14
+#define N_PCH_SMI_STS_TCO 13
+#define N_PCH_SMI_STS_DEVMON 12
+#define N_PCH_SMI_STS_MCSMI 11
+#define N_PCH_SMI_STS_GPIO_SMI 10
+#define N_PCH_SMI_STS_GPE0 9
+#define N_PCH_SMI_STS_PM1_STS_REG 8
+#define N_PCH_SMI_STS_SWSMI_TMR 6
+#define N_PCH_SMI_STS_APM 5
+#define N_PCH_SMI_STS_ON_SLP_EN 4
+#define N_PCH_SMI_STS_LEGACY_USB 3
+#define N_PCH_SMI_STS_BIOS 2
+
+#define R_PCH_ACPI_GPE_CNTL 0x40
+#define B_PCH_ACPI_GPE_CNTL_SWGPE_CTRL BIT17
+
+#define R_PCH_DEVACT_STS 0x44
+#define S_PCH_DEVACT_STS 2
+#define B_PCH_DEVACT_STS_MASK 0x13E1
+#define B_PCH_DEVACT_STS_KBC BIT12
+#define B_PCH_DEVACT_STS_PIRQDH BIT9
+#define B_PCH_DEVACT_STS_PIRQCG BIT8
+#define B_PCH_DEVACT_STS_PIRQBF BIT7
+#define B_PCH_DEVACT_STS_PIRQAE BIT6
+#define B_PCH_DEVACT_STS_D0_TRP BIT0
+#define N_PCH_DEVACT_STS_KBC 12
+#define N_PCH_DEVACT_STS_PIRQDH 9
+#define N_PCH_DEVACT_STS_PIRQCG 8
+#define N_PCH_DEVACT_STS_PIRQBF 7
+#define N_PCH_DEVACT_STS_PIRQAE 6
+
+#define R_PCH_ACPI_PM2_CNT 0x50
+#define B_PCH_ACPI_PM2_CNT_ARB_DIS BIT0
+
+#define R_PCH_OC_WDT_CTL 0x54
+#define B_PCH_OC_WDT_CTL_RLD BIT31
+#define B_PCH_OC_WDT_CTL_ICCSURV_STS BIT25
+#define B_PCH_OC_WDT_CTL_NO_ICCSURV_STS BIT24
+#define B_PCH_OC_WDT_CTL_FORCE_ALL BIT15
+#define B_PCH_OC_WDT_CTL_EN BIT14
+#define B_PCH_OC_WDT_CTL_ICCSURV BIT13
+#define B_PCH_OC_WDT_CTL_LCK BIT12
+#define B_PCH_OC_WDT_CTL_TOV_MASK 0x3FF
+#define B_PCH_OC_WDT_CTL_FAILURE_STS BIT23
+#define B_PCH_OC_WDT_CTL_UNXP_RESET_STS BIT22
+#define B_PCH_OC_WDT_CTL_AFTER_POST 0x3F0000
+#define V_PCH_OC_WDT_CTL_STATUS_FAILURE 1
+#define V_PCH_OC_WDT_CTL_STATUS_OK 0
+
+#define R_PCH_ACPI_GPE0_STS_31_0 0x80
+#define R_PCH_ACPI_GPE0_STS_63_32 0x84
+#define R_PCH_ACPI_GPE0_STS_95_64 0x88
+#define R_PCH_ACPI_GPE0_STS_127_96 0x8C
+#define S_PCH_ACPI_GPE0_STS_127_96 4
+#define B_PCH_ACPI_GPE0_STS_127_96_WADT BIT18
+#define B_PCH_ACPI_GPE0_STS_127_96_LAN_WAKE BIT16
+#define B_PCH_ACPI_GPE0_STS_127_96_PME_B0 BIT13
+#define B_PCH_ACPI_GPE0_STS_127_96_ME_SCI BIT12
+#define B_PCH_ACPI_GPE0_STS_127_96_PME BIT11
+#define B_PCH_ACPI_GPE0_STS_127_96_BATLOW BIT10
+#define B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP BIT9
+#define B_PCH_ACPI_GPE0_STS_127_96_RI BIT8
+#define B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK BIT7
+#define B_PCH_ACPI_GPE0_STS_127_96_TC0SCI BIT6
+#define B_PCH_ACPI_GPE0_STS_127_96_SWGPE BIT2
+#define B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG BIT1
+#define N_PCH_ACPI_GPE0_STS_127_96_PME_B0 13
+#define N_PCH_ACPI_GPE0_STS_127_96_PME 11
+#define N_PCH_ACPI_GPE0_STS_127_96_BATLOW 10
+#define N_PCH_ACPI_GPE0_STS_127_96_PCI_EXP 9
+#define N_PCH_ACPI_GPE0_STS_127_96_RI 8
+#define N_PCH_ACPI_GPE0_STS_127_96_SMB_WAK 7
+#define N_PCH_ACPI_GPE0_STS_127_96_TC0SCI 6
+#define N_PCH_ACPI_GPE0_STS_127_96_SWGPE 2
+#define N_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG 1
+
+#define R_PCH_ACPI_GPE0_EN_31_0 0x90
+#define R_PCH_ACPI_GPE0_EN_63_32 0x94
+#define R_PCH_ACPI_GPE0_EN_95_64 0x98
+#define R_PCH_ACPI_GPE0_EN_127_96 0x9C
+#define S_PCH_ACPI_GPE0_EN_127_96 4
+#define B_PCH_ACPI_GPE0_EN_127_96_WADT BIT18
+#define B_PCH_ACPI_GPE0_EN_127_96_LAN_WAKE BIT16
+#define B_PCH_ACPI_GPE0_EN_127_96_PME_B0 BIT13
+#define B_PCH_ACPI_GPE0_EN_127_96_ME_SCI BIT12
+#define B_PCH_ACPI_GPE0_EN_127_96_PME BIT11
+#define B_PCH_ACPI_GPE0_EN_127_96_BATLOW BIT10
+#define B_PCH_ACPI_GPE0_EN_127_96_PCI_EXP BIT9
+#define B_PCH_ACPI_GPE0_EN_127_96_RI BIT8
+#define B_PCH_ACPI_GPE0_EN_127_96_TC0SCI BIT6
+#define B_PCH_ACPI_GPE0_EN_127_96_SWGPE BIT2
+#define B_PCH_ACPI_GPE0_EN_127_96_HOT_PLUG BIT1
+#define N_PCH_ACPI_GPE0_EN_127_96_PME_B0 13
+#define N_PCH_ACPI_GPE0_EN_127_96_USB3 12
+#define N_PCH_ACPI_GPE0_EN_127_96_PME 11
+#define N_PCH_ACPI_GPE0_EN_127_96_BATLOW 10
+#define N_PCH_ACPI_GPE0_EN_127_96_PCI_EXP 9
+#define N_PCH_ACPI_GPE0_EN_127_96_RI 8
+#define N_PCH_ACPI_GPE0_EN_127_96_TC0SCI 6
+#define N_PCH_ACPI_GPE0_EN_127_96_SWGPE 2
+#define N_PCH_ACPI_GPE0_EN_127_96_HOT_PLUG 1
+
+
+//
+// TCO register I/O map
+//
+#define R_PCH_TCO_RLD 0x0
+#define R_PCH_TCO_DAT_IN 0x2
+#define R_PCH_TCO_DAT_OUT 0x3
+#define R_PCH_TCO1_STS 0x04
+#define S_PCH_TCO1_STS 2
+#define B_PCH_TCO1_STS_DMISERR BIT12
+#define B_PCH_TCO1_STS_DMISMI BIT10
+#define B_PCH_TCO1_STS_DMISCI BIT9
+#define B_PCH_TCO1_STS_BIOSWR BIT8
+#define B_PCH_TCO1_STS_NEWCENTURY BIT7
+#define B_PCH_TCO1_STS_TIMEOUT BIT3
+#define B_PCH_TCO1_STS_TCO_INT BIT2
+#define B_PCH_TCO1_STS_SW_TCO_SMI BIT1
+#define B_PCH_TCO1_STS_NMI2SMI BIT0
+#define N_PCH_TCO1_STS_DMISMI 10
+#define N_PCH_TCO1_STS_BIOSWR 8
+#define N_PCH_TCO1_STS_NEWCENTURY 7
+#define N_PCH_TCO1_STS_TIMEOUT 3
+#define N_PCH_TCO1_STS_SW_TCO_SMI 1
+#define N_PCH_TCO1_STS_NMI2SMI 0
+
+#define R_PCH_TCO2_STS 0x06
+#define S_PCH_TCO2_STS 2
+#define B_PCH_TCO2_STS_SMLINK_SLV_SMI BIT4
+#define B_PCH_TCO2_STS_BAD_BIOS BIT3
+#define B_PCH_TCO2_STS_BOOT BIT2
+#define B_PCH_TCO2_STS_SECOND_TO BIT1
+#define B_PCH_TCO2_STS_INTRD_DET BIT0
+#define N_PCH_TCO2_STS_INTRD_DET 0
+
+#define R_PCH_TCO1_CNT 0x08
+#define S_PCH_TCO1_CNT 2
+#define B_PCH_TCO_CNT_LOCK BIT12
+#define B_PCH_TCO_CNT_TMR_HLT BIT11
+#define B_PCH_TCO_CNT_NMI2SMI_EN BIT9
+#define B_PCH_TCO_CNT_NMI_NOW BIT8
+#define N_PCH_TCO_CNT_NMI2SMI_EN 9
+
+#define R_PCH_TCO2_CNT 0x0A
+#define S_PCH_TCO2_CNT 2
+#define B_PCH_TCO2_CNT_OS_POLICY 0x0030
+#define B_PCH_TCO2_CNT_GPI11_ALERT_DISABLE 0x0008
+#define B_PCH_TCO2_CNT_INTRD_SEL 0x0006
+#define N_PCH_TCO2_CNT_INTRD_SEL 2
+
+#define R_PCH_TCO_MESSAGE1 0x0C
+#define R_PCH_TCO_MESSAGE2 0x0D
+#define R_PCH_TCO_WDCNT 0x0E
+#define R_PCH_TCO_SW_IRQ_GEN 0x10
+#define B_PCH_TCO_IRQ12_CAUSE BIT1
+#define B_PCH_TCO_IRQ1_CAUSE BIT0
+#define R_PCH_TCO_TMR 0x12
+
+//
+// PWRM Registers
+//
+#define R_PCH_WADT_AC 0x0 ///< Wake Alarm Device Timer: AC
+#define R_PCH_WADT_DC 0x4 ///< Wake Alarm Device Timer: DC
+#define R_PCH_WADT_EXP_AC 0x8 ///< Wake Alarm Device Expired Timer: AC
+#define R_PCH_WADT_EXP_DC 0xC ///< Wake Alarm Device Expired Timer: DC
+#define R_PCH_PWRM_PRSTS 0x10 ///< Power and Reset Status
+#define B_PCH_PWRM_PRSTS_VE_WD_TMR_STS BIT7 ///< VE Watchdog Timer Status
+#define B_PCH_PWRM_PRSTS_WOL_OVR_WK_STS BIT5
+#define B_PCH_PWRM_PRSTS_FIELD_1 BIT4
+#define B_PCH_PWRM_PRSTS_ME_WAKE_STS BIT0
+#define R_PCH_PWRM_14 0x14
+#define R_PCH_PWRM_CFG 0x18 ///< Power Management Configuration
+#define B_PCH_PWRM_CFG_ALLOW_24_OSC_SD BIT29 ///< Allow 24MHz Crystal Oscillator Shutdown
+#define B_PCH_PWRM_CFG_ALLOW_USB2_CORE_PG BIT25 ///< Allow USB2 Core Power Gating
+#define B_PCH_PWRM_CFG_RTC_DS_WAKE_DIS BIT21 ///< RTC Wake from Deep S4/S5 Disable
+#define B_PCH_PWRM_CFG_SSMAW_MASK (BIT19 | BIT18) ///< SLP_SUS# Min Assertion Width
+#define V_PCH_PWRM_CFG_SSMAW_4S (BIT19 | BIT18) ///< 4 seconds
+#define V_PCH_PWRM_CFG_SSMAW_1S BIT19 ///< 1 second
+#define V_PCH_PWRM_CFG_SSMAW_0_5S BIT18 ///< 0.5 second (500ms)
+#define V_PCH_PWRM_CFG_SSMAW_0S 0 ///< 0 second
+#define B_PCH_PWRM_CFG_SAMAW_MASK (BIT17 | BIT16) ///< SLP_A# Min Assertion Width
+#define V_PCH_PWRM_CFG_SAMAW_2S (BIT17 | BIT16) ///< 2 seconds
+#define V_PCH_PWRM_CFG_SAMAW_98ms BIT17 ///< 98ms
+#define V_PCH_PWRM_CFG_SAMAW_4S BIT16 ///< 4 seconds
+#define V_PCH_PWRM_CFG_SAMAW_0S 0 ///< 0 second
+#define B_PCH_PWRM_CFG_RPCD_MASK (BIT9 | BIT8) ///< Reset Power Cycle Duration
+#define V_PCH_PWRM_CFG_RPCD_1S (BIT9 | BIT8) ///< 1-2 seconds
+#define V_PCH_PWRM_CFG_RPCD_2S BIT9 ///< 2-3 seconds
+#define V_PCH_PWRM_CFG_RPCD_3S BIT8 ///< 3-4 seconds
+#define V_PCH_PWRM_CFG_RPCD_4S 0 ///< 4-5 seconds (Default)
+#define R_PCH_PWRM_PCH_PM_STS 0x1C ///< Contains misc. fields used to record PCH power management events
+#define B_PCH_PWRM_PCH_PM_STS_PMC_MSG_FULL_STS BIT24 ///< MTPMC transport mechanism full indication
+#define R_PCH_PWRM_MTPMC 0x20 ///< Message to PMC
+#define V_PCH_PWRM_MTPMC_COMMAND_PG_LANE_0_15 0xE ///< Command to override lanes 0-15 power gating
+#define V_PCH_PWRM_MTPMC_COMMAND_PG_LANE_16_31 0xF ///< Command to override lanes 16-31 power gating
+#define B_PCH_PWRM_MTPMC_PG_CMD_DATA 0xFFFF0000 ///< Data part of PowerGate Message to PMC
+#define N_PCH_PWRM_MTPMC_PG_CMD_DATA 16
+#define R_PCH_PWRM_PCH_PM_STS2 0x24 ///< PCH Power Management Status
+#define R_PCH_PWRM_S3_PWRGATE_POL 0x28 ///< S3 Power Gating Policies
+#define B_PCH_PWRM_S3DC_GATE_SUS BIT1 ///< Deep S3 Enable in DC Mode
+#define B_PCH_PWRM_S3AC_GATE_SUS BIT0 ///< Deep S3 Enable in AC Mode
+#define R_PCH_PWRM_S4_PWRGATE_POL 0x2C ///< Deep S4 Power Policies
+#define B_PCH_PWRM_S4DC_GATE_SUS BIT1 ///< Deep S4 Enable in DC Mode
+#define B_PCH_PWRM_S4AC_GATE_SUS BIT0 ///< Deep S4 Enable in AC Mode
+#define R_PCH_PWRM_S5_PWRGATE_POL 0x30 ///< Deep S5 Power Policies
+#define B_PCH_PWRM_S5DC_GATE_SUS BIT15 ///< Deep S5 Enable in DC Mode
+#define B_PCH_PWRM_S5AC_GATE_SUS BIT14 ///< Deep S5 Enable in AC Mode
+#define R_PCH_PWRM_DSX_CFG 0x34 ///< Deep SX Configuration
+#define B_PCH_PWRM_DSX_CFG_WAKE_PIN_DSX_EN BIT2 ///< WAKE# Pin DeepSx Enable
+#define B_PCH_PWRM_DSX_CFG_ACPRES_PD_DSX_DIS BIT1 ///< AC_PRESENT pin pulldown in DeepSx disable
+#define B_PCH_PWRM_DSX_CFG_LAN_WAKE_EN BIT0 ///< LAN_WAKE Pin DeepSx Enable
+#define R_PCH_PWRM_CFG2 0x3C ///< Power Management Configuration Reg 2
+#define B_PCH_PWRM_CFG2_PBOP (BIT31 | BIT30 | BIT29) ///< Power Button Override Period (PBOP)
+#define N_PCH_PWRM_CFG2_PBOP 29 ///< Power Button Override Period (PBOP)
+#define B_PCH_PWRM_CFG2_PB_DIS BIT28 ///< Power Button Native Mode Disable (PB_DIS)
+#define B_PCH_PWRM_CFG2_DRAM_RESET_CTL BIT26 ///< DRAM RESET# control
+#define R_PCH_PWRM_EN_SN_SLOW_RING 0x48 ///< Enable Snoop Request to SLOW_RING
+#define R_PCH_PWRM_EN_SN_SLOW_RING2 0x4C ///< Enable Snoop Request to SLOW_RING 2nd Reg
+#define R_PCH_PWRM_EN_SN_SA 0x50 ///< Enable Snoop Request to SA
+#define R_PCH_PWRM_EN_SN_SA2 0x54 ///< Enable Snoop Request to SA 2nd Reg
+#define R_PCH_PWRM_EN_SN_SLOW_RING_CF 0x58 ///< Enable Snoop Request to SLOW_RING_CF
+#define R_PCH_PWRM_EN_NS_SA 0x68 ///< Enable Non-Snoop Request to SA
+#define R_PCH_PWRM_EN_CW_SLOW_RING 0x80 ///< Enable Clock Wake to SLOW_RING
+#define R_PCH_PWRM_EN_CW_SLOW_RING2 0x84 ///< Enable Clock Wake to SLOW_RING 2nd Reg
+#define R_PCH_PWRM_EN_CW_SA 0x88 ///< Enable Clock Wake to SA
+#define R_PCH_PWRM_EN_CW_SA2 0x8C ///< Enable Clock Wake to SA 2nd Reg
+#define R_PCH_PWRM_EN_CW_SLOW_RING_CF 0x98 ///< Enable Clock Wake to SLOW_RING_CF
+#define R_PCH_PWRM_EN_PA_SLOW_RING 0xA8 ///< Enable Pegged Active to SLOW_RING
+#define R_PCH_PWRM_EN_PA_SLOW_RING2 0xAC ///< Enable Pegged Active to SLOW_RING 2nd Reg
+#define R_PCH_PWRM_EN_PA_SA 0xB0 ///< Enable Pegged Active to SA
+#define R_PCH_PWRM_EN_PA_SA2 0xB4 ///< Enable Pegged Active to SA 2nd Reg
+#define R_PCH_PWRM_EN_MISC_EVENT 0xC0 ///< Enable Misc PM_SYNC Events
+#define R_PCH_PWRM_PMSYNC_TPR_CONFIG 0xC4
+#define B_PCH_PWRM_PMSYNC_TPR_CONFIG_LOCK BIT31
+#define B_PCH_PWRM_PMSYNC_PCH2CPU_TT_EN BIT26
+#define B_PCH_PWRM_PMSYNC_PCH2CPU_TT_STATE (BIT25 | BIT24)
+#define N_PCH_PWRM_PMSYNC_PCH2CPU_TT_STATE 24
+#define V_PCH_PWRM_PMSYNC_PCH2CPU_TT_STATE_1 1
+#define R_PCH_PWRM_PMSYNC_MISC_CFG 0xC8
+#define B_PCH_PWRM_PMSYNC_PM_SYNC_LOCK BIT15 ///< PM_SYNC Configuration Lock
+#define B_PCH_PWRM_PMSYNC_GPIO_D_SEL BIT11
+#define B_PCH_PWRM_PMSYNC_GPIO_C_SEL BIT10
+#define R_PCH_PWRM_PM_SYNC_STATE_HYS 0xD0 ///< PM_SYNC State Hysteresis
+#define R_PCH_PWRM_PM_SYNC_MODE 0xD4 ///< PM_SYNC Pin Mode
+#define R_PCH_PWRM_CFG3 0xE0 ///< Power Management Configuration Reg 3
+#define B_PCH_PWRM_CFG3_DSX_WLAN_PP_EN BIT16 ///< Deep-Sx WLAN Phy Power Enable
+#define B_PCH_PWRM_CFG3_HOST_WLAN_PP_EN BIT17 ///< Host Wireless LAN Phy Power Enable
+#define B_PCH_PWRM_CFG3_PWRG_LOCK BIT2 ///< Lock power gating override messages
+#define R_PCH_PWRM_PM_DOWN_PPB_CFG 0xE4 ///< PM_DOWN PCH_POWER_BUDGET CONFIGURATION
+#define R_PCH_PWRM_CFG4 0xE8 ///< Power Management Configuration Reg 4
+#define B_PCH_PWRM_CFG4_U2_PHY_PG_EN BIT30 ///< USB2 PHY SUS Well Power Gating Enable
+#define B_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR (0x000001FF) ///< CPU I/O VR Ramp Duration, [8:0]
+#define N_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR 0
+#define V_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR_70US 0x007
+#define V_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR_240US 0x018
+#define R_PCH_PWRM_CPU_EPOC 0xEC
+#define R_PCH_PWRM_VR_MISC_CTL 0x100
+#define B_PCH_PWRM_VR_MISC_CTL_VIDSOVEN BIT3
+#define R_PCH_PWRM_GPIO_CFG 0x120
+#define B_PCH_PWRM_GPIO_CFG_GPE0_DW2 (BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_PWRM_GPIO_CFG_GPE0_DW2 8
+#define B_PCH_PWRM_GPIO_CFG_GPE0_DW1 (BIT7 | BIT6 | BIT5 | BIT4)
+#define N_PCH_PWRM_GPIO_CFG_GPE0_DW1 4
+#define B_PCH_PWRM_GPIO_CFG_GPE0_DW0 (BIT3 | BIT2 | BIT1 | BIT0)
+#define N_PCH_PWRM_GPIO_CFG_GPE0_DW0 0
+#define R_PCH_PWRM_PM_SYNC_MODE_C0 0xF4 ///< PM_SYNC Pin Mode in C0
+#define R_PCH_PWRM_ACPI_TMR_CTL 0xFC
+#define B_PCH_PWRM_ACPI_TMR_DIS BIT1
+#define R_PCH_PWRM_124 0x124
+#define R_PCH_PWRM_SLP_S0_RESIDENCY_COUNTER 0x13C
+#define R_PCH_PWRM_MODPHY_PM_CFG1 0x200
+#define R_PCH_PWRM_MODPHY_PM_CFG1_MLSXSWPGP 0xFFFF
+#define R_PCH_PWRM_MODPHY_PM_CFG2 0x204 ///< ModPHY Power Management Configuration Reg 2
+#define B_PCH_PWRM_MODPHY_PM_CFG2_MLSPDDGE BIT30 ///< ModPHY Lane SUS Power Domain Dynamic Gating Enable
+#define B_PCH_PWRM_MODPHY_PM_CFG2_EMFC BIT29 ///< Enable ModPHY FET Control
+#define B_PCH_PWRM_MODPHY_PM_CFG2_EFRT (BIT28 | BIT27 | BIT26 | BIT25 | BIT24) ///< External FET Ramp Time
+#define N_PCH_PWRM_MODPHY_PM_CFG2_EFRT 24
+#define V_PCH_PWRM_MODPHY_PM_CFG2_EFRT_200US 0x0A
+#define B_PCH_PWRM_MODPHY_PM_CFG2_ASLOR_UFS BIT16 ///< UFS ModPHY SPD SPD Override
+#define R_PCH_PWRM_MODPHY_PM_CFG3 0x208 ///< ModPHY Power Management Configuration Reg 3
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_UFS BIT16 ///< UFS ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_XDCI BIT15 ///< xDCI ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_XHCI BIT14 ///< xHCI ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_GBE BIT13 ///< GbE ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_SATA BIT12 ///< SATA ModPHY SPD RT Request
+#define R_PCH_PWRM_30C 0x30C
+#define R_PCH_PWRM_OBFF_CFG 0x314 ///< OBFF Configuration
+#define R_PCH_PWRM_31C 0x31C
+#define R_PCH_PWRM_CPPM_MISC_CFG 0x320 ///< CPPM Miscellaneous Configuration
+#define R_PCH_PWRM_CPPM_CG_POL1A 0x324 ///< CPPM Clock Gating Policy Reg 1
+#define R_PCH_PWRM_CPPM_CG_POL2A 0x340 ///< CPPM Clock Gating Policy Reg 3
+#define R_PCH_PWRM_34C 0x34C
+#define R_PCH_PWRM_CPPM_CG_POL3A 0x3A8 ///< CPPM Clock Gating Policy Reg 5
+#define B_PCH_PWRM_CPPM_CG_POLXA_CPPM_GX_QUAL BIT30 ///< CPPM Shutdown Qualifier Enable for Clock Source Group X
+#define B_PCH_PWRM_CPPM_CG_POLXA_LTR_GX_THRESH (0x000001FF) ///< LTR Threshold for Clock Source Group X, [8:0]
+#define R_PCH_PWRM_3D0 0x3D0
+#define R_PCH_PWRM_CPPM_MPG_POL1A 0x3E0 ///< CPPM ModPHY Gating Policy Reg 1A
+#define B_PCH_PWRM_CPPM_MPG_POL1A_CPPM_MODPHY_QUAL BIT30 ///< CPPM Shutdown Qualifier Enable for ModPHY
+#define B_PCH_PWRM_CPPM_MPG_POL1A_LT_MODPHY_SEL BIT29 ///< ASLT/PLT Selection for ModPHY
+#define B_PCH_PWRM_CPPM_MPG_POL1A_LTR_MODPHY_THRESH (0x000001FF) ///< LTR Threshold for ModPHY, [8:0]
+#define R_PCH_PWRM_CS_SD_CTL1 0x3E8 ///< Clock Source Shutdown Control Reg 1
+#define B_PCH_PWRM_CS_SD_CTL1_CS5_CTL_CFG (BIT22 | BIT21 | BIT20) ///< Clock Source 5 Control Configuration
+#define N_PCH_PWRM_CS_SD_CTL1_CS5_CTL_CFG 20
+#define B_PCH_PWRM_CS_SD_CTL1_CS1_CTL_CFG (BIT2 | BIT1 | BIT0) ///< Clock Source 1 Control Configuration
+#define N_PCH_PWRM_CS_SD_CTL1_CS1_CTL_CFG 0
+#define R_PCH_PWRM_CS_SD_CTL2 0x3EC ///< Clock Source Shutdown Control Reg 2
+#define R_PCH_PWRM_HSWPGCR1 0x5D0
+#define B_PCH_PWRM_SW_PG_CTRL_LOCK BIT31
+#define B_PCH_PWRM_DFX_SW_PG_CTRL BIT0
+#define R_PCH_PWRM_600 0x600
+#define R_PCH_PWRM_604 0x604
+#define R_PCH_PWRM_ST_PG_FDIS_PMC_1 0x620 ///< Static PG Related Function Disable Register 1
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_ST_FDIS_LK BIT31 ///< Static Function Disable Lock (ST_FDIS_LK)
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_CAM_FDIS_PMC BIT6 ///< Camera Function Disable (PMC Version) (CAM_FDIS_PMC)
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_ISH_FDIS_PMC BIT5 ///< SH Function Disable (PMC Version) (ISH_FDIS_PMC)
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_GBE_FDIS_PMC BIT0 ///< GBE Function Disable (PMC Version) (GBE_FDIS_PMC)
+#define R_PCH_PWRM_ST_PG_FDIS_PMC_2 0x624 ///< Static Function Disable Control Register 2
+#define V_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_FDIS_PMC 0x7FF ///< Static Function Disable Control Register 2
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_GSPI1_FDIS_PMC BIT10 ///< SerialIo Controller GSPI Device 1 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_GSPI0_FDIS_PMC BIT9 ///< SerialIo Controller GSPI Device 0 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_UART2_FDIS_PMC BIT8 ///< SerialIo Controller UART Device 2 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_UART1_FDIS_PMC BIT7 ///< SerialIo Controller UART Device 1 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_UART0_FDIS_PMC BIT6 ///< SerialIo Controller UART Device 0 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C5_FDIS_PMC BIT5 ///< SerialIo Controller I2C Device 5 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C4_FDIS_PMC BIT4 ///< SerialIo Controller I2C Device 4 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C3_FDIS_PMC BIT3 ///< SerialIo Controller I2C Device 3 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C2_FDIS_PMC BIT2 ///< SerialIo Controller I2C Device 2 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C1_FDIS_PMC BIT1 ///< SerialIo Controller I2C Device 1 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C0_FDIS_PMC BIT0 ///< SerialIo Controller I2C Device 0 Function Disable
+#define R_PCH_PWRM_NST_PG_FDIS_1 0x628
+#define B_PCH_PWRM_NST_PG_FDIS_1_SCC_FDIS_PMC BIT25 ///< SCC Function Disable. This is only avaiable in B0 onward.
+#define B_PCH_PWRM_NST_PG_FDIS_1_XDCI_FDIS_PMC BIT24 ///< XDCI Function Disable. This is only avaiable in B0 onward.
+#define B_PCH_PWRM_NST_PG_FDIS_1_ADSP_FDIS_PMC BIT23 ///< ADSP Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_SATA_FDIS_PMC BIT22 ///< SATA Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C3_FDIS_PMC BIT13 ///< PCIe Controller C Port 3 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C2_FDIS_PMC BIT12 ///< PCIe Controller C Port 2 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C1_FDIS_PMC BIT11 ///< PCIe Controller C Port 1 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C0_FDIS_PMC BIT10 ///< PCIe Controller C Port 0 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B3_FDIS_PMC BIT9 ///< PCIe Controller B Port 3 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B2_FDIS_PMC BIT8 ///< PCIe Controller B Port 2 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B1_FDIS_PMC BIT7 ///< PCIe Controller B Port 1 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B0_FDIS_PMC BIT6 ///< PCIe Controller B Port 0 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A3_FDIS_PMC BIT5 ///< PCIe Controller A Port 3 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A2_FDIS_PMC BIT4 ///< PCIe Controller A Port 2 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A1_FDIS_PMC BIT3 ///< PCIe Controller A Port 1 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A0_FDIS_PMC BIT2 ///< PCIe Controller A Port 0 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_XHCI_FDIS_PMC BIT0 ///< XHCI Function Disable
+#define R_PCH_PWRM_FUSE_DIS_RD_1 0x640 ///< Fuse Disable Read 1 Register
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E3_FUSE_DIS BIT21 ///< PCIe Controller E Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E2_FUSE_DIS BIT20 ///< PCIe Controller E Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E1_FUSE_DIS BIT19 ///< PCIe Controller E Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E0_FUSE_DIS BIT18 ///< PCIe Controller E Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D3_FUSE_DIS BIT17 ///< PCIe Controller D Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D2_FUSE_DIS BIT16 ///< PCIe Controller D Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D1_FUSE_DIS BIT15 ///< PCIe Controller D Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D0_FUSE_DIS BIT14 ///< PCIe Controller D Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C3_FUSE_DIS BIT13 ///< PCIe Controller C Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C2_FUSE_DIS BIT12 ///< PCIe Controller C Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C1_FUSE_DIS BIT11 ///< PCIe Controller C Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C0_FUSE_DIS BIT10 ///< PCIe Controller C Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B3_FUSE_DIS BIT9 ///< PCIe Controller B Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B2_FUSE_DIS BIT8 ///< PCIe Controller B Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B1_FUSE_DIS BIT7 ///< PCIe Controller B Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B0_FUSE_DIS BIT6 ///< PCIe Controller B Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A3_FUSE_DIS BIT5 ///< PCIe Controller A Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A2_FUSE_DIS BIT4 ///< PCIe Controller A Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A1_FUSE_DIS BIT3 ///< PCIe Controller A Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A0_FUSE_DIS BIT2 ///< PCIe Controller A Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_XHCI_FUSE_DIS BIT0 ///< XHCI Fuse Disable
+#define R_PCH_PWRM_FUSE_DIS_RD_2 0x644 ///< Fuse Disable Read 2 Register
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SPC_SS_DIS BIT25 ///< SPC Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SPB_SS_DIS BIT24 ///< SPB Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SPA_SS_DIS BIT23 ///< SPA Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_PSTH_FUSE_SS_DIS BIT21 ///< PSTH Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_DMI_FUSE_SS_DIS BIT20 ///< DMI Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_OTG_FUSE_SS_DIS BIT19 ///< OTG Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_XHCI_SS_DIS BIT18 ///< XHCI Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_FIA_FUSE_SS_DIS BIT17 ///< FIA Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_DSP_FUSE_SS_DIS BIT16 ///< DSP Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SATA_FUSE_SS_DIS BIT15 ///< SATA Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_ICC_FUSE_SS_DIS BIT14 ///< ICC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_LPC_FUSE_SS_DIS BIT13 ///< LPC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_RTC_FUSE_SS_DIS BIT12 ///< RTC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_P2S_FUSE_SS_DIS BIT11 ///< P2S Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_TRSB_FUSE_SS_DIS BIT10 ///< TRSB Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SMB_FUSE_SS_DIS BIT9 ///< SMB Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_ITSS_FUSE_SS_DIS BIT8 ///< ITSS Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SERIALIO_FUSE_SS_DIS BIT6 ///< SerialIo Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SCC_FUSE_SS_DIS BIT4 ///< SCC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_P2D_FUSE_SS_DIS BIT3 ///< P2D Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_CAM_FUSE_SS_DIS BIT2 ///< Camera Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_ISH_FUSE_SS_DIS BIT1 ///< ISH Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_GBE_FUSE_SS_DIS BIT0 ///< GBE Fuse or Soft Strap Disable
+#define R_PCH_PWRM_FUSE_DIS_RD_3 0x648 ///< Static PG Fuse and Soft Strap Disable Read Register 3
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA3_FUSE_SS_DIS BIT3 ///< PNCRA3 Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA2_FUSE_SS_DIS BIT2 ///< PNCRA2 Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA1_FUSE_SS_DIS BIT1 ///< PNCRA1 Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA_FUSE_SS_DIS BIT0 ///< PNCRA Fuse or Soft Strap Disable
+
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h
new file mode 100644
index 0000000000..c52f1e721d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h
@@ -0,0 +1,364 @@
+/** @file
+ Register definition for PSF component
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_PSF_H_
+#define _PCH_REGS_PSF_H_
+
+//
+// Private chipset regsiter (Memory space) offset definition
+// The PCR register defines is used for PCR MMIO programming and PCH SBI programming as well.
+//
+
+//
+// PSFx segment registers
+//
+#define R_PCH_PCR_PSF_GLOBAL_CONFIG 0x4000 ///< PSF Segment Global Configuration Register
+#define B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG BIT4
+#define B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG BIT3
+#define R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS0 0x4010 ///< PSF Segment Rootspace Configuration Register
+#define R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS1 0x4014
+#define B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_ENADDRP2P BIT1
+#define B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_VTDEN BIT0
+#define R_PCH_PCR_PSF_PORT_CONFIG_PG0_PORT0 0x4018 ///< PSF Segment Port Configuration Register
+
+#define S_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR 4
+#define S_PCH_PSF_TARGET_GNTCNT_RELOAD 4
+#define B_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR_GNT_CNT_RELOAD 0x1F
+#define B_PCH_PSF_TARGET_GNTCNT_RELOAD_GNT_CNT_RELOAD 0x1F
+
+//
+// PSFx PCRs definitions
+//
+#define R_PCH_PCR_PSFX_T0_SHDW_BAR0 0 ///< PCI BAR0
+#define R_PCH_PCR_PSFX_T0_SHDW_BAR1 0x04 ///< PCI BAR1
+#define R_PCH_PCR_PSFX_T0_SHDW_BAR2 0x08 ///< PCI BAR2
+#define R_PCH_PCR_PSFX_T0_SHDW_BAR3 0x0C ///< PCI BAR3
+#define R_PCH_PCR_PSFX_T0_SHDW_BAR4 0x10 ///< PCI BAR4
+#define R_PCH_PCR_PSFX_T0_SHDW_PCIEN 0x1C ///< PCI configuration space enable bits
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR0DIS BIT16 ///< Disable BAR0
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR1DIS BIT17 ///< Disable BAR1
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS BIT18 ///< Disable BAR2
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS BIT19 ///< Disable BAR3
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR4DIS BIT20 ///< Disable BAR4
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR5DIS BIT21 ///< Disable BAR5
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS BIT8 ///< Function disable
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_MEMEN BIT1 ///< Memory decoding enable
+#define B_PCH_PCR_PSFX_T0_SHDW_PCIEN_IOEN BIT0 ///< IO decoding enable
+#define R_PCH_PCR_PSFX_T0_SHDW_PMCSR 0x20 ///< PCI power management configuration
+#define B_PCH_PCR_PSFX_T0_SHDW_PMCSR_PWRST (BIT1 | BIT0) ///< Power status
+#define R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS 0x38 ///< PCI configuration disable
+#define B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS BIT0 ///< config disable
+
+#define R_PCH_PCR_PSFX_T1_SHDW_PCIEN 0x3C ///< PCI configuration space enable bits
+#define B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS BIT8 ///< Function disable
+#define B_PCH_PCR_PSFX_T1_SHDW_PCIEN_MEMEN BIT1 ///< Memory decoding enable
+#define B_PCH_PCR_PSFX_T1_SHDW_PCIEN_IOEN BIT0 ///< IO decoding enable
+
+#define B_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE 0x01F0 ///< device number
+#define N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE 4
+#define B_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION (BIT3 | BIT2 | BIT1) ///< function number
+#define N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION 1
+
+#define V_PCH_LP_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB 0x38A00
+#define V_PCH_H_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB 0x38B00
+
+//
+// PSF1 PCRs
+//
+// PSF1 PCH-LP Specific Base Address
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_GBE_REG_BASE 0x0200 ///< D31F6 PSF base address (GBE)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_CAM_REG_BASE 0x0300 ///< D20F3 PSF base address (CAM)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_CSE_WLAN_REG_BASE 0x0500 ///< D22F7 PSF base address (CSME: WLAN)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_HECI3_REG_BASE 0x0700 ///< D22F4 PSF base address (CSME: HECI3)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_HECI2_REG_BASE 0x0800 ///< D22F1 PSF base address (CSME: HECI2)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_CSE_UMA_REG_BASE 0x0900 ///< D18F3 PSF base address (CSME: CSE UMA)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_HECI1_REG_BASE 0x0A00 ///< D22F0 PSF base address (CSME: HECI1)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_KT_REG_BASE 0x0B00 ///< D22F3 PSF base address (CSME: KT)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_IDER_REG_BASE 0x0C00 ///< D22F2 PSF base address (CSME: IDER)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_CLINK_REG_BASE 0x0D00 ///< D18F1 PSF base address (CSME: CLINK)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_PMT_REG_BASE 0x0E00 ///< D18F2 PSF base address (CSME: PMT)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_KVM_REG_BASE 0x0F00 ///< D18F0 PSF base address (CSME: KVM)
+#define R_PCH_LP_PCR_PSF1_T0_SHDW_SATA_REG_BASE 0x1000 ///< PCH-LP D23F0 PSF base address (SATA)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE12_REG_BASE 0x2000 ///< PCH-LP D29F3 PSF base address (PCIE PORT 12)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE11_REG_BASE 0x2100 ///< PCH-LP D29F2 PSF base address (PCIE PORT 11)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE10_REG_BASE 0x2200 ///< PCH-LP D29F1 PSF base address (PCIE PORT 10)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE09_REG_BASE 0x2300 ///< PCH-LP D29F0 PSF base address (PCIE PORT 09)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE08_REG_BASE 0x2400 ///< PCH-LP D28F7 PSF base address (PCIE PORT 08)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE07_REG_BASE 0x2500 ///< PCH-LP D28F6 PSF base address (PCIE PORT 07)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE06_REG_BASE 0x2600 ///< PCH-LP D28F5 PSF base address (PCIE PORT 06)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE05_REG_BASE 0x2700 ///< PCH-LP D28F4 PSF base address (PCIE PORT 05)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE04_REG_BASE 0x2800 ///< PCH-LP D28F3 PSF base address (PCIE PORT 04)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE03_REG_BASE 0x2900 ///< PCH-LP D28F2 PSF base address (PCIE PORT 03)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE02_REG_BASE 0x2A00 ///< PCH-LP D28F1 PSF base address (PCIE PORT 02)
+#define R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE 0x2B00 ///< PCH-LP D28F0 PSF base address (PCIE PORT 01)
+
+// PSF1 PCH-H Specific Base Address
+#define R_PCH_H_PCR_PSF1_T0_SHDW_CSE_WLAN_REG_BASE 0x0200 ///< D22F7 PSF base address (CSME: WLAN)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_HECI3_REG_BASE 0x0300 ///< SPT-H D22F4 PSF base address (CSME: HECI3)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_HECI2_REG_BASE 0x0400 ///< SPT-H D22F1 PSF base address (CSME: HECI2)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_CSE_UMA_REG_BASE 0x0500 ///< D18F3 PSF base address (CSME: CSE UMA)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_HECI1_REG_BASE 0x0600 ///< SPT-H D22F0 PSF base address (CSME: HECI1)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_KT_REG_BASE 0x0700 ///< SPT-H D22F3 PSF base address (CSME: KT)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_IDER_REG_BASE 0x0800 ///< SPT-H D22F2 PSF base address (CSME: IDER)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_CLINK_REG_BASE 0x0900 ///< D18F1 PSF base address (CSME: CLINK)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_PMT_REG_BASE 0x0A00 ///< D18F2 PSF base address (CSME: PMT)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_KVM_REG_BASE 0x0B00 ///< D18F0 PSF base address (CSME: KVM)
+#define R_PCH_H_PCR_PSF1_T0_SHDW_SATA_REG_BASE 0x0C00 ///< PCH-H D23F0 PSF base address (SATA)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE20_REG_BASE 0x2000 ///< PCH-H D27F3 PSF base address (PCIE PORT 20)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE19_REG_BASE 0x2100 ///< PCH-H D27F2 PSF base address (PCIE PORT 19)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE18_REG_BASE 0x2200 ///< PCH-H D27F1 PSF base address (PCIE PORT 18)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE17_REG_BASE 0x2300 ///< PCH-H D27F0 PSF base address (PCIE PORT 17)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE16_REG_BASE 0x2400 ///< PCH-H D29F7 PSF base address (PCIE PORT 16)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE15_REG_BASE 0x2500 ///< PCH-H D29F6 PSF base address (PCIE PORT 15)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE14_REG_BASE 0x2600 ///< PCH-H D29F5 PSF base address (PCIE PORT 14)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE13_REG_BASE 0x2700 ///< PCH-H D29F4 PSF base address (PCIE PORT 13)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE12_REG_BASE 0x2800 ///< PCH-H D29F3 PSF base address (PCIE PORT 10)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE11_REG_BASE 0x2900 ///< PCH-H D29F2 PSF base address (PCIE PORT 11)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE10_REG_BASE 0x2A00 ///< PCH-H D29F1 PSF base address (PCIE PORT 10)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE09_REG_BASE 0x2B00 ///< PCH-H D29F0 PSF base address (PCIE PORT 09)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE08_REG_BASE 0x2C00 ///< PCH-H D28F7 PSF base address (PCIE PORT 08)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE07_REG_BASE 0x2D00 ///< PCH-H D28F6 PSF base address (PCIE PORT 07)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE06_REG_BASE 0x2E00 ///< PCH-H D28F5 PSF base address (PCIE PORT 06)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE05_REG_BASE 0x2F00 ///< PCH-H D28F4 PSF base address (PCIE PORT 05)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE04_REG_BASE 0x3000 ///< PCH-H D28F3 PSF base address (PCIE PORT 04)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE03_REG_BASE 0x3100 ///< PCH-H D28F2 PSF base address (PCIE PORT 03)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE02_REG_BASE 0x3200 ///< PCH-H D28F1 PSF base address (PCIE PORT 02)
+#define R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE 0x3300 ///< PCH-H D28F0 PSF base address (PCIE PORT 01)
+
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE24_REG_BASE 0x2000 ///< PCH-H D27F7 PSF base address (PCIE PORT 24)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE23_REG_BASE 0x2100 ///< PCH-H D27F6 PSF base address (PCIE PORT 23)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE22_REG_BASE 0x2200 ///< PCH-H D27F5 PSF base address (PCIE PORT 22)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE21_REG_BASE 0x2300 ///< PCH-H D27F4 PSF base address (PCIE PORT 21)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE20_REG_BASE 0x2400 ///< PCH-H D27F3 PSF base address (PCIE PORT 20)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE19_REG_BASE 0x2500 ///< PCH-H D27F2 PSF base address (PCIE PORT 19)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE18_REG_BASE 0x2600 ///< PCH-H D27F1 PSF base address (PCIE PORT 18)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE17_REG_BASE 0x2700 ///< PCH-H D27F0 PSF base address (PCIE PORT 17)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE16_REG_BASE 0x2800 ///< PCH-H D29F7 PSF base address (PCIE PORT 16)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE15_REG_BASE 0x2900 ///< PCH-H D29F6 PSF base address (PCIE PORT 15)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE14_REG_BASE 0x2A00 ///< PCH-H D29F5 PSF base address (PCIE PORT 14)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE13_REG_BASE 0x2B00 ///< PCH-H D29F4 PSF base address (PCIE PORT 13)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE12_REG_BASE 0x2C00 ///< PCH-H D29F3 PSF base address (PCIE PORT 10)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE11_REG_BASE 0x2D00 ///< PCH-H D29F2 PSF base address (PCIE PORT 11)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE10_REG_BASE 0x2E00 ///< PCH-H D29F1 PSF base address (PCIE PORT 10)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE09_REG_BASE 0x2F00 ///< PCH-H D29F0 PSF base address (PCIE PORT 09)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE08_REG_BASE 0x3000 ///< PCH-H D28F7 PSF base address (PCIE PORT 08)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE07_REG_BASE 0x3100 ///< PCH-H D28F6 PSF base address (PCIE PORT 07)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE06_REG_BASE 0x3200 ///< PCH-H D28F5 PSF base address (PCIE PORT 06)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE05_REG_BASE 0x3300 ///< PCH-H D28F4 PSF base address (PCIE PORT 05)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE04_REG_BASE 0x3400 ///< PCH-H D28F3 PSF base address (PCIE PORT 04)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE03_REG_BASE 0x3500 ///< PCH-H D28F2 PSF base address (PCIE PORT 03)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE02_REG_BASE 0x3600 ///< PCH-H D28F1 PSF base address (PCIE PORT 02)
+#define R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE 0x3700 ///< PCH-H D28F0 PSF base address (PCIE PORT 01)
+
+
+// Other PSF1 PCRs definition
+#define R_PCH_H_PCR_PSF1_PSF_PORT_CONFIG_PG1_PORT7 0x4038 ///< PSF Port Configuration Register
+#define R_PCH_LP_PCR_PSF1_PSF_PORT_CONFIG_PG1_PORT7 0x403C ///< PSF Port Configuration Register
+#define R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI 0x4050 ///< Multicast Control Register
+#define R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI 0x4060 ///< Destination ID
+#define R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI 0x4048 ///< Multicast Control Register
+#define R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI 0x4058 ///< Destination ID
+#define R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI 0x404C ///< Multicast Control Register
+#define R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI 0x405C ///< Destination ID
+
+
+//PSF 1 Multicast Message Configuration
+
+#define R_PCH_PCR_PSF1_RC_OWNER_RS0 0x4008 ///< Destination ID
+
+#define B_PCH_PCR_PSF1_TARGET_CHANNELID 0xFF
+#define B_PCH_PCR_PSF1_TARGET_PORTID 0x7F00
+#define N_PCH_PCR_PSF1_TARGET_PORTID 8
+#define B_PCH_PCR_PSF1_TARGET_PORTGROUPID BIT15
+#define N_PCH_PCR_PSF1_TARGET_PORTGROUPID 15
+#define B_PCH_PCR_PSF1_TARGET_PSFID 0xFF0000
+#define N_PCH_PCR_PSF1_TARGET_PSFID 16
+#define B_PCH_PCR_PSF1_TARGET_CHANMAP BIT31
+
+#define V_PCH_PCR_PSF1_RC_OWNER_RS0_CHANNELID 0
+#define V_PCH_PCR_PSF1_RC_OWNER_RS0_PORTID 10
+#define V_PCH_PCR_PSF1_RC_OWNER_RS0_PORTGROUPID_DOWNSTREAM 1
+#define V_PCH_PCR_PSF1_RC_OWNER_RS0_PSFID_PMT 0
+#define V_PCH_PCR_PSF1_RC_OWNER_RS0_PSFID_PSF1 1
+
+#define V_PCH_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGTX_MCTP1_PORTGROUPID_UPSTREAM 0
+#define V_PCH_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGTX_MCTP1_PORTGROUPID_DOWNSTREAM 1
+#define V_PCH_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGTX_MCTP1_PSFID_PSF1 1
+
+#define R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1 0x4058 ///< Multicast Control Register
+#define R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGT0_MCTP1 0x409C ///< Destination ID
+#define R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1 0x4050 ///< Multicast Control Register
+#define R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGT0_MCTP1 0x40B4 ///< Destination ID
+#define R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1 0x4054 ///< Multicast Control Register
+#define R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGT0_MCTP1 0x40C8 ///< Destination ID
+
+#define B_PCH_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1_MULTCEN BIT0
+#define B_PCH_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1_NUMMC 0xFE
+#define N_PCH_PCR_PSF1_PSF_MC_CONTROL_MCAST1_RS0_MCTP1_NUMMC 1
+
+#define V_PCH_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGTX_MCTP1_CHANNELID_DMI 0
+#define V_PCH_PCR_PSF1_PSF_MC_AGENT_MCAST1_RS0_TGTX_MCTP1_PORTID_DMI 0
+
+
+
+//
+// controls the PCI configuration header of a PCI function
+//
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0 0x4198 ///< SPA
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F1 0x419C ///< SPA
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F2 0x41A0 ///< SPA
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F3 0x41A4 ///< SPA
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F4 0x41A8 ///< SPB
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F5 0x41AC ///< SPB
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F6 0x41B0 ///< SPB
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F7 0x41B4 ///< SPB
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F0 0x41B8 ///< SPC
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F1 0x41BC ///< SPC
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F2 0x41C0 ///< SPC
+#define R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F3 0x41C4 ///< SPC
+
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0 0x41C0 ///< SPA
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F1 0x41C4 ///< SPA
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F2 0x41C8 ///< SPA
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F3 0x41CC ///< SPA
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F4 0x41D0 ///< SPB
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F5 0x41D4 ///< SPB
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F6 0x41D8 ///< SPB
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F7 0x41DC ///< SPB
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F0 0x41E0 ///< SPC
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F1 0x41E4 ///< SPC
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F2 0x41E8 ///< SPC
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F3 0x41EC ///< SPC
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F4 0x41F0 ///< SPD
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F5 0x41F4 ///< SPD
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F6 0x41F8 ///< SPD
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F7 0x41FC ///< SPD
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F0 0x4200 ///< SPE
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F1 0x4204 ///< SPE
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F2 0x4208 ///< SPE
+#define R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F3 0x420C ///< SPE
+
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0 0x4274 ///< SPA
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F1 0x4278 ///< SPA
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F2 0x427C ///< SPA
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F3 0x4280 ///< SPA
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F4 0x4284 ///< SPB
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F5 0x4288 ///< SPB
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F6 0x428C ///< SPB
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPB_D28_F7 0x4290 ///< SPB
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F0 0x4294 ///< SPC
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F1 0x4298 ///< SPC
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F2 0x429C ///< SPC
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPC_D29_F3 0x42A0 ///< SPC
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F4 0x42A4 ///< SPD
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F5 0x42A8 ///< SPD
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F6 0x42AC ///< SPD
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPD_D29_F7 0x42B0 ///< SPD
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F0 0x42B4 ///< SPE
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F1 0x42B8 ///< SPE
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F2 0x42BC ///< SPE
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPE_D27_F3 0x42C0 ///< SPE
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPF_D27_F4 0x42C4 ///< SPF
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPF_D27_F5 0x42C8 ///< SPF
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPF_D27_F6 0x42CC ///< SPF
+#define R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPF_D27_F7 0x42D0 ///< SPF
+
+//
+// PSF1 grant count registers
+//
+#define R_PCH_LP_PSF1_DEV_GNTCNT_RELOAD_DGCR0 0x41CC
+#define R_PCH_LP_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0 0x45D0
+
+#define R_SKL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0 0x4214
+#define R_KBL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0 0x42D8
+#define R_SKL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0 0x46DC
+#define R_KBL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0 0x4834
+
+//
+// PSF2 PCRs (PID:PSF2)
+//
+#define R_PCH_PCR_PSF2_T0_SHDW_TRH_REG_BASE 0x0100 ///< D20F2 PSF base address (Thermal). // LP&H
+// PSF2 PCH-LP Specific Base Address
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_UFS_REG_BASE 0x0200 ///< D30F7 PSF base address (SCC: UFS)
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_SDCARD_REG_BASE 0x0300 ///< D30F6 PSF base address (SCC: SDCard)
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_SDIO_REG_BASE 0x0400 ///< D30F5 PSF base address (SCC: SDIO)
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_EMMC_REG_BASE 0x0500 ///< D30F4 PSF base address (SCC: eMMC)
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_OTG_REG_BASE 0x0600 ///< D20F1 PSF base address (USB device controller: OTG)
+#define R_PCH_LP_PCR_PSF2_T0_SHDW_XHCI_REG_BASE 0x0700 ///< D20F0 PSF base address (XHCI)
+// PSF2 PCH-H Specific Base Address
+#define R_PCH_H_PCR_PSF2_T0_SHDW_OTG_REG_BASE 0x0200 ///< D20F1 PSF base address (USB device controller: OTG)
+#define R_PCH_H_PCR_PSF2_T0_SHDW_XHCI_REG_BASE 0x0300 ///< D20F0 PSF base address (XHCI)
+
+//
+// PSF3 PCRs (PID:PSF3)
+//
+#define R_PCH_PCR_PSF3_T0_SHDW_P2SB_REG_BASE 0x0100 ///< D31F1 PSF base address (P2SB) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_ACPI_REG_BASE 0x0200 ///< D20F4 PSF base address (TraceHub ACPI) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE 0x0300 ///< D31F7 PSF base address (TraceHub PCI) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_LPC_REG_BASE 0x0400 ///< D31F0 PSF base address (LPC) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_SMBUS_REG_BASE 0x0500 ///< D31F4 PSF base address (SMBUS) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_PMC_REG_BASE 0x0700 ///< D31F2 PSF base address (PMC) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_ISH_REG_BASE 0x0800 ///< D19F0 PSF base address (ISH) // LP&H
+#define R_PCH_PCR_PSF3_T0_SHDW_AUD_REG_BASE 0x1900 ///< D31F3 PSF base address (HDA, ADSP) // LP&H
+// PSF3 PCH-LP Specific Base Address
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C4_REG_BASE 0x0900 ///< D25F2 PSF base address (SerialIo: I2C4)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_SPI1_REG_BASE 0x0A00 ///< D30F3 PSF base address (SerialIo: SPI1)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_SPI0_REG_BASE 0x0B00 ///< D30F2 PSF base address (SerialIo: SPI0)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_UART1_REG_BASE 0x0C00 ///< D30F1 PSF base address (SerialIo: UART1)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_UART0_REG_BASE 0x0D00 ///< D30F0 PSF base address (SerialIo: UART0)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C5_REG_BASE 0x0E00 ///< D25F1 PSF base address (SerialIo: I2C5)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_UART2_REG_BASE 0x0F00 ///< D25F0 PSF base address (SerialIo: UART2)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C3_REG_BASE 0x1000 ///< D21F3 PSF base address (SerialIo: I2C3)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C2_REG_BASE 0x1100 ///< D21F2 PSF base address (SerialIo: I2C2)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C1_REG_BASE 0x1200 ///< D21F1 PSF base address (SerialIo: I2C1)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_I2C0_REG_BASE 0x1300 ///< D21F0 PSF base address (SerialIo: I2C0)
+#define R_PCH_LP_PCR_PSF3_T0_SHDW_SPI_SPI_REG_BASE 0x1600 ///< D31F5 PSF base address (SPI SPI)
+// PSF3 PCH-H Specific Base Address
+#define R_PCH_H_PCR_PSF3_T0_SHDW_SPI1_REG_BASE 0x0900 ///< D30F3 PSF base address (SerialIo: SPI1)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_SPI0_REG_BASE 0x0A00 ///< D30F2 PSF base address (SerialIo: SPI0)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_UART1_REG_BASE 0x0B00 ///< D30F1 PSF base address (SerialIo: UART1)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_UART0_REG_BASE 0x0C00 ///< D30F0 PSF base address (SerialIo: UART0)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_UART2_REG_BASE 0x0D00 ///< D25F0 PSF base address (SerialIo: UART2)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_I2C3_REG_BASE 0x0E00 ///< D21F3 PSF base address (SerialIo: I2C3)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_I2C2_REG_BASE 0x0F00 ///< D21F2 PSF base address (SerialIo: I2C2)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_I2C1_REG_BASE 0x1000 ///< D21F1 PSF base address (SerialIo: I2C1)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_I2C0_REG_BASE 0x1100 ///< D21F0 PSF base address (SerialIo: I2C0)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_SPI_SPI_REG_BASE 0x1400 ///< D31F5 PSF base address (SPI SPI)
+#define R_PCH_H_PCR_PSF3_T0_SHDW_GBE_REG_BASE 0x1700 ///< D31F6 PSF base address (GBE)
+
+#define R_PCH_PCR_PSF3_PSF_MC_CONTROL_MCAST0_EOI 0x404C ///< Multicast Control Register // LP&H
+#define R_PCH_PCR_PSF3_PSF_MC_AGENT_MCAST0_TGT0_EOI 0x4054 ///< Destination ID // LP&H
+
+#define R_PCH_H_PCR_PSF3_PSF_PORT_CONFIG_PG1_PORT1 0x4020 ///< PSF Port Configuration Register
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h
new file mode 100644
index 0000000000..b312f7100e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h
@@ -0,0 +1,72 @@
+/** @file
+ Register definition for PSTH component
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_PSTH_H_
+#define _PCH_REGS_PSTH_H_
+
+//
+// Private chipset regsiter (Memory space) offset definition
+// The PCR register defines is used for PCR MMIO programming and PCH SBI programming as well.
+//
+
+//
+// PSTH and IO Trap PCRs (PID:PSTH)
+//
+#define R_PCH_PCR_PSTH_PSTHCTL 0x1D00 ///< PSTH control register
+#define B_PCH_PCR_PSTH_PSTHIOSFPTCGE BIT2 ///< PSTH IOSF primary trunk clock gating enable
+#define B_PCH_PCR_PSTH_PSTHIOSFSTCGE BIT1 ///< PSTH IOSF sideband trunk clock gating enable
+#define B_PCH_PCR_PSTH_PSTHDCGE BIT0 ///< PSTH dynamic clock gating enable
+#define R_PCH_PCR_PSTH_TRPST 0x1E00 ///< Trap status regsiter
+#define B_PCH_PCR_PSTH_TRPST_CTSS 0x0000000F ///< Cycle Trap SMI# Status mask
+#define R_PCH_PCR_PSTH_TRPC 0x1E10 ///< Trapped cycle
+#define B_PCH_PCR_PSTH_TRPC_RW BIT24 ///< Read/Write#: 1=Read, 0=Write
+#define B_PCH_PCR_PSTH_TRPC_AHBE 0x00000000000F0000 ///< Active high byte enables
+#define B_PCH_PCR_PSTH_TRPC_IOA 0x000000000000FFFC ///< Trap cycle I/O address
+#define R_PCH_PCR_PSTH_TRPD 0x1E18 ///< Trapped write data
+#define B_PCH_PCR_PSTH_TRPD_IOD 0x00000000FFFFFFFF ///< Trap cycle I/O data
+#define R_PCH_PCR_PSTH_TRPREG0 0x1E80 ///< IO Tarp 0 register
+#define R_PCH_PCR_PSTH_TRPREG1 0x1E88 ///< IO Tarp 1 register
+#define R_PCH_PCR_PSTH_TRPREG2 0x1E90 ///< IO Tarp 2 register
+#define R_PCH_PCR_PSTH_TRPREG3 0x1E98 ///< IO Tarp 3 register
+#define B_PCH_PCR_PSTH_TRPREG_RWM BIT17 ///< 49 - 32 for 32 bit access, Read/Write mask
+#define B_PCH_PCR_PSTH_TRPREG_RWIO BIT16 ///< 48 - 32 for 32 bit access, Read/Write#, 1=Read, 0=Write
+#define N_PCH_PCR_PSTH_TRPREG_RWIO 16 ///< 48 - 32 for 32 bit access, 16bit shift for Read/Write field
+#define N_PCH_PCR_PSTH_TRPREG_BEM (36 - 32)
+#define B_PCH_PCR_PSTH_TRPREG_BEM 0x000000F000000000 ///< Byte enable mask
+#define B_PCH_PCR_PSTH_TRPREG_BE 0x0000000F00000000 ///< Byte enable
+#define B_PCH_PCR_PSTH_TRPREG_AM 0x0000000000FC0000 ///< IO Address mask
+#define B_PCH_PCR_PSTH_TRPREG_AD 0x000000000000FFFC ///< IO Address
+#define B_PCH_PCR_PSTH_TRPREG_TSE BIT0 ///< Trap and SMI# Enable
+
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSata.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSata.h
new file mode 100644
index 0000000000..88d066ea28
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSata.h
@@ -0,0 +1,720 @@
+/** @file
+ Register names for PCH SATA controllers
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_SATA_H_
+#define _PCH_REGS_SATA_H_
+
+//
+// SATA Controller Registers (D23:F0)
+//
+#define PCI_DEVICE_NUMBER_PCH_SATA 23
+#define PCI_FUNCTION_NUMBER_PCH_SATA 0
+#define V_PCH_SATA_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+
+//
+// SKL PCH-LP SATA Device ID's
+//
+#define V_PCH_LP_SATA_DEVICE_ID_M_AHCI 0x9D03 ///< SATA Controller (AHCI) - Mobile
+#define V_PCH_LP_SATA_DEVICE_ID_M_RAID 0x9D05 ///< SATA Controller (RAID 0/1/5/10) - NOT premium - Mobile
+#define V_PCH_LP_SATA_DEVICE_ID_M_RAID_ALTDIS 0x282A ///< SATA Controller (RAID 0/1/5/10) - NOT premium - Mobile - Alternate ID
+#define V_PCH_LP_SATA_DEVICE_ID_M_RAID_PREM 0x9D07 ///< SATA Controller (RAID 0/1/5/10) - premium - Mobile
+#define V_PCH_LP_SATA_DEVICE_ID_M_RAID_RRT 0x9D0F ///< SATA Controller (RAID 1/RRT Only) - Mobile
+
+//
+// PCH-H SATA Device ID's
+//
+#define V_PCH_H_SATA_DEVICE_ID_D_RAID_ALTDIS 0x2822 ///< SATA Controller (RAID 0/1/5/10) - premium - Alternate ID
+#define V_PCH_H_SATA_DEVICE_ID_D_RAID_RSTE 0x2826 ///< SATA Controller (RAID 0/1/5/10) - RSTe of Server SKU
+
+//
+// SKL PCH-H SATA Device ID's
+//
+#define V_SKL_PCH_H_SATA_DEVICE_ID_D_AHCI 0xA102 ///< SATA Controller (AHCI)
+#define V_SKL_PCH_H_SATA_DEVICE_ID_D_AHCI_A0 0xA103 ///< SATA Controller (AHCI) - SPTH A0
+#define V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID 0xA105 ///< SATA Controller (RAID 0/1/5/10) - NOT premium
+#define V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID_PREM 0xA107 ///< SATA Controller (RAID 0/1/5/10) - premium
+#define V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID_RRT 0xA10F ///< SATA Controller (RAID 1/RRT Only)
+
+//
+// KBL PCH-H SATA Device ID's
+//
+#define V_KBL_PCH_H_SATA_DEVICE_ID_D_AHCI 0xA282 ///< SATA Controller (AHCI)
+#define V_KBL_PCH_H_SATA_DEVICE_ID_D_RAID 0xA284 ///< SATA Controller (RAID 0/1/5/10) - NOT premium
+#define V_KBL_PCH_H_SATA_DEVICE_ID_D_RAID_PREM 0xA286 ///< SATA Controller (RAID 0/1/5/10) - premium
+#define V_KBL_PCH_H_SATA_DEVICE_ID_D_OPTANE 0xA28E ///< SATA Controller (RAID 1/RRT Only)
+
+
+//
+// SATA Controller common Registers
+//
+#define V_PCH_SATA_SUB_CLASS_CODE_AHCI 0x06
+#define V_PCH_SATA_SUB_CLASS_CODE_RAID 0x04
+#define R_PCH_SATA_AHCI_BAR 0x24
+#define B_PCH_SATA_AHCI_BAR_BA 0xFFFFF800
+#define V_PCH_SATA_AHCI_BAR_LENGTH 0x800
+#define N_PCH_SATA_AHCI_BAR_ALIGNMENT 11
+#define V_PCH_SATA_AHCI_BAR_LENGTH_512K 0x80000
+#define N_PCH_SATA_AHCI_BAR_ALIGNMENT_512K 19
+#define B_PCH_SATA_AHCI_BAR_PF BIT3
+#define B_PCH_SATA_AHCI_BAR_TP (BIT2 | BIT1)
+#define B_PCH_SATA_AHCI_BAR_RTE BIT0
+#define R_PCH_SATA_PID 0x70
+#define B_PCH_SATA_PID_NEXT 0xFF00
+#define V_PCH_SATA_PID_NEXT_0 0xB000
+#define V_PCH_SATA_PID_NEXT_1 0xA800
+#define B_PCH_SATA_PID_CID 0x00FF
+#define R_PCH_SATA_PC 0x72
+#define S_PCH_SATA_PC 2
+#define B_PCH_SATA_PC_PME (BIT15 | BIT14 | BIT13 | BIT12 | BIT11)
+#define V_PCH_SATA_PC_PME_0 0x0000
+#define V_PCH_SATA_PC_PME_1 0x4000
+#define B_PCH_SATA_PC_D2_SUP BIT10
+#define B_PCH_SATA_PC_D1_SUP BIT9
+#define B_PCH_SATA_PC_AUX_CUR (BIT8 | BIT7 | BIT6)
+#define B_PCH_SATA_PC_DSI BIT5
+#define B_PCH_SATA_PC_PME_CLK BIT3
+#define B_PCH_SATA_PC_VER (BIT2 | BIT1 | BIT0)
+#define R_PCH_SATA_PMCS 0x74
+#define B_PCH_SATA_PMCS_PMES BIT15
+#define B_PCH_SATA_PMCS_PMEE BIT8
+#define B_PCH_SATA_PMCS_NSFRST BIT3
+#define V_PCH_SATA_PMCS_NSFRST_1 0x01
+#define V_PCH_SATA_PMCS_NSFRST_0 0x00
+#define B_PCH_SATA_PMCS_PS (BIT1 | BIT0)
+#define V_PCH_SATA_PMCS_PS_3 0x03
+#define V_PCH_SATA_PMCS_PS_0 0x00
+#define R_PCH_SATA_MID 0x80
+#define B_PCH_SATA_MID_NEXT 0xFF00
+#define B_PCH_SATA_MID_CID 0x00FF
+#define R_PCH_SATA_MC 0x82
+#define B_PCH_SATA_MC_C64 BIT7
+#define B_PCH_SATA_MC_MME (BIT6 | BIT5 | BIT4)
+#define V_PCH_SATA_MC_MME_4 0x04
+#define V_PCH_SATA_MC_MME_2 0x02
+#define V_PCH_SATA_MC_MME_1 0x01
+#define V_PCH_SATA_MC_MME_0 0x00
+#define B_PCH_SATA_MC_MMC (BIT3 | BIT2 | BIT1)
+#define V_PCH_SATA_MC_MMC_4 0x04
+#define V_PCH_SATA_MC_MMC_0 0x00
+#define B_PCH_SATA_MC_MSIE BIT0
+#define V_PCH_SATA_MC_MSIE_1 0x01
+#define V_PCH_SATA_MC_MSIE_0 0x00
+#define R_PCH_SATA_MA 0x84
+#define B_PCH_SATA_MA 0xFFFFFFFC
+#define R_PCH_SATA_MD 0x88
+#define B_PCH_SATA_MD_MSIMD 0xFFFF
+
+//
+// Sata Register for PCH-LP
+//
+#define R_PCH_LP_SATA_MAP 0x90
+#define B_PCH_LP_SATA_MAP_SPD (BIT10 | BIT9 | BIT8)
+#define N_PCH_LP_SATA_MAP_SPD 8
+#define B_PCH_LP_SATA_MAP_SPD2 BIT10
+#define B_PCH_LP_SATA_MAP_SPD1 BIT9
+#define B_PCH_LP_SATA_MAP_SPD0 BIT8
+#define B_PCH_LP_SATA_MAP_SMS_MASK BIT6
+#define N_PCH_LP_SATA_MAP_SMS_MASK 6
+#define V_PCH_LP_SATA_MAP_SMS_AHCI 0x0
+#define V_PCH_LP_SATA_MAP_SMS_RAID 0x1
+#define R_PCH_LP_SATA_PCS 0x92
+#define B_PCH_LP_SATA_PCS_OOB_RETRY BIT15
+#define B_PCH_LP_SATA_PCS_P2P BIT10
+#define B_PCH_LP_SATA_PCS_P1P BIT9
+#define B_PCH_LP_SATA_PCS_P0P BIT8
+#define B_PCH_LP_SATA_PCS_PXE_MASK (BIT2 | BIT1 | BIT0)
+#define B_PCH_LP_SATA_PCS_P2E BIT2
+#define B_PCH_LP_SATA_PCS_P1E BIT1
+#define B_PCH_LP_SATA_PCS_P0E BIT0
+#define R_PCH_LP_SATA_SCLKGC 0x94
+#define B_PCH_LP_SATA_SCLKGC_PCD (BIT26 | BIT25 | BIT24)
+#define B_PCH_LP_SATA_SCLKGC_PORT2_PCD BIT26
+#define B_PCH_LP_SATA_SCLKGC_PORT1_PCD BIT25
+#define B_PCH_LP_SATA_SCLKGC_PORT0_PCD BIT24
+#define R_PCH_LP_SATA_98 0x98
+
+//
+// Sata Register for PCH-H
+//
+#define R_PCH_H_SATA_MAP 0x90
+#define B_PCH_H_SATA_MAP_SPD 0xFF0000
+#define N_PCH_H_SATA_MAP_SPD 16
+#define B_PCH_H_SATA_MAP_SPD7 BIT23
+#define B_PCH_H_SATA_MAP_SPD6 BIT22
+#define B_PCH_H_SATA_MAP_SPD5 BIT21
+#define B_PCH_H_SATA_MAP_SPD4 BIT20
+#define B_PCH_H_SATA_MAP_SPD3 BIT19
+#define B_PCH_H_SATA_MAP_SPD2 BIT18
+#define B_PCH_H_SATA_MAP_SPD1 BIT17
+#define B_PCH_H_SATA_MAP_SPD0 BIT16
+#define B_PCH_H_SATA_MAP_PCD 0xFF
+#define B_PCH_H_SATA_MAP_PORT7_PCD BIT7
+#define B_PCH_H_SATA_MAP_PORT6_PCD BIT6
+#define B_PCH_H_SATA_MAP_PORT5_PCD BIT5
+#define B_PCH_H_SATA_MAP_PORT4_PCD BIT4
+#define B_PCH_H_SATA_MAP_PORT3_PCD BIT3
+#define B_PCH_H_SATA_MAP_PORT2_PCD BIT2
+#define B_PCH_H_SATA_MAP_PORT1_PCD BIT1
+#define B_PCH_H_SATA_MAP_PORT0_PCD BIT0
+#define R_PCH_H_SATA_PCS 0x94
+#define B_PCH_H_SATA_PCS_P7P BIT23
+#define B_PCH_H_SATA_PCS_P6P BIT22
+#define B_PCH_H_SATA_PCS_P5P BIT21
+#define B_PCH_H_SATA_PCS_P4P BIT20
+#define B_PCH_H_SATA_PCS_P3P BIT19
+#define B_PCH_H_SATA_PCS_P2P BIT18
+#define B_PCH_H_SATA_PCS_P1P BIT17
+#define B_PCH_H_SATA_PCS_P0P BIT16
+#define B_PCH_H_SATA_PCS_PXE_MASK 0xFF
+#define B_PCH_H_SATA_PCS_P7E BIT7
+#define B_PCH_H_SATA_PCS_P6E BIT6
+#define B_PCH_H_SATA_PCS_P5E BIT5
+#define B_PCH_H_SATA_PCS_P4E BIT4
+#define B_PCH_H_SATA_PCS_P3E BIT3
+#define B_PCH_H_SATA_PCS_P2E BIT2
+#define B_PCH_H_SATA_PCS_P1E BIT1
+#define B_PCH_H_SATA_PCS_P0E BIT0
+
+#define R_PCH_SATA_SATAGC 0x9C
+#define B_PCH_H_SATA_SATAGC_SMS_MASK BIT16
+#define N_PCH_H_SATA_SATAGC_SMS_MASK 16
+#define V_PCH_H_SATA_SATAGC_SMS_AHCI 0x0
+#define V_PCH_H_SATA_SATAGC_SMS_RAID 0x1
+#define B_PCH_SATA_SATAGC_AIE BIT7
+#define B_PCH_SATA_SATAGC_AIES BIT6
+#define B_PCH_SATA_SATAGC_MSS (BIT4 | BIT3)
+#define V_PCH_SATA_SATAGC_MSS_8K 0x2
+#define N_PCH_SATA_SATAGC_MSS 3
+#define B_PCH_SATA_SATAGC_ASSEL (BIT2 | BIT1 | BIT0)
+
+#define V_PCH_SATA_SATAGC_ASSEL_2K 0x0
+#define V_PCH_SATA_SATAGC_ASSEL_16K 0x1
+#define V_PCH_SATA_SATAGC_ASSEL_32K 0x2
+#define V_PCH_SATA_SATAGC_ASSEL_64K 0x3
+#define V_PCH_SATA_SATAGC_ASSEL_128K 0x4
+#define V_PCH_SATA_SATAGC_ASSEL_256K 0x5
+#define V_PCH_SATA_SATAGC_ASSEL_512K 0x6
+
+#define R_PCH_SATA_SIRI 0xA0
+#define R_PCH_SATA_STRD 0xA4
+#define R_PCH_SATA_SIR_0C 0x0C
+#define R_PCH_SATA_SIR_50 0x50
+#define R_PCH_SATA_SIR_54 0x54
+#define R_PCH_SATA_SIR_58 0x58
+#define R_PCH_SATA_SIR_5C 0x5C
+#define R_PCH_SATA_SIR_60 0x60
+#define R_PCH_SATA_SIR_64 0x64
+#define R_PCH_SATA_SIR_68 0x68
+#define R_PCH_SATA_SIR_6C 0x6C
+#define R_PCH_SATA_SIR_70 0x70
+#define R_PCH_SATA_SIR_80 0x80
+#define R_PCH_SATA_SIR_84 0x84
+#define R_PCH_SATA_SIR_8C 0x8C
+#define R_PCH_SATA_SIR_90 0x90
+#define R_PCH_SATA_SIR_98 0x98
+#define R_PCH_SATA_SIR_9C 0x9C
+#define R_PCH_SATA_SIR_A0 0xA0
+#define R_PCH_SATA_SIR_A4 0xA4
+#define R_PCH_SATA_SIR_A8 0xA8
+#define R_PCH_SATA_SIR_C8 0xC8
+#define R_PCH_SATA_SIR_CC 0xCC
+#define R_PCH_SATA_SIR_D0 0xD0
+#define R_PCH_SATA_SIR_D4 0xD4
+#define B_PCH_SATA_STRD_DTA 0xFFFFFFFF
+#define R_PCH_SATA_CR0 0xA8
+#define B_PCH_SATA_CR0_MAJREV 0x00F00000
+#define B_PCH_SATA_CR0_MINREV 0x000F0000
+#define B_PCH_SATA_CR0_NEXT 0x0000FF00
+#define B_PCH_SATA_CR0_CAP 0x000000FF
+#define R_PCH_SATA_CR1 0xAC
+#define B_PCH_SATA_CR1_BAROFST 0xFFF0
+#define B_PCH_SATA_CR1_BARLOC 0x000F
+#define R_PCH_SATA_FLR_CID 0xB0
+#define B_PCH_SATA_FLR_CID_NEXT 0xFF00
+#define B_PCH_SATA_FLR_CID 0x00FF
+#define V_PCH_SATA_FLR_CID_1 0x0009
+#define V_PCH_SATA_FLR_CID_0 0x0013
+#define R_PCH_SATA_FLR_CLV 0xB2
+#define B_PCH_SATA_FLR_CLV_FLRC_FLRCSSEL_0 BIT9
+#define B_PCH_SATA_FLR_CLV_TXPC_FLRCSSEL_0 BIT8
+#define B_PCH_SATA_FLR_CLV_VSCID_FLRCSSEL_0 0x00FF
+#define B_PCH_SATA_FLR_CLV_VSCID_FLRCSSEL_1 0x00FF
+#define V_PCH_SATA_FLR_CLV_VSCID_FLRCSSEL 0x0006
+#define R_PCH_SATA_FLRC 0xB4
+#define B_PCH_SATA_FLRC_TXP BIT8
+#define B_PCH_SATA_FLRC_INITFLR BIT0
+#define R_PCH_SATA_SP 0xC0
+#define B_PCH_SATA_SP 0xFFFFFFFF
+#define R_PCH_SATA_MXID 0xD0
+#define N_PCH_SATA_MXID_NEXT 8
+
+#define R_PCH_SATA_BFCS 0xE0
+#define B_PCH_SATA_BFCS_P7BFI BIT17
+#define B_PCH_SATA_BFCS_P6BFI BIT16
+#define B_PCH_SATA_BFCS_P5BFI BIT15
+#define B_PCH_SATA_BFCS_P4BFI BIT14
+#define B_PCH_SATA_BFCS_P3BFI BIT13
+#define B_PCH_SATA_BFCS_P2BFI BIT12
+#define B_PCH_SATA_BFCS_P2BFS BIT11
+#define B_PCH_SATA_BFCS_P2BFF BIT10
+#define B_PCH_SATA_BFCS_P1BFI BIT9
+#define B_PCH_SATA_BFCS_P0BFI BIT8
+#define B_PCH_SATA_BFCS_BIST_FIS_T BIT7
+#define B_PCH_SATA_BFCS_BIST_FIS_A BIT6
+#define B_PCH_SATA_BFCS_BIST_FIS_S BIT5
+#define B_PCH_SATA_BFCS_BIST_FIS_L BIT4
+#define B_PCH_SATA_BFCS_BIST_FIS_F BIT3
+#define B_PCH_SATA_BFCS_BIST_FIS_P BIT2
+#define R_PCH_SATA_BFTD1 0xE4
+#define B_PCH_SATA_BFTD1 0xFFFFFFFF
+#define R_PCH_SATA_BFTD2 0xE8
+#define B_PCH_SATA_BFTD2 0xFFFFFFFF
+
+#define R_PCH_SATA_VS_CAP 0xA4
+#define B_PCH_SATA_VS_CAP_NRMBE BIT0 ///< NVM Remap Memory BAR Enable
+#define B_PCH_SATA_VS_CAP_MSL 0x1FFE ///< Memory Space Limit
+#define N_PCH_SATA_VS_CAP_MSL 1
+#define V_PCH_SATA_VS_CAP_MSL 0x1EF ///< Memory Space Limit Field Value
+#define B_PCH_SATA_VS_CAP_NRMO 0xFFF0000 ///< NVM Remapped Memory Offset
+#define N_PCH_SATA_VS_CAP_NRMO 16
+#define V_PCH_SATA_VS_CAP_NRMO 0x10 ///< NVM Remapped Memory Offset Field Value
+
+//
+// RST PCIe Storage Remapping Registers
+//
+#define R_PCH_RST_PCIE_STORAGE_RCR 0x800 ///< Remap Capability Register
+#define B_PCH_RST_PCIE_STORAGE_RCR_NRS (BIT2|BIT1|BIT0) ///< Number of Remapping Supported
+#define B_PCH_RST_PCIE_STORAGE_RCR_NRS_CR1 BIT0 ///< Number of Remapping Supported (RST PCIe Storage Cycle Router #1)
+#define R_PCH_RST_PCIE_STORAGE_SPR 0x80C ///< Scratch Pad Register
+#define R_PCH_RST_PCIE_STORAGE_CR1_DCC 0x880 ///< CR#1 Device Class Code
+#define N_PCH_RST_PCIE_STORAGE_CR1_DCC_SCC 8
+#define N_PCH_RST_PCIE_STORAGE_CR1_DCC_BCC 16
+#define B_PCH_RST_PCIE_STORAGE_CR1_DCC_DT BIT31 ///< Device Type
+#define V_PCH_RST_PCIE_STORAGE_REMAP_CONFIG_CR 0x80 ///< Remapped Configuration for RST PCIe Storage Cycle Router #n
+#define V_PCH_RST_PCIE_STORAGE_REMAP_RP_OFFSET 0x100 ///< Remapped Root Port Offset Value
+#define R_PCH_RST_PCIE_STORAGE_CCFG 0x1D0 ///< Port Configuration Register
+
+//
+// AHCI BAR Area related Registers
+//
+#define R_PCH_SATA_AHCI_CAP 0x0
+#define B_PCH_SATA_AHCI_CAP_S64A BIT31
+#define B_PCH_SATA_AHCI_CAP_SCQA BIT30
+#define B_PCH_SATA_AHCI_CAP_SSNTF BIT29
+#define B_PCH_SATA_AHCI_CAP_SIS BIT28 ///< Supports Interlock Switch
+#define B_PCH_SATA_AHCI_CAP_SSS BIT27 ///< Supports Stagger Spin-up
+#define B_PCH_SATA_AHCI_CAP_SALP BIT26
+#define B_PCH_SATA_AHCI_CAP_SAL BIT25
+#define B_PCH_SATA_AHCI_CAP_SCLO BIT24 ///< Supports Command List Override
+#define B_PCH_SATA_AHCI_CAP_ISS_MASK (BIT23 | BIT22 | BIT21 | BIT20)
+#define N_PCH_SATA_AHCI_CAP_ISS 20 ///< Interface Speed Support
+#define V_PCH_SATA_AHCI_CAP_ISS_1_5_G 0x01
+#define V_PCH_SATA_AHCI_CAP_ISS_3_0_G 0x02
+#define V_PCH_SATA_AHCI_CAP_ISS_6_0_G 0x03
+#define B_PCH_SATA_AHCI_CAP_SNZO BIT19
+#define B_PCH_SATA_AHCI_CAP_SAM BIT18
+#define B_PCH_SATA_AHCI_CAP_PMS BIT17 ///< Supports Port Multiplier
+#define B_PCH_SATA_AHCI_CAP_PMD BIT15 ///< PIO Multiple DRQ Block
+#define B_PCH_SATA_AHCI_CAP_SSC BIT14
+#define B_PCH_SATA_AHCI_CAP_PSC BIT13
+#define B_PCH_SATA_AHCI_CAP_NCS 0x1F00
+#define B_PCH_SATA_AHCI_CAP_CCCS BIT7
+#define B_PCH_SATA_AHCI_CAP_EMS BIT6
+#define B_PCH_SATA_AHCI_CAP_SXS BIT5 ///< External SATA is supported
+#define B_PCH_SATA_AHCI_CAP_NPS 0x001F
+
+#define R_PCH_SATA_AHCI_GHC 0x04
+#define B_PCH_SATA_AHCI_GHC_AE BIT31
+#define B_PCH_SATA_AHCI_GHC_MRSM BIT2
+#define B_PCH_SATA_AHCI_GHC_IE BIT1
+#define B_PCH_SATA_AHCI_GHC_HR BIT0
+
+#define R_PCH_SATA_AHCI_IS 0x08
+#define B_PCH_SATA_AHCI_IS_PORT7 BIT7
+#define B_PCH_SATA_AHCI_IS_PORT6 BIT6
+#define B_PCH_SATA_AHCI_IS_PORT5 BIT5
+#define B_PCH_SATA_AHCI_IS_PORT4 BIT4
+#define B_PCH_SATA_AHCI_IS_PORT3 BIT3
+#define B_PCH_SATA_AHCI_IS_PORT2 BIT2
+#define B_PCH_SATA_AHCI_IS_PORT1 BIT1
+#define B_PCH_SATA_AHCI_IS_PORT0 BIT0
+#define R_PCH_SATA_AHCI_PI 0x0C
+#define B_PCH_H_SATA_PORT_MASK 0xFF
+#define B_PCH_LP_SATA_PORT_MASK 0x03
+#define B_PCH_SATA_PORT7_IMPLEMENTED BIT7
+#define B_PCH_SATA_PORT6_IMPLEMENTED BIT6
+#define B_PCH_SATA_PORT5_IMPLEMENTED BIT5
+#define B_PCH_SATA_PORT4_IMPLEMENTED BIT4
+#define B_PCH_SATA_PORT3_IMPLEMENTED BIT3
+#define B_PCH_SATA_PORT2_IMPLEMENTED BIT2
+#define B_PCH_SATA_PORT1_IMPLEMENTED BIT1
+#define B_PCH_SATA_PORT0_IMPLEMENTED BIT0
+#define R_PCH_SATA_AHCI_VS 0x10
+#define B_PCH_SATA_AHCI_VS_MJR 0xFFFF0000
+#define B_PCH_SATA_AHCI_VS_MNR 0x0000FFFF
+#define R_PCH_SATA_AHCI_EM_LOC 0x1C
+#define B_PCH_SATA_AHCI_EM_LOC_OFST 0xFFFF0000
+#define B_PCH_SATA_AHCI_EM_LOC_SZ 0x0000FFFF
+#define R_PCH_SATA_AHCI_EM_CTRL 0x20
+#define B_PCH_SATA_AHCI_EM_CTRL_ATTR_ALHD BIT26
+#define B_PCH_SATA_AHCI_EM_CTRL_ATTR_XMT BIT25
+#define B_PCH_SATA_AHCI_EM_CTRL_ATTR_SMB BIT24
+#define B_PCH_SATA_AHCI_EM_CTRL_SUPP_SGPIO BIT19
+#define B_PCH_SATA_AHCI_EM_CTRL_SUPP_SES2 BIT18
+#define B_PCH_SATA_AHCI_EM_CTRL_SUPP_SAFTE BIT17
+#define B_PCH_SATA_AHCI_EM_CTRL_SUPP_LED BIT16
+#define B_PCH_SATA_AHCI_EM_CTRL_RST BIT9
+#define B_PCH_SATA_AHCI_EM_CTRL_CTL_TM BIT8
+#define B_PCH_SATA_AHCI_EM_CTRL_STS_MR BIT0
+#define R_PCH_SATA_AHCI_CAP2 0x24
+#define B_PCH_SATA_AHCI_CAP2_DESO BIT5
+#define B_PCH_SATA_AHCI_CAP2_SADM BIT4
+#define B_PCH_SATA_AHCI_CAP2_SDS BIT3
+#define B_PCH_SATA_AHCI_CAP2_APST BIT2 ///< Automatic Partial to Slumber Transitions
+#define R_PCH_SATA_AHCI_VSP 0xA0
+#define B_PCH_SATA_AHCI_VSP_SLPD BIT0
+#define R_PCH_SATA_AHCI_RSTF 0xC8 ///< RST Feature Capabilities
+#define B_PCH_SATA_AHCI_RSTF_OMA BIT13
+#define B_PCH_SATA_AHCI_RSTF_LEGACY BIT12
+#define B_PCH_SATA_AHCI_RSTF_OUD (BIT11 | BIT10)
+#define N_PCH_SATA_AHCI_RSTF_OUD 10
+#define B_PCH_SATA_AHCI_RSTF_SEREQ BIT9
+#define B_PCH_SATA_AHCI_RSTF_IROES BIT8
+#define B_PCH_SATA_AHCI_RSTF_LEDL BIT7
+#define B_PCH_SATA_AHCI_RSTF_HDDLK BIT6
+#define B_PCH_SATA_AHCI_RSTF_IRSTOROM BIT5
+#define B_PCH_SATA_AHCI_RSTF_RSTE BIT4
+#define B_PCH_SATA_AHCI_RSTF_R5E BIT3
+#define B_PCH_SATA_AHCI_RSTF_R10E BIT2
+#define B_PCH_SATA_AHCI_RSTF_R1E BIT1
+#define B_PCH_SATA_AHCI_RSTF_R0E BIT0
+#define B_PCH_SATA_AHCI_RSTF_LOWBYTES 0x1FF
+#define R_PCH_SATA_AHCI_P0CLB 0x100
+#define R_PCH_SATA_AHCI_P1CLB 0x180
+#define R_PCH_SATA_AHCI_P2CLB 0x200
+#define R_PCH_SATA_AHCI_P3CLB 0x280
+#define R_PCH_SATA_AHCI_P4CLB 0x300
+#define R_PCH_SATA_AHCI_P5CLB 0x380
+#define R_PCH_SATA_AHCI_P6CLB 0x400
+#define R_PCH_SATA_AHCI_P7CLB 0x480
+#define B_PCH_SATA_AHCI_PXCLB 0xFFFFFC00
+#define R_PCH_SATA_AHCI_P0CLBU 0x104
+#define R_PCH_SATA_AHCI_P1CLBU 0x184
+#define R_PCH_SATA_AHCI_P2CLBU 0x204
+#define R_PCH_SATA_AHCI_P3CLBU 0x284
+#define R_PCH_SATA_AHCI_P4CLBU 0x304
+#define R_PCH_SATA_AHCI_P5CLBU 0x384
+#define R_PCH_SATA_AHCI_P6CLBU 0x404
+#define R_PCH_SATA_AHCI_P7CLBU 0x484
+#define B_PCH_SATA_AHCI_PXCLBU 0xFFFFFFFF
+#define R_PCH_SATA_AHCI_P0FB 0x108
+#define R_PCH_SATA_AHCI_P1FB 0x188
+#define R_PCH_SATA_AHCI_P2FB 0x208
+#define R_PCH_SATA_AHCI_P3FB 0x288
+#define R_PCH_SATA_AHCI_P4FB 0x308
+#define R_PCH_SATA_AHCI_P5FB 0x388
+#define R_PCH_SATA_AHCI_P6FB 0x408
+#define R_PCH_SATA_AHCI_P7FB 0x488
+#define B_PCH_SATA_AHCI_PXFB 0xFFFFFF00
+#define R_PCH_SATA_AHCI_P0FBU 0x10C
+#define R_PCH_SATA_AHCI_P1FBU 0x18C
+#define R_PCH_SATA_AHCI_P2FBU 0x20C
+#define R_PCH_SATA_AHCI_P3FBU 0x28C
+#define R_PCH_SATA_AHCI_P4FBU 0x30C
+#define R_PCH_SATA_AHCI_P5FBU 0x38C
+#define R_PCH_SATA_AHCI_P6FBU 0x40C
+#define R_PCH_SATA_AHCI_P7FBU 0x48C
+#define B_PCH_SATA_AHCI_PXFBU 0xFFFFFFFF
+#define R_PCH_SATA_AHCI_P0IS 0x110
+#define R_PCH_SATA_AHCI_P1IS 0x190
+#define R_PCH_SATA_AHCI_P2IS 0x210
+#define R_PCH_SATA_AHCI_P3IS 0x290
+#define R_PCH_SATA_AHCI_P4IS 0x310
+#define R_PCH_SATA_AHCI_P5IS 0x390
+#define R_PCH_SATA_AHCI_P6IS 0x410
+#define R_PCH_SATA_AHCI_P7IS 0x490
+#define B_PCH_SATA_AHCI_PXIS_CPDS BIT31
+#define B_PCH_SATA_AHCI_PXIS_TFES BIT30
+#define B_PCH_SATA_AHCI_PXIS_HBFS BIT29
+#define B_PCH_SATA_AHCI_PXIS_HBDS BIT28
+#define B_PCH_SATA_AHCI_PXIS_IFS BIT27
+#define B_PCH_SATA_AHCI_PXIS_INFS BIT26
+#define B_PCH_SATA_AHCI_PXIS_OFS BIT24
+#define B_PCH_SATA_AHCI_PXIS_IPMS BIT23
+#define B_PCH_SATA_AHCI_PXIS_PRCS BIT22
+#define B_PCH_SATA_AHCI_PXIS_DIS BIT7
+#define B_PCH_SATA_AHCI_PXIS_PCS BIT6
+#define B_PCH_SATA_AHCI_PXIS_DPS BIT5
+#define B_PCH_SATA_AHCI_PXIS_UFS BIT4
+#define B_PCH_SATA_AHCI_PXIS_SDBS BIT3
+#define B_PCH_SATA_AHCI_PXIS_DSS BIT2
+#define B_PCH_SATA_AHCI_PXIS_PSS BIT1
+#define B_PCH_SATA_AHCI_PXIS_DHRS BIT0
+#define R_PCH_SATA_AHCI_P0IE 0x114
+#define R_PCH_SATA_AHCI_P1IE 0x194
+#define R_PCH_SATA_AHCI_P2IE 0x214
+#define R_PCH_SATA_AHCI_P3IE 0x294
+#define R_PCH_SATA_AHCI_P4IE 0x314
+#define R_PCH_SATA_AHCI_P5IE 0x394
+#define R_PCH_SATA_AHCI_P6IE 0x414
+#define R_PCH_SATA_AHCI_P7IE 0x494
+#define B_PCH_SATA_AHCI_PXIE_CPDE BIT31
+#define B_PCH_SATA_AHCI_PXIE_TFEE BIT30
+#define B_PCH_SATA_AHCI_PXIE_HBFE BIT29
+#define B_PCH_SATA_AHCI_PXIE_HBDE BIT28
+#define B_PCH_SATA_AHCI_PXIE_IFE BIT27
+#define B_PCH_SATA_AHCI_PXIE_INFE BIT26
+#define B_PCH_SATA_AHCI_PXIE_OFE BIT24
+#define B_PCH_SATA_AHCI_PXIE_IPME BIT23
+#define B_PCH_SATA_AHCI_PXIE_PRCE BIT22
+#define B_PCH_SATA_AHCI_PXIE_DIE BIT7
+#define B_PCH_SATA_AHCI_PXIE_PCE BIT6
+#define B_PCH_SATA_AHCI_PXIE_DPE BIT5
+#define B_PCH_SATA_AHCI_PXIE_UFIE BIT4
+#define B_PCH_SATA_AHCI_PXIE_SDBE BIT3
+#define B_PCH_SATA_AHCI_PXIE_DSE BIT2
+#define B_PCH_SATA_AHCI_PXIE_PSE BIT1
+#define B_PCH_SATA_AHCI_PXIE_DHRE BIT0
+#define R_PCH_SATA_AHCI_P0CMD 0x118
+#define R_PCH_SATA_AHCI_P1CMD 0x198
+#define R_PCH_SATA_AHCI_P2CMD 0x218
+#define R_PCH_SATA_AHCI_P3CMD 0x298
+#define R_PCH_SATA_AHCI_P4CMD 0x318
+#define R_PCH_SATA_AHCI_P5CMD 0x398
+#define R_PCH_SATA_AHCI_P6CMD 0x418
+#define R_PCH_SATA_AHCI_P7CMD 0x498
+#define B_PCH_SATA_AHCI_PxCMD_ICC (BIT31 | BIT30 | BIT29 | BIT28)
+#define B_PCH_SATA_AHCI_PxCMD_MASK (BIT27 | BIT26 | BIT22 | BIT21 | BIT19 | BIT18)
+#define B_PCH_SATA_AHCI_PxCMD_ASP BIT27
+#define B_PCH_SATA_AHCI_PxCMD_ALPE BIT26
+#define B_PCH_SATA_AHCI_PxCMD_DLAE BIT25
+#define B_PCH_SATA_AHCI_PxCMD_ATAPI BIT24
+#define B_PCH_SATA_AHCI_PxCMD_APSTE BIT23
+#define B_PCH_SATA_AHCI_PxCMD_SUD BIT1
+#define R_PCH_SATA_AHCI_P0DEVSLP 0x144
+#define R_PCH_SATA_AHCI_P1DEVSLP 0x1C4
+#define R_PCH_SATA_AHCI_P2DEVSLP 0x244
+#define R_PCH_SATA_AHCI_P3DEVSLP 0x2C4
+#define R_PCH_SATA_AHCI_P4DEVSLP 0x344
+#define R_PCH_SATA_AHCI_P5DEVSLP 0x3C4
+#define R_PCH_SATA_AHCI_P6DEVSLP 0x444
+#define R_PCH_SATA_AHCI_P7DEVSLP 0x4C4
+#define B_PCH_SATA_AHCI_PxDEVSLP_DSP BIT1
+#define B_PCH_SATA_AHCI_PxDEVSLP_ADSE BIT0
+#define B_PCH_SATA_AHCI_PxDEVSLP_DITO_MASK 0x01FF8000
+#define V_PCH_SATA_AHCI_PxDEVSLP_DITO_625 0x01388000
+#define B_PCH_SATA_AHCI_PxDEVSLP_DM_MASK 0x1E000000
+#define V_PCH_SATA_AHCI_PxDEVSLP_DM_16 0x1E000000
+#define B_PCH_SATA_AHCI_PxCMD_ESP BIT21 ///< Used with an external SATA device
+#define B_PCH_SATA_AHCI_PxCMD_MPSP BIT19 ///< Mechanical Switch Attached to Port
+#define B_PCH_SATA_AHCI_PxCMD_HPCP BIT18 ///< Hotplug capable
+#define B_PCH_SATA_AHCI_PxCMD_CR BIT15
+#define B_PCH_SATA_AHCI_PxCMD_FR BIT14
+#define B_PCH_SATA_AHCI_PxCMD_ISS BIT13
+#define B_PCH_SATA_AHCI_PxCMD_CCS 0x00001F00
+#define B_PCH_SATA_AHCI_PxCMD_FRE BIT4
+#define B_PCH_SATA_AHCI_PxCMD_CLO BIT3
+#define B_PCH_SATA_AHCI_PxCMD_POD BIT2
+#define B_PCH_SATA_AHCI_PxCMD_SUD BIT1
+#define B_PCH_SATA_AHCI_PxCMD_ST BIT0
+#define R_PCH_SATA_AHCI_P0TFD 0x120
+#define R_PCH_SATA_AHCI_P1TFD 0x1A0
+#define R_PCH_SATA_AHCI_P2TFD 0x220
+#define R_PCH_SATA_AHCI_P3TFD 0x2A0
+#define R_PCH_SATA_AHCI_P4TFD 0x320
+#define R_PCH_SATA_AHCI_P5TFD 0x3A0
+#define R_PCH_SATA_AHCI_P6TFD 0x420
+#define B_PCH_SATA_AHCI_PXTFD_ERR 0x0000FF00
+#define B_PCH_SATA_AHCI_PXTFD_STS 0x000000FF
+#define R_PCH_SATA_AHCI_P0SIG 0x124
+#define R_PCH_SATA_AHCI_P1SIG 0x1A4
+#define R_PCH_SATA_AHCI_P2SIG 0x224
+#define R_PCH_SATA_AHCI_P3SIG 0x2A4
+#define R_PCH_SATA_AHCI_P4SIG 0x324
+#define R_PCH_SATA_AHCI_P5SIG 0x3A4
+#define R_PCH_SATA_AHCI_P6SIG 0x424
+#define B_PCH_SATA_AHCI_PXSIG_LBA_HR 0xFF000000
+#define B_PCH_SATA_AHCI_PXSIG_LBA_MR 0x00FF0000
+#define B_PCH_SATA_AHCI_PXSIG_LBA_LR 0x0000FF00
+#define B_PCH_SATA_AHCI_PXSIG_SCR 0x000000FF
+#define R_PCH_SATA_AHCI_P0SSTS 0x128
+#define R_PCH_SATA_AHCI_P1SSTS 0x1A8
+#define R_PCH_SATA_AHCI_P2SSTS 0x228
+#define R_PCH_SATA_AHCI_P3SSTS 0x2A8
+#define R_PCH_SATA_AHCI_P4SSTS 0x328
+#define R_PCH_SATA_AHCI_P5SSTS 0x3A8
+#define R_PCH_SATA_AHCI_P6SSTS 0x428
+#define B_PCH_SATA_AHCI_PXSSTS_IPM_0 0x00000000
+#define B_PCH_SATA_AHCI_PXSSTS_IPM_1 0x00000100
+#define B_PCH_SATA_AHCI_PXSSTS_IPM_2 0x00000200
+#define B_PCH_SATA_AHCI_PXSSTS_IPM_6 0x00000600
+#define B_PCH_SATA_AHCI_PXSSTS_SPD_0 0x00000000
+#define B_PCH_SATA_AHCI_PXSSTS_SPD_1 0x00000010
+#define B_PCH_SATA_AHCI_PXSSTS_SPD_2 0x00000020
+#define B_PCH_SATA_AHCI_PXSSTS_SPD_3 0x00000030
+#define B_PCH_SATA_AHCI_PXSSTS_DET_0 0x00000000
+#define B_PCH_SATA_AHCI_PXSSTS_DET_1 0x00000001
+#define B_PCH_SATA_AHCI_PXSSTS_DET_3 0x00000003
+#define B_PCH_SATA_AHCI_PXSSTS_DET_4 0x00000004
+#define R_PCH_SATA_AHCI_P0SCTL 0x12C
+#define R_PCH_SATA_AHCI_P1SCTL 0x1AC
+#define R_PCH_SATA_AHCI_P2SCTL 0x22C
+#define R_PCH_SATA_AHCI_P3SCTL 0x2AC
+#define R_PCH_SATA_AHCI_P4SCTL 0x32C
+#define R_PCH_SATA_AHCI_P5SCTL 0x3AC
+#define R_PCH_SATA_AHCI_P6SCTL 0x42C
+#define B_PCH_SATA_AHCI_PXSCTL_IPM 0x00000F00
+#define V_PCH_SATA_AHCI_PXSCTL_IPM_0 0x00000000
+#define V_PCH_SATA_AHCI_PXSCTL_IPM_1 0x00000100
+#define V_PCH_SATA_AHCI_PXSCTL_IPM_2 0x00000200
+#define V_PCH_SATA_AHCI_PXSCTL_IPM_3 0x00000300
+#define B_PCH_SATA_AHCI_PXSCTL_SPD 0x000000F0
+#define V_PCH_SATA_AHCI_PXSCTL_SPD_0 0x00000000
+#define V_PCH_SATA_AHCI_PXSCTL_SPD_1 0x00000010
+#define V_PCH_SATA_AHCI_PXSCTL_SPD_2 0x00000020
+#define V_PCH_SATA_AHCI_PXSCTL_SPD_3 0x00000030
+#define B_PCH_SATA_AHCI_PXSCTL_DET 0x0000000F
+#define V_PCH_SATA_AHCI_PXSCTL_DET_0 0x00000000
+#define V_PCH_SATA_AHCI_PXSCTL_DET_1 0x00000001
+#define V_PCH_SATA_AHCI_PXSCTL_DET_4 0x00000004
+#define R_PCH_SATA_AHCI_P0SERR 0x130
+#define R_PCH_SATA_AHCI_P1SERR 0x1B0
+#define R_PCH_SATA_AHCI_P2SERR 0x230
+#define R_PCH_SATA_AHCI_P3SERR 0x2B0
+#define R_PCH_SATA_AHCI_P4SERR 0x330
+#define R_PCH_SATA_AHCI_P5SERR 0x3B0
+#define R_PCH_SATA_AHCI_P6SERR 0x430
+#define B_PCH_SATA_AHCI_PXSERR_EXCHG BIT26
+#define B_PCH_SATA_AHCI_PXSERR_UN_FIS_TYPE BIT25
+#define B_PCH_SATA_AHCI_PXSERR_TRSTE_24 BIT24
+#define B_PCH_SATA_AHCI_PXSERR_TRSTE_23 BIT23
+#define B_PCH_SATA_AHCI_PXSERR_HANDSHAKE BIT22
+#define B_PCH_SATA_AHCI_PXSERR_CRC_ERROR BIT21
+#define B_PCH_SATA_AHCI_PXSERR_10B8B_DECERR BIT19
+#define B_PCH_SATA_AHCI_PXSERR_COMM_WAKE BIT18
+#define B_PCH_SATA_AHCI_PXSERR_PHY_ERROR BIT17
+#define B_PCH_SATA_AHCI_PXSERR_PHY_RDY_CHG BIT16
+#define B_PCH_SATA_AHCI_PXSERR_INTRNAL_ERR BIT11
+#define B_PCH_SATA_AHCI_PXSERR_PROTOCOL_ERR BIT10
+#define B_PCH_SATA_AHCI_PXSERR_PCDIE BIT9
+#define B_PCH_SATA_AHCI_PXSERR_TDIE BIT8
+#define B_PCH_SATA_AHCI_PXSERR_RCE BIT1
+#define B_PCH_SATA_AHCI_PXSERR_RDIE BIT0
+#define R_PCH_SATA_AHCI_P0SACT 0x134
+#define R_PCH_SATA_AHCI_P1SACT 0x1B4
+#define R_PCH_SATA_AHCI_P2SACT 0x234
+#define R_PCH_SATA_AHCI_P3SACT 0x2B4
+#define R_PCH_SATA_AHCI_P4SACT 0x334
+#define R_PCH_SATA_AHCI_P5SACT 0x3B4
+#define R_PCH_SATA_AHCI_P6SACT 0x434
+#define B_PCH_SATA_AHCI_PXSACT_DS 0xFFFFFFFF
+#define R_PCH_SATA_AHCI_P0CI 0x138
+#define R_PCH_SATA_AHCI_P1CI 0x1B8
+#define R_PCH_SATA_AHCI_P2CI 0x238
+#define R_PCH_SATA_AHCI_P3CI 0x2B8
+#define R_PCH_SATA_AHCI_P4CI 0x338
+#define R_PCH_SATA_AHCI_P5CI 0x3B8
+#define R_PCH_SATA_AHCI_P6CI 0x438
+#define B_PCH_SATA_AHCI_PXCI 0xFFFFFFFF
+
+//
+// SATA AHCI Device ID macros
+//
+#define IS_PCH_H_SATA_AHCI_DEVICE_ID(DeviceId) \
+ ( \
+ (DeviceId == V_SKL_PCH_H_SATA_DEVICE_ID_D_AHCI_A0) || \
+ (DeviceId == V_SKL_PCH_H_SATA_DEVICE_ID_D_AHCI) || \
+ (DeviceId == V_KBL_PCH_H_SATA_DEVICE_ID_D_AHCI) \
+ )
+
+#define IS_PCH_LP_SATA_AHCI_DEVICE_ID(DeviceId) \
+ ( \
+ (DeviceId == V_PCH_LP_SATA_DEVICE_ID_M_AHCI) \
+ )
+
+#define IS_PCH_SATA_AHCI_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_SATA_AHCI_DEVICE_ID(DeviceId) || \
+ IS_PCH_LP_SATA_AHCI_DEVICE_ID(DeviceId) \
+ )
+
+//
+// SATA RAID Device ID macros
+//
+#define IS_PCH_H_SATA_RAID_DEVICE_ID(DeviceId) \
+ ( \
+ (DeviceId == V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID) || \
+ (DeviceId == V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID_PREM) || \
+ (DeviceId == V_PCH_H_SATA_DEVICE_ID_D_RAID_ALTDIS) || \
+ (DeviceId == V_PCH_H_SATA_DEVICE_ID_D_RAID_RSTE) || \
+ (DeviceId == V_SKL_PCH_H_SATA_DEVICE_ID_D_RAID_RRT) || \
+ (DeviceId == V_KBL_PCH_H_SATA_DEVICE_ID_D_RAID) || \
+ (DeviceId == V_KBL_PCH_H_SATA_DEVICE_ID_D_RAID_PREM) \
+ )
+
+
+#define IS_PCH_LP_SATA_RAID_DEVICE_ID(DeviceId) \
+ ( \
+ (DeviceId == V_PCH_LP_SATA_DEVICE_ID_M_RAID) || \
+ (DeviceId == V_PCH_LP_SATA_DEVICE_ID_M_RAID_ALTDIS) || \
+ (DeviceId == V_PCH_LP_SATA_DEVICE_ID_M_RAID_PREM) || \
+ (DeviceId == V_PCH_LP_SATA_DEVICE_ID_M_RAID_RRT) \
+ )
+
+#define IS_PCH_SATA_RAID_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_SATA_RAID_DEVICE_ID(DeviceId) || \
+ IS_PCH_LP_SATA_RAID_DEVICE_ID(DeviceId) \
+ )
+
+//
+// Combined SATA IDE/AHCI/RAID Device ID macros
+//
+#define IS_PCH_H_SATA_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_SATA_AHCI_DEVICE_ID(DeviceId) || \
+ IS_PCH_H_SATA_RAID_DEVICE_ID(DeviceId) \
+ )
+
+#define IS_PCH_LP_SATA_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_LP_SATA_AHCI_DEVICE_ID(DeviceId) || \
+ IS_PCH_LP_SATA_RAID_DEVICE_ID(DeviceId) \
+ )
+#define IS_PCH_SATA_DEVICE_ID(DeviceId) \
+ ( \
+ IS_PCH_H_SATA_DEVICE_ID(DeviceId) || \
+ IS_PCH_LP_SATA_DEVICE_ID(DeviceId) \
+ )
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsScs.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsScs.h
new file mode 100644
index 0000000000..b1872adbe6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsScs.h
@@ -0,0 +1,202 @@
+/** @file
+ Register names for PCH Storage and Communication Subsystem
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_SCS_H_
+#define _PCH_REGS_SCS_H_
+
+//
+// SCS eMMC Controller Registers (D30:F4)
+//
+#define PCI_DEVICE_NUMBER_PCH_SCS_EMMC 30
+#define PCI_FUNCTION_NUMBER_PCH_SCS_EMMC 4
+#define V_PCH_SCS_EMMC_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+#define V_PCH_SCS_EMMC_DEVICE_ID 0x9D2B
+
+//
+// SCS SDIO Controller Registers (D30:F5)
+//
+#define PCI_DEVICE_NUMBER_PCH_SCS_SDIO 30
+#define PCI_FUNCTION_NUMBER_PCH_SCS_SDIO 5
+#define V_PCH_SCS_SDIO_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+#define V_PCH_SCS_SDIO_DEVICE_ID 0x9D2C
+
+//
+// SCS SDCARD Controller Registers (D30:F6)
+//
+#define PCI_DEVICE_NUMBER_PCH_SCS_SDCARD 30
+#define PCI_FUNCTION_NUMBER_PCH_SCS_SDCARD 6
+#define V_PCH_SCS_SDCARD_VENDOR_ID V_PCH_INTEL_VENDOR_ID
+#define V_PCH_SCS_SDCARD_DEVICE_ID 0x9D2D
+
+//
+// SCS Devices PCI Config Space Registers
+//
+#define R_PCH_SCS_DEV_PCS 0x84 ///< PME Control Status
+#define B_PCH_SCS_DEV_PCS_PMESTS BIT15 ///< PME Status
+#define B_PCH_SCS_DEV_PCS_PMEEN BIT8 ///< PME Enable
+#define B_PCH_SCS_DEV_PCS_NSS BIT3 ///< No Soft Reset
+#define B_PCH_SCS_DEV_PCS_PS (BIT1 | BIT0) ///< Power State
+#define B_PCH_SCS_DEV_PCS_PS_D3HOT (BIT1 | BIT0) ///< Power State: D3Hot State
+#define R_PCH_SCS_DEV_PG_CONFIG 0xA2 ///< PG Config
+#define B_PCH_SCS_DEV_PG_CONFIG_SE BIT3 ///< Sleep Enable
+#define B_PCH_SCS_DEV_PG_CONFIG_PGE BIT2 ///< PG Enable
+#define B_PCH_SCS_DEV_PG_CONFIG_I3E BIT1 ///< I3 Enable
+#define B_PCH_SCS_DEV_PG_CONFIG_PMCRE BIT0 ///< PMC Request Enable
+#define V_PCH_SCS_DEV_BAR0_SIZE 0x1000 ///< BAR0 size
+//
+// SCS Devices MMIO Space Register
+//
+#define R_PCH_SCS_DEV_MEM_DMAADR 0x00
+#define R_PCH_SCS_DEV_MEM_BLKSZ 0x04
+#define R_PCH_SCS_DEV_MEM_BLKCNT 0x06
+#define R_PCH_SCS_DEV_MEM_CMDARG 0x08
+#define R_PCH_SCS_DEV_MEM_XFRMODE 0x0C
+#define B_PCH_SCS_DEV_MEM_XFRMODE_DMA_EN BIT0
+#define B_PCH_SCS_DEV_MEM_XFRMODE_BLKCNT_EN BIT1
+#define B_PCH_SCS_DEV_MEM_XFRMODE_AUTOCMD_EN_MASK (BIT2 | BIT3)
+#define V_PCH_SCS_DEV_MEM_XFRMODE_AUTOCMD12_EN 1
+#define B_PCH_SCS_DEV_MEM_XFRMODE_DATA_TRANS_DIR BIT4 ///< 1: Read (Card to Host), 0: Write (Host to Card)
+#define B_PCH_SCS_DEV_MEM_XFRMODE_MULTI_SINGLE_BLK BIT5 ///< 1: Multiple Block, 0: Single Block
+#define R_PCH_SCS_DEV_MEM_SDCMD 0x0E
+#define B_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_MASK (BIT0 | BIT1)
+#define V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_NO_RESP 0
+#define V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP136 1
+#define V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP48 2
+#define V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP48_CHK 3
+#define B_PCH_SCS_DEV_MEM_SDCMD_CMD_CRC_CHECK_EN BIT3
+#define B_PCH_SCS_DEV_MEM_SDCMD_CMD_INDEX_CHECK_EN BIT4
+#define B_PCH_SCS_DEV_MEM_SDCMD_DATA_PRESENT_SEL BIT5
+#define R_PCH_SCS_DEV_MEM_RESP 0x10
+#define R_PCH_SCS_DEV_MEM_BUFDATAPORT 0x20
+#define R_PCH_SCS_DEV_MEM_PSTATE 0x24
+#define B_PCH_SCS_DEV_MEM_PSTATE_DAT0 BIT20
+#define R_PCH_SCS_DEV_MEM_PWRCTL 0x29
+#define R_PCH_SCS_DEV_MEM_CLKCTL 0x2C
+#define R_PCH_SCS_DEV_MEM_TIMEOUT_CTL 0x2E ///< Timeout Control
+#define B_PCH_SCS_DEV_MEM_TIMEOUT_CTL_DTCV 0x0F ///< Data Timeout Counter Value
+#define R_PCH_SCS_DEV_MEM_SWRST 0x2F
+#define B_PCH_SCS_DEV_MEM_SWRST_CMDLINE BIT1
+#define B_PCH_SCS_DEV_MEM_SWRST_DATALINE BIT2
+#define R_PCH_SCS_DEV_MEM_NINTSTS 0x30
+#define B_PCH_SCS_DEV_MEM_NINTSTS_MASK 0xFFFF
+#define B_PCH_SCS_DEV_MEM_NINTSTS_CLEAR_MASK 0x60FF
+#define B_PCH_SCS_DEV_MEM_NINTSTS_CMD_COMPLETE BIT0
+#define B_PCH_SCS_DEV_MEM_NINTSTS_TRANSFER_COMPLETE BIT1
+#define B_PCH_SCS_DEV_MEM_NINTSTS_DMA_INTERRUPT BIT3
+#define B_PCH_SCS_DEV_MEM_NINTSTS_BUF_READ_READY_INTR BIT5
+#define R_PCH_SCS_DEV_MEM_ERINTSTS 0x32
+#define B_PCH_SCS_DEV_MEM_ERINTSTS_MASK 0x13FF
+#define B_PCH_SCS_DEV_MEM_ERINTSTS_CLEAR_MASK 0x13FF
+#define R_PCH_SCS_DEV_MEM_NINTEN 0x34
+#define B_PCH_SCS_DEV_MEM_NINTEN_MASK 0x7FFF
+#define R_PCH_SCS_DEV_MEM_ERINTEN 0x36
+#define B_PCH_SCS_DEV_MEM_ERINTEN_MASK 0x13FF
+#define R_PCH_SCS_DEV_MEM_NINTSIGNEN 0x38
+#define B_PCH_SCS_DEV_MEM_NINTSIGNEN_MASK 0x7FFF
+#define R_PCH_SCS_DEV_MEM_ERINTSIGNEN 0x3A
+#define B_PCH_SCS_DEV_MEM_ERINTSIGNEN_MASK 0x13FF
+#define R_PCH_SCS_DEV_MEM_HOST_CTL2 0x3E
+#define B_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_MASK (BIT0 | BIT1 | BIT2)
+#define V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_HS400 5
+#define V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_DDR50 4
+#define V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_SDR104 3
+#define V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_SDR25 1
+#define R_PCH_SCS_DEV_MEM_CAP1 0x40
+#define R_PCH_SCS_DEV_MEM_CAP2 0x44
+#define B_PCH_SCS_DEV_MEM_CAP2_HS400_SUPPORT BIT31
+#define B_PCH_SCS_DEV_MEM_CAP2_SDR104_SUPPORT BIT1
+#define R_PCH_SCS_DEV_MEM_CESHC2 0x3C ///< Auto CMD12 Error Status Register & Host Control 2
+#define B_PCH_SCS_DEV_MEM_CESHC2_ASYNC_INT BIT30 ///< Asynchronous Interrupt Enable
+#define R_PCH_SCS_DEV_MEM_CAP_BYPASS_CONTROL 0x810
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_CONTROL_EN 0x5A
+#define R_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1 0x814
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_EMMC_DEFAULTS 0x3C80EB1E
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_SDIO_DEFAULTS 0x1C80EF1E
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_SDCARD_DEFAULTS 0x1C80E75C
+#define B_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_HS400 BIT29
+#define B_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMEOUT_CLK_FREQ (BIT27 | BIT26 | BIT25 | BIT24 | BIT23 | BIT22)
+#define N_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMEOUT_CLK_FREQ 22
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMEOUT_CLK_FREQ 0x1
+#define B_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMER_COUNT (BIT20 | BIT19 | BIT18 | BIT17)
+#define N_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMER_COUNT 17
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_TIMER_COUNT 0x8
+#define B_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_SLOT_TYPE (BIT12 | BIT11)
+#define N_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_SLOT_TYPE 11
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_SLOT_TYPE_EMBEDDED 0x1
+#define R_PCH_SCS_DEV_MEM_CAP_BYPASS_REG2 0x818
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG2_EMMC_DEFAULTS 0x040040C8
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG2_SDIO_DEFAULTS 0x040000C8
+#define V_PCH_SCS_DEV_MEM_CAP_BYPASS_REG2_SDCARD_DEFAULTS 0x040000C8
+#define R_PCH_SCS_DEV_MEM_TX_CMD_DLL_CNTL1 0x820
+#define R_PCH_SCS_DEV_MEM_TX_CMD_DLL_CNTL2 0x80C
+#define R_PCH_SCS_DEV_MEM_TX_DATA_DLL_CNTL1 0x824
+#define R_PCH_SCS_DEV_MEM_TX_DATA_DLL_CNTL2 0x828
+#define R_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL1 0x82C
+#define R_PCH_SCS_DEV_MEM_RX_STROBE_DLL_CNTL 0x830
+#define R_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL2 0x834
+#define N_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL2_CLKSRC_RX 16
+#define V_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL2_CLKSRC_RX_CLK_AUTO 0x2
+#define V_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL2_CLKSRC_RX_CLK_BEFORE 0x1
+#define V_PCH_SCS_DEV_MEM_RX_CMD_DATA_DLL_CNTL2_CLKSRC_RX_CLK_AFTER 0x0
+
+//
+// SCS Private Configuration Space Registers
+//
+#define R_PCH_PCR_SCS_IOSFCTL 0x00 ///< IOSF Control
+#define B_PCH_PCR_SCS_IOSFCTL_NSNPDIS BIT7 ///< Non-Snoop Disable
+#define B_PCH_PCR_SCS_IOSFCTL_MAX_RD_PEND (BIT3 | BIT2 | BIT1 | BIT0) ///< Max upstream pending reads
+#define R_PCH_PCR_SCS_OCPCTL 0x10 ///< OCP Control
+#define B_PCH_PCR_SCS_OCPCTL_NPEN BIT0 ///< Downstream non-posted memory write capability
+#define R_PCH_PCR_SCS_PMCTL 0x1D0 ///< Power Management Control
+#define R_PCH_PCR_SCS_PCICFGCTR_EMMC 0x200 ///< PCI Configuration Control 1 - eMMC
+#define R_PCH_PCR_SCS_PCICFGCTR_SDIO 0x204 ///< PCI Configuration Control 2 - SDIO
+#define R_PCH_PCR_SCS_PCICFGCTR_SDCARD 0x208 ///< PCI Configuration Control 3 - SD Card
+#define B_PCH_PCR_SCS_PCICFGCTR_PCI_IRQ 0x0FF00000 ///< PCI IRQ number
+#define N_PCH_PCR_SCS_PCICFGCTR_PCI_IRQ 20
+#define B_PCH_PCR_SCS_PCICFGCTR_ACPI_IRQ 0x000FF000 ///< ACPI IRQ number
+#define N_PCH_PCR_SCS_PCICFGCTR_ACPI_IRQ 12
+#define B_PCH_PCR_SCS_PCICFGCTR_IPIN1 (BIT11 | BIT10 | BIT9 | BIT8) ///< Interrupt Pin
+#define N_PCH_PCR_SCS_PCICFGCTR_IPIN1 8
+#define B_PCH_PCR_SCS_PCICFGCTR_BAR1DIS BIT7 ///< BAR 1 Disable
+#define B_PCH_PCR_SCS_PCICFGCTR_PS 0x7C ///< PME Support
+#define B_PCH_PCR_SCS_PCICFGCTR_ACPI_INT_EN BIT1 ///< ACPI Interrupt Enable
+#define B_PCH_PCR_SCS_PCICFGCTR_PCI_CFG_DIS BIT0 ///< PCI Configuration Space Disable
+
+#define R_PCH_PCR_SCS_GPPRVRW1 0x600 ///< Clock Gating Control
+#define R_PCH_PCR_SCS_GPPRVRW2 0x604 ///< Host Controller Disable
+#define B_PCH_PCR_SCS_GPPRVRW2_EMMC_DIS BIT1 ///< eMMC Host Controller Disable
+#define B_PCH_PCR_SCS_GPPRVRW2_SDIO_SDCARD_DIS BIT2 ///< 1: SDIO Host Controller Disable, 0: SDCARD Host Controller Disable
+#define R_PCH_PCR_SCS_GPPRVRW6 0x614 ///< 1.8V Signal Select Delay Control
+#define V_PCH_PCR_SCS_GPPRVRW6_1P8_SEL_DELAY 0x7F ///< Rcomp SDCARD 10ms delay during switch
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSerialIo.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSerialIo.h
new file mode 100644
index 0000000000..461b935fde
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSerialIo.h
@@ -0,0 +1,325 @@
+/** @file
+ Register names for PCH Serial IO Controllers
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_SERIAL_IO_
+#define _PCH_REGS_SERIAL_IO_
+
+
+//
+// Serial IO I2C0 Controller Registers (D21:F0)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C0 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C0 0
+#define V_PCH_LP_SERIAL_IO_I2C0_DEVICE_ID 0x9D60
+#define V_SKL_PCH_H_SERIAL_IO_I2C0_DEVICE_ID 0xA160
+#define V_KBL_PCH_H_SERIAL_IO_I2C0_DEVICE_ID 0xA2E0
+
+//
+// Serial IO I2C1 Controller Registers (D21:F1)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C1 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C1 1
+#define V_PCH_LP_SERIAL_IO_I2C1_DEVICE_ID 0x9D61
+#define V_SKL_PCH_H_SERIAL_IO_I2C1_DEVICE_ID 0xA161
+#define V_KBL_PCH_H_SERIAL_IO_I2C1_DEVICE_ID 0xA2E1
+
+//
+// Serial IO I2C2 Controller Registers (D21:F2)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C2 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C2 2
+#define V_PCH_LP_SERIAL_IO_I2C2_DEVICE_ID 0x9D62
+#define V_SKL_PCH_H_SERIAL_IO_I2C2_DEVICE_ID 0xA162
+#define V_KBL_PCH_H_SERIAL_IO_I2C2_DEVICE_ID 0xA2E2
+
+//
+// Serial IO I2C3 Controller Registers (D21:F3)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C3 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C3 3
+#define V_PCH_LP_SERIAL_IO_I2C3_DEVICE_ID 0x9D63
+#define V_SKL_PCH_H_SERIAL_IO_I2C3_DEVICE_ID 0xA163
+#define V_KBL_PCH_H_SERIAL_IO_I2C3_DEVICE_ID 0xA2E3
+
+//
+// Serial IO I2C4 Controller Registers (D25:F2)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C4 25
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C4 2
+#define V_PCH_LP_SERIAL_IO_I2C4_DEVICE_ID 0x9D64
+
+//
+// Serial IO I2C5 Controller Registers (D25:F1)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C5 25
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C5 1
+#define V_PCH_LP_SERIAL_IO_I2C5_DEVICE_ID 0x9D65
+
+//
+// Serial IO SPI0 Controller Registers (D30:F2)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI0 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI0 2
+#define V_PCH_LP_SERIAL_IO_SPI0_DEVICE_ID 0x9D29
+#define V_SKL_PCH_H_SERIAL_IO_SPI0_DEVICE_ID 0xA129
+#define V_KBL_PCH_H_SERIAL_IO_SPI0_DEVICE_ID 0xA2A9
+
+//
+// Serial IO SPI1 Controller Registers (D30:F3)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI1 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI1 3
+#define V_PCH_LP_SERIAL_IO_SPI1_DEVICE_ID 0x9D2A
+#define V_SKL_PCH_H_SERIAL_IO_SPI1_DEVICE_ID 0xA129
+#define V_KBL_PCH_H_SERIAL_IO_SPI1_DEVICE_ID 0xA2AA
+
+//
+// Serial IO UART0 Controller Registers (D30:F0)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART0 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART0 0
+#define V_PCH_LP_SERIAL_IO_UART0_DEVICE_ID 0x9D27
+#define V_SKL_PCH_H_SERIAL_IO_UART0_DEVICE_ID 0xA127
+#define V_KBL_PCH_H_SERIAL_IO_UART0_DEVICE_ID 0xA2A7
+
+//
+// Serial IO UART1 Controller Registers (D30:F1)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART1 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART1 1
+#define V_PCH_LP_SERIAL_IO_UART1_DEVICE_ID 0x9D28
+#define V_SKL_PCH_H_SERIAL_IO_UART1_DEVICE_ID 0xA128
+#define V_KBL_PCH_H_SERIAL_IO_UART1_DEVICE_ID 0xA2A8
+
+//
+// Serial IO UART2 Controller Registers (D25:F0)
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART2 25
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART2 0
+#define V_PCH_LP_SERIAL_IO_UART2_DEVICE_ID 0x9D66
+#define V_SKL_PCH_H_SERIAL_IO_UART2_DEVICE_ID 0xA166
+#define V_KBL_PCH_H_SERIAL_IO_UART2_DEVICE_ID 0xA2E6
+
+#define V_PCH_SERIAL_IO_DEV_MIN_FUN 0
+#define V_PCH_SERIAL_IO_DEV_MAX_FUN 5
+
+//
+// Serial IO Controllers General PCI Configuration Registers
+// registers accessed using PciD21FxRegBase + offset
+//
+#define R_PCH_SERIAL_IO_BAR0_LOW 0x10
+#define B_PCH_SERIAL_IO_BAR0_LOW_BAR 0xFFFFF000
+#define R_PCH_SERIAL_IO_BAR0_HIGH 0x14
+#define R_PCH_SERIAL_IO_BAR1_LOW 0x18
+#define B_PCH_SERIAL_IO_BAR1_LOW_BAR 0xFFFFF000
+#define R_PCH_SERIAL_IO_BAR1_HIGH 0x1C
+#define V_PCH_SERIAL_IO_BAR_SIZE (4 * 1024)
+#define N_PCH_SERIAL_IO_BAR_ALIGNMENT 12
+
+#define R_PCH_SERIAL_IO_PME_CTRL_STS 0x84
+#define B_PCH_SERIAL_IO_PME_CTRL_STS_PWR_ST (BIT1| BIT0)
+
+#define R_PCH_SERIAL_IO_D0I3MAXDEVPG 0xA0
+#define B_PCH_SERIAL_IO_D0I3MAXDEVPG_PMCRE BIT16
+#define B_PCH_SERIAL_IO_D0I3MAXDEVPG_I3E BIT17
+#define B_PCH_SERIAL_IO_D0I3MAXDEVPG_PGE BIT18
+
+#define R_PCH_SERIAL_IO_INTERRUPTREG 0x3C
+#define B_PCH_SERIAL_IO_INTERRUPTREG_INTLINE 0x000000FF
+
+//
+// Serial IO Controllers Private Registers
+// registers accessed : BAR0 + offset
+//
+#define R_PCH_SERIAL_IO_SSCR1 0x4
+#define B_PCH_SERIAL_IO_SSCR1_IFS BIT16
+
+#define R_PCH_SERIAL_IO_PPR_CLK 0x200
+#define B_PCH_SERIAL_IO_PPR_CLK_EN BIT0
+#define B_PCH_SERIAL_IO_PPR_CLK_UPDATE BIT31
+#define V_PCH_SERIAL_IO_PPR_CLK_M_DIV 0x30
+#define V_PCH_SERIAL_IO_PPR_CLK_N_DIV 0xC35
+
+#define R_PCH_SERIAL_IO_PPR_RESETS 0x204
+#define B_PCH_SERIAL_IO_PPR_RESETS_FUNC BIT0
+#define B_PCH_SERIAL_IO_PPR_RESETS_APB BIT1
+#define B_PCH_SERIAL_IO_PPR_RESETS_IDMA BIT2
+
+#define R_PCH_SERIAL_IO_ACTIVE_LTR 0x210
+#define R_PCH_SERIAL_IO_IDLE_LTR 0x214
+#define B_PCH_SERIAL_IO_LTR_SNOOP_VALUE 0x000003FF
+#define B_PCH_SERIAL_IO_LTR_SNOOP_SCALE 0x00001C00
+#define B_PCH_SERIAL_IO_LTR_SNOOP_REQUIREMENT BIT15
+
+#define R_PCH_SERIAL_IO_SPI_CS_CONTROL 0x224
+#define B_PCH_SERIAL_IO_SPI_CS_CONTROL_STATE BIT1
+#define B_PCH_SERIAL_IO_SPI_CS_CONTROL_MODE BIT0
+
+#define R_PCH_SERIAL_IO_REMAP_ADR_LOW 0x240
+#define R_PCH_SERIAL_IO_REMAP_ADR_HIGH 0x244
+
+#define R_PCH_SERIAL_IO_I2C_SDA_HOLD 0x7C
+#define V_PCH_SERIAL_IO_I2C_SDA_HOLD_VALUE 0x002C002C
+
+//
+// I2C Controller
+// Registers accessed through BAR0 + offset
+//
+#define R_IC_CON 0x00 // I2c Control
+#define B_IC_MASTER_MODE BIT0
+#define B_IC_RESTART_EN BIT5
+#define B_IC_SLAVE_DISABLE BIT6
+#define V_IC_SPEED_STANDARD 0x02
+#define V_IC_SPEED_FAST 0x04
+#define V_IC_SPEED_HIGH 0x06
+
+#define R_IC_TAR 0x04 // I2c Target Address
+#define B_IC_TAR_10BITADDR_MASTER BIT12
+
+#define R_IC_DATA_CMD 0x10 // I2c Rx/Tx Data Buffer and Command
+#define B_IC_CMD_READ BIT8 // 1 = read, 0 = write
+#define B_IC_CMD_STOP BIT9 // 1 = STOP
+#define B_IC_CMD_RESTART BIT10 // 1 = IC_RESTART_EN
+#define V_IC_WRITE_CMD_MASK 0xFF
+
+#define R_IC_SS_SCL_HCNT 0x14 // Standard Speed I2c Clock SCL High Count
+#define R_IC_SS_SCL_LCNT 0x18 // Standard Speed I2c Clock SCL Low Count
+#define R_IC_FS_SCL_HCNT 0x1C // Full Speed I2c Clock SCL High Count
+#define R_IC_FS_SCL_LCNT 0x20 // Full Speed I2c Clock SCL Low Count
+#define R_IC_HS_SCL_HCNT 0x24 // High Speed I2c Clock SCL High Count
+#define R_IC_HS_SCL_LCNT 0x28 // High Speed I2c Clock SCL Low Count
+#define R_IC_INTR_STAT 0x2C // I2c Inetrrupt Status
+#define R_IC_INTR_MASK 0x30 // I2c Interrupt Mask
+#define B_IC_INTR_GEN_CALL BIT11 // General call received
+#define B_IC_INTR_START_DET BIT10
+#define B_IC_INTR_STOP_DET BIT9
+#define B_IC_INTR_ACTIVITY BIT8
+#define B_IC_INTR_TX_ABRT BIT6 // Set on NACK
+#define B_IC_INTR_TX_EMPTY BIT4
+#define B_IC_INTR_TX_OVER BIT3
+#define B_IC_INTR_RX_FULL BIT2 // Data bytes in RX FIFO over threshold
+#define B_IC_INTR_RX_OVER BIT1
+#define B_IC_INTR_RX_UNDER BIT0
+#define R_IC_RAW_INTR_STAT ( 0x34) // I2c Raw Interrupt Status
+#define R_IC_RX_TL ( 0x38) // I2c Receive FIFO Threshold
+#define R_IC_TX_TL ( 0x3C) // I2c Transmit FIFO Threshold
+#define R_IC_CLR_INTR ( 0x40) // Clear Combined and Individual Interrupts
+#define R_IC_CLR_RX_UNDER ( 0x44) // Clear RX_UNDER Interrupt
+#define R_IC_CLR_RX_OVER ( 0x48) // Clear RX_OVERinterrupt
+#define R_IC_CLR_TX_OVER ( 0x4C) // Clear TX_OVER interrupt
+#define R_IC_CLR_RD_REQ ( 0x50) // Clear RD_REQ interrupt
+#define R_IC_CLR_TX_ABRT ( 0x54) // Clear TX_ABRT interrupt
+#define R_IC_CLR_RX_DONE ( 0x58) // Clear RX_DONE interrupt
+#define R_IC_CLR_ACTIVITY ( 0x5C) // Clear ACTIVITY interrupt
+#define R_IC_CLR_STOP_DET ( 0x60) // Clear STOP_DET interrupt
+#define R_IC_CLR_START_DET ( 0x64) // Clear START_DET interrupt
+#define R_IC_CLR_GEN_CALL ( 0x68) // Clear GEN_CALL interrupt
+#define R_IC_ENABLE ( 0x6C) // I2c Enable
+
+#define R_IC_STATUS 0x70 // I2c Status
+#define B_IC_STATUS_RFF BIT4 // RX FIFO is completely full
+#define B_IC_STATUS_RFNE BIT3 // RX FIFO is not empty
+#define B_IC_STATUS_TFE BIT2 // TX FIFO is completely empty
+#define B_IC_STATUS_TFNF BIT1 // TX FIFO is not full
+#define B_IC_STATUS_ACTIVITY BIT0 // Controller Activity Status.
+
+#define R_IC_TXFL R ( 0x74) // Transmit FIFO Level Register
+#define R_IC_RXFLR ( 0x78) // Receive FIFO Level Register
+#define R_IC_SDA_HOLD ( 0x7C)
+#define R_IC_TX_ABRT_SOURCE ( 0x80) // I2c Transmit Abort Status Register
+#define B_IC_TX_ABRT_7B_ADDR_NACK BIT0 // NACK on 7-bit address
+
+#define R_IC_SDA_SETUP ( 0x94) // I2c SDA Setup Register
+#define R_IC_ACK_GENERAL_CALL ( 0x98) // I2c ACK General Call Register
+#define R_IC_ENABLE_STATUS ( 0x9C) // I2c Enable Status Register
+#define B_IC_EN BIT0 // I2c enable status
+
+#define R_IC_CLK_GATE (0xC0)
+#define R_IC_COMP_PARAM ( 0xF4) // Component Parameter Register
+#define R_IC_COMP_VERSION ( 0xF8) // Component Version ID
+#define R_IC_COMP_TYPE ( 0xFC) // Component Type
+
+
+
+//
+// Bridge Private Configuration Registers
+// accessed only through SB messaging. SB access = SerialIo IOSF2OCP Bridge Port ID + offset
+//
+#define R_PCH_PCR_SERIAL_IO_PMCTL 0x1D0
+#define V_PCH_PCR_SERIAL_IO_PMCTL_PWR_GATING 0x3F
+
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRLx 0x200
+#define V_PCH_PCR_SERIAL_IO_PCICFGCTRL_N_OFFS 0x04
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL1 0x200 //I2C0
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL2 0x204 //I2C1
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL3 0x208 //I2C2
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL4 0x20C //I2C3
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL5 0x210 //I2C4
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL6 0x214 //I2C5
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL9 0x218 //UA00
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL10 0x21C //UA01
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL11 0x220 //UA02
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL13 0x224 //SPI0
+#define R_PCH_PCR_SERIAL_IO_PCICFGCTRL14 0x228 //SPI1
+
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_CFG_DIS BIT0
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_INTR_EN BIT1
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_BAR1_DIS BIT7
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_INT_PIN (BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_PCR_SERIAL_IO_PCICFGCTRL_INT_PIN 8
+#define V_PCH_PCR_SERIAL_IO_PCICFGCTRL_INTA 0x01
+#define V_PCH_PCR_SERIAL_IO_PCICFGCTRL_INTB 0x02
+#define V_PCH_PCR_SERIAL_IO_PCICFGCTRL_INTC 0x03
+#define V_PCH_PCR_SERIAL_IO_PCICFGCTRL_INTD 0x04
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_IRQ 0x000FF000
+#define N_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_IRQ 12
+#define B_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_IRQ 0x0FF00000
+#define N_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_IRQ 20
+
+#define R_PCH_PCR_SERIAL_IO_GPPRVRW2 0x604
+#define V_PCH_PCR_SERIAL_IO_GPPRVRW2_CLK_GATING (BIT11 | BIT1)
+
+#define R_PCH_PCR_SERIAL_IO_GPPRVRW7 0x618
+#define B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART0_BYTE_ADDR_EN BIT0
+#define B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART1_BYTE_ADDR_EN BIT1
+#define B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART2_BYTE_ADDR_EN BIT2
+
+//
+// Number of pins used by SerialIo controllers
+//
+#define PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER 2
+#define PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER 4
+#define PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER_NO_FLOW_CTRL 2
+#define PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER 4
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSmbus.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSmbus.h
new file mode 100644
index 0000000000..9682040879
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSmbus.h
@@ -0,0 +1,149 @@
+/** @file
+ Register names for PCH Smbus Device.
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_SMBUS_H_
+#define _PCH_REGS_SMBUS_H_
+
+//
+// SMBus Controller Registers (D31:F4)
+//
+#define PCI_DEVICE_NUMBER_PCH_SMBUS 31
+#define PCI_FUNCTION_NUMBER_PCH_SMBUS 4
+#define R_PCH_SMBUS_BASE 0x20
+#define V_PCH_SMBUS_BASE_SIZE (1 << 5)
+#define B_PCH_SMBUS_BASE_BAR 0x0000FFE0
+#define R_PCH_SMBUS_HOSTC 0x40
+#define B_PCH_SMBUS_HOSTC_SPDWD BIT4
+#define B_PCH_SMBUS_HOSTC_SSRESET BIT3
+#define B_PCH_SMBUS_HOSTC_I2C_EN BIT2
+#define B_PCH_SMBUS_HOSTC_SMI_EN BIT1
+#define B_PCH_SMBUS_HOSTC_HST_EN BIT0
+#define R_PCH_SMBUS_TCOBASE 0x50
+#define B_PCH_SMBUS_TCOBASE_BAR 0x0000FFE0
+#define R_PCH_SMBUS_TCOCTL 0x54
+#define B_PCH_SMBUS_TCOCTL_TCO_BASE_EN BIT8
+#define B_PCH_SMBUS_TCOCTL_TCO_BASE_LOCK BIT0
+#define R_PCH_SMBUS_64 0x64
+#define R_PCH_SMBUS_80 0x80
+
+//
+// SMBus I/O Registers
+//
+#define R_PCH_SMBUS_HSTS 0x00 ///< Host Status Register R/W
+#define B_PCH_SMBUS_HBSY 0x01
+#define B_PCH_SMBUS_INTR 0x02
+#define B_PCH_SMBUS_DERR 0x04
+#define B_PCH_SMBUS_BERR 0x08
+#define B_PCH_SMBUS_FAIL 0x10
+#define B_PCH_SMBUS_SMBALERT_STS 0x20
+#define B_PCH_SMBUS_IUS 0x40
+#define B_PCH_SMBUS_BYTE_DONE_STS 0x80
+#define B_PCH_SMBUS_ERROR (B_PCH_SMBUS_DERR | B_PCH_SMBUS_BERR | B_PCH_SMBUS_FAIL)
+#define B_PCH_SMBUS_HSTS_ALL 0xFF
+#define R_PCH_SMBUS_HCTL 0x02 ///< Host Control Register R/W
+#define B_PCH_SMBUS_INTREN 0x01
+#define B_PCH_SMBUS_KILL 0x02
+#define B_PCH_SMBUS_SMB_CMD 0x1C
+#define V_PCH_SMBUS_SMB_CMD_QUICK 0x00
+#define V_PCH_SMBUS_SMB_CMD_BYTE 0x04
+#define V_PCH_SMBUS_SMB_CMD_BYTE_DATA 0x08
+#define V_PCH_SMBUS_SMB_CMD_WORD_DATA 0x0C
+#define V_PCH_SMBUS_SMB_CMD_PROCESS_CALL 0x10
+#define V_PCH_SMBUS_SMB_CMD_BLOCK 0x14
+#define V_PCH_SMBUS_SMB_CMD_IIC_READ 0x18
+#define V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS 0x1C
+#define B_PCH_SMBUS_LAST_BYTE 0x20
+#define B_PCH_SMBUS_START 0x40
+#define B_PCH_SMBUS_PEC_EN 0x80
+#define R_PCH_SMBUS_HCMD 0x03 ///< Host Command Register R/W
+#define R_PCH_SMBUS_TSA 0x04 ///< Transmit Slave Address Register R/W
+#define B_PCH_SMBUS_RW_SEL 0x01
+#define B_PCH_SMBUS_READ 0x01 // RW
+#define B_PCH_SMBUS_WRITE 0x00 // RW
+#define B_PCH_SMBUS_ADDRESS 0xFE
+#define R_PCH_SMBUS_HD0 0x05 ///< Data 0 Register R/W
+#define R_PCH_SMBUS_HD1 0x06 ///< Data 1 Register R/W
+#define R_PCH_SMBUS_HBD 0x07 ///< Host Block Data Register R/W
+#define R_PCH_SMBUS_PEC 0x08 ///< Packet Error Check Data Register R/W
+#define R_PCH_SMBUS_RSA 0x09 ///< Receive Slave Address Register R/W
+#define B_PCH_SMBUS_SLAVE_ADDR 0x7F
+#define R_PCH_SMBUS_SD 0x0A ///< Receive Slave Data Register R/W
+#define R_PCH_SMBUS_AUXS 0x0C ///< Auxiliary Status Register R/WC
+#define B_PCH_SMBUS_CRCE 0x01
+#define B_PCH_SMBUS_STCO 0x02 ///< SMBus TCO Mode
+#define R_PCH_SMBUS_AUXC 0x0D ///< Auxiliary Control Register R/W
+#define B_PCH_SMBUS_AAC 0x01
+#define B_PCH_SMBUS_E32B 0x02
+#define R_PCH_SMBUS_SMLC 0x0E ///< SMLINK Pin Control Register R/W
+#define B_PCH_SMBUS_SMLINK0_CUR_STS 0x01
+#define B_PCH_SMBUS_SMLINK1_CUR_STS 0x02
+#define B_PCH_SMBUS_SMLINK_CLK_CTL 0x04
+#define R_PCH_SMBUS_SMBC 0x0F ///< SMBus Pin Control Register R/W
+#define B_PCH_SMBUS_SMBCLK_CUR_STS 0x01
+#define B_PCH_SMBUS_SMBDATA_CUR_STS 0x02
+#define B_PCH_SMBUS_SMBCLK_CTL 0x04
+#define R_PCH_SMBUS_SSTS 0x10 ///< Slave Status Register R/WC
+#define B_PCH_SMBUS_HOST_NOTIFY_STS 0x01
+#define R_PCH_SMBUS_SCMD 0x11 ///< Slave Command Register R/W
+#define B_PCH_SMBUS_HOST_NOTIFY_INTREN 0x01
+#define B_PCH_SMBUS_HOST_NOTIFY_WKEN 0x02
+#define B_PCH_SMBUS_SMBALERT_DIS 0x04
+#define R_PCH_SMBUS_NDA 0x14 ///< Notify Device Address Register RO
+#define B_PCH_SMBUS_DEVICE_ADDRESS 0xFE
+#define R_PCH_SMBUS_NDLB 0x16 ///< Notify Data Low Byte Register RO
+#define R_PCH_SMBUS_NDHB 0x17 ///< Notify Data High Byte Register RO
+
+//
+// SMBus Private Config Registers
+// (PID:SMB)
+//
+#define R_PCH_PCR_SMBUS_TCOCFG 0x00 ///< TCO Configuration register
+#define B_PCH_PCR_SMBUS_TCOCFG_IE BIT7 ///< TCO IRQ Enable
+#define B_PCH_PCR_SMBUS_TCOCFG_IS (BIT2 | BIT1 | BIT0) ///< TCO IRQ Select
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_9 0x00
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_10 0x01
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_11 0x02
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_20 0x04 ///< only if APIC enabled
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_21 0x05 ///< only if APIC enabled
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_22 0x06 ///< only if APIC enabled
+#define V_PCH_PCR_SMBUS_TCOCFG_IRQ_23 0x07 ///< only if APIC enabled
+#define R_PCH_PCR_SMBUS_SMBTM 0x04 ///< SMBus Test Mode
+#define B_PCH_PCR_SMBUS_SMBTM_SMBCT BIT1 ///< SMBus Counter
+#define B_PCH_PCR_SMBUS_SMBTM_SMBDG BIT0 ///< SMBus Deglitch
+#define R_PCH_PCR_SMBUS_SCTM 0x08 ///< Short Counter Test Mode
+#define B_PCH_PCR_SMBUS_SCTM_SSU BIT31 ///< Simulation Speed-Up
+#define R_PCH_PCR_SMBUS_GC 0x0C ///< General Control
+#define B_PCH_PCR_SMBUS_GC_FD BIT0 ///< Function Disable
+#define B_PCH_PCR_SMBUS_GC_NR BIT1 ///< No Reboot
+#define B_PCH_PCR_SMBUS_GC_SMBSCGE BIT2 ///< SMB Static Clock Gating Enable
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSpi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSpi.h
new file mode 100644
index 0000000000..f43c676797
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsSpi.h
@@ -0,0 +1,309 @@
+/** @file
+ Register names for PCH SPI device.
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_SPI_H_
+#define _PCH_REGS_SPI_H_
+
+//
+// SPI Registers (D31:F5)
+//
+
+#define PCI_DEVICE_NUMBER_PCH_SPI 31
+#define PCI_FUNCTION_NUMBER_PCH_SPI 5
+
+#define R_PCH_SPI_BAR0 0x10
+#define B_PCH_SPI_BAR0_MASK 0x0FFF
+
+#define R_PCH_SPI_BDE 0xD8
+#define B_PCH_SPI_BDE_F8 0x8000
+#define B_PCH_SPI_BDE_F0 0x4000
+#define B_PCH_SPI_BDE_E8 0x2000
+#define B_PCH_SPI_BDE_E0 0x1000
+#define B_PCH_SPI_BDE_D8 0x0800
+#define B_PCH_SPI_BDE_D0 0x0400
+#define B_PCH_SPI_BDE_C8 0x0200
+#define B_PCH_SPI_BDE_C0 0x0100
+#define B_PCH_SPI_BDE_LEG_F 0x0080
+#define B_PCH_SPI_BDE_LEG_E 0x0040
+#define B_PCH_SPI_BDE_70 0x0008
+#define B_PCH_SPI_BDE_60 0x0004
+#define B_PCH_SPI_BDE_50 0x0002
+#define B_PCH_SPI_BDE_40 0x0001
+
+#define R_PCH_SPI_BC 0xDC
+#define S_PCH_SPI_BC 4
+#define N_PCH_SPI_BC_ASE_BWP 11
+#define B_PCH_SPI_BC_ASE_BWP BIT11
+#define N_PCH_SPI_BC_ASYNC_SS 10
+#define B_PCH_SPI_BC_ASYNC_SS BIT10
+#define B_PCH_SPI_BC_OSFH BIT9 ///< OS Function Hide
+#define N_PCH_SPI_BC_SYNC_SS 8
+#define B_PCH_SPI_BC_SYNC_SS BIT8
+#define B_PCH_SPI_BC_BILD BIT7
+#define B_PCH_SPI_BC_BBS BIT6 ///< Boot BIOS strap
+#define N_PCH_SPI_BC_BBS 6
+#define V_PCH_SPI_BC_BBS_SPI 0 ///< Boot BIOS strapped to SPI
+#define V_PCH_SPI_BC_BBS_LPC 1 ///< Boot BIOS strapped to LPC
+#define B_PCH_SPI_BC_EISS BIT5 ///< Enable InSMM.STS
+#define B_PCH_SPI_BC_TSS BIT4
+#define B_PCH_SPI_BC_SRC (BIT3 | BIT2)
+#define N_PCH_SPI_BC_SRC 2
+#define V_PCH_SPI_BC_SRC_PREF_EN_CACHE_EN 0x02 ///< Prefetching and Caching enabled
+#define V_PCH_SPI_BC_SRC_PREF_DIS_CACHE_DIS 0x01 ///< No prefetching and no caching
+#define V_PCH_SPI_BC_SRC_PREF_DIS_CACHE_EN 0x00 ///< No prefetching, but caching enabled
+#define B_PCH_SPI_BC_LE BIT1 ///< Lock Enable
+#define N_PCH_SPI_BC_BLE 1
+#define B_PCH_SPI_BC_WPD BIT0 ///< Write Protect Disable
+
+//
+// BIOS Flash Program Registers (based on SPI_BAR0)
+//
+#define R_PCH_SPI_BFPR 0x00 ///< BIOS Flash Primary Region Register(32bits), which is RO and contains the same value from FREG1
+#define B_PCH_SPI_BFPR_PRL 0x7FFF0000 ///< BIOS Flash Primary Region Limit mask
+#define N_PCH_SPI_BFPR_PRL 16 ///< BIOS Flash Primary Region Limit bit position
+#define B_PCH_SPI_BFPR_PRB 0x00007FFF ///< BIOS Flash Primary Region Base mask
+#define N_PCH_SPI_BFPR_PRB 0 ///< BIOS Flash Primary Region Base bit position
+#define R_PCH_SPI_HSFSC 0x04 ///< Hardware Sequencing Flash Status and Control Register(32bits)
+#define B_PCH_SPI_HSFSC_FSMIE BIT31 ///< Flash SPI SMI# Enable
+#define B_PCH_SPI_HSFSC_FDBC_MASK 0x3F000000 ///< Flash Data Byte Count ( <= 64), Count = (Value in this field) + 1.
+#define N_PCH_SPI_HSFSC_FDBC 24
+#define B_PCH_SPI_HSFSC_CYCLE_MASK 0x001E0000 ///< Flash Cycle.
+#define N_PCH_SPI_HSFSC_CYCLE 17
+#define V_PCH_SPI_HSFSC_CYCLE_READ 0 ///< Flash Cycle Read
+#define V_PCH_SPI_HSFSC_CYCLE_WRITE 2 ///< Flash Cycle Write
+#define V_PCH_SPI_HSFSC_CYCLE_4K_ERASE 3 ///< Flash Cycle 4K Block Erase
+#define V_PCH_SPI_HSFSC_CYCLE_64K_ERASE 4 ///< Flash Cycle 64K Sector Erase
+#define V_PCH_SPI_HSFSC_CYCLE_READ_SFDP 5 ///< Flash Cycle Read SFDP
+#define V_PCH_SPI_HSFSC_CYCLE_READ_JEDEC_ID 6 ///< Flash Cycle Read JEDEC ID
+#define V_PCH_SPI_HSFSC_CYCLE_WRITE_STATUS 7 ///< Flash Cycle Write Status
+#define V_PCH_SPI_HSFSC_CYCLE_READ_STATUS 8 ///< Flash Cycle Read Status
+#define B_PCH_SPI_HSFSC_CYCLE_FGO BIT16 ///< Flash Cycle Go.
+#define B_PCH_SPI_HSFSC_FLOCKDN BIT15 ///< Flash Configuration Lock-Down
+#define B_PCH_SPI_HSFSC_FDV BIT14 ///< Flash Descriptor Valid, once valid software can use hareware sequencing regs
+#define B_PCH_SPI_HSFSC_FDOPSS BIT13 ///< Flash Descriptor Override Pin-Strap Status
+#define B_PCH_SPI_HSFSC_PRR34_LOCKDN BIT12 ///< PRR3 PRR4 Lock-Down
+#define B_PCH_SPI_HSFSC_SAF_CE BIT8 ///< SAF ctype error
+#define B_PCH_SPI_HSFSC_SAF_MODE_ACTIVE BIT7 ///< Indicates flash is attached either directly to the PCH via the SPI bus or EC/BMC
+#define B_PCH_SPI_HSFSC_SAF_LE BIT6 ///< SAF link error
+#define B_PCH_SPI_HSFSC_SCIP BIT5 ///< SPI cycle in progress
+#define B_PCH_SPI_HSFSC_SAF_DLE BIT4 ///< SAF Data length error
+#define B_PCH_SPI_HSFSC_SAF_ERROR BIT3 ///< SAF Error
+#define B_PCH_SPI_HSFSC_AEL BIT2 ///< Access Error Log
+#define B_PCH_SPI_HSFSC_FCERR BIT1 ///< Flash Cycle Error
+#define B_PCH_SPI_HSFSC_FDONE BIT0 ///< Flash Cycle Done
+#define R_PCH_SPI_FADDR 0x08 ///< SPI Flash Address
+#define B_PCH_SPI_FADDR_MASK 0x07FFFFFF ///< SPI Flash Address Mask (0~26bit)
+#define R_PCH_SPI_DLOCK 0x0C ///< Discrete Lock Bits
+#define B_PCH_SPI_DLOCK_PR0LOCKDN BIT8 ///< PR0LOCKDN
+#define R_PCH_SPI_FDATA00 0x10 ///< SPI Data 00 (32 bits)
+#define R_PCH_SPI_FDATA01 0x14 ///< SPI Data 01
+#define R_PCH_SPI_FDATA02 0x18 ///< SPI Data 02
+#define R_PCH_SPI_FDATA03 0x1C ///< SPI Data 03
+#define R_PCH_SPI_FDATA04 0x20 ///< SPI Data 04
+#define R_PCH_SPI_FDATA05 0x24 ///< SPI Data 05
+#define R_PCH_SPI_FDATA06 0x28 ///< SPI Data 06
+#define R_PCH_SPI_FDATA07 0x2C ///< SPI Data 07
+#define R_PCH_SPI_FDATA08 0x30 ///< SPI Data 08
+#define R_PCH_SPI_FDATA09 0x34 ///< SPI Data 09
+#define R_PCH_SPI_FDATA10 0x38 ///< SPI Data 10
+#define R_PCH_SPI_FDATA11 0x3C ///< SPI Data 11
+#define R_PCH_SPI_FDATA12 0x40 ///< SPI Data 12
+#define R_PCH_SPI_FDATA13 0x44 ///< SPI Data 13
+#define R_PCH_SPI_FDATA14 0x48 ///< SPI Data 14
+#define R_PCH_SPI_FDATA15 0x4C ///< SPI Data 15
+#define R_PCH_SPI_FRAP 0x50 ///< Flash Region Access Permisions Register
+#define B_PCH_SPI_FRAP_BRWA_MASK 0x0000FF00 ///< BIOS Region Write Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: ME; 3: GbE; 4: PlatformData
+#define N_PCH_SPI_FRAP_BRWA 8 ///< BIOS Region Write Access bit position
+#define B_PCH_SPI_FRAP_BRRA_MASK 0x000000FF ///< BIOS Region Read Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: ME; 3: GbE; 4: PlatformData
+#define B_PCH_SPI_FRAP_BMRAG_MASK 0x00FF0000 ///< BIOS Master Read Access Grant
+#define B_PCH_SPI_FRAP_BMWAG_MASK 0xFF000000 ///< BIOS Master Write Access Grant
+#define R_PCH_SPI_FREG0_FLASHD 0x54 ///< Flash Region 0(Flash Descriptor)(32bits)
+#define R_PCH_SPI_FREG1_BIOS 0x58 ///< Flash Region 1(BIOS)(32bits)
+#define R_PCH_SPI_FREG2_ME 0x5C ///< Flash Region 2(ME)(32bits)
+#define R_PCH_SPI_FREG3_GBE 0x60 ///< Flash Region 3(GbE)(32bits)
+#define R_PCH_SPI_FREG4_PLATFORM_DATA 0x64 ///< Flash Region 4(Platform Data)(32bits)
+#define R_PCH_SPI_FREG5_DER 0x68 ///< Flash Region 5(Device Expansion Region)(32bits)
+#define S_PCH_SPI_FREGX 4 ///< Size of Flash Region register
+#define B_PCH_SPI_FREGX_LIMIT_MASK 0x7FFF0000 ///< Flash Region Limit [30:16] represents [26:12], [11:0] are assumed to be FFFh
+#define N_PCH_SPI_FREGX_LIMIT 16 ///< Region limit bit position
+#define N_PCH_SPI_FREGX_LIMIT_REPR 12 ///< Region limit bit represents position
+#define B_PCH_SPI_FREGX_BASE_MASK 0x00007FFF ///< Flash Region Base, [14:0] represents [26:12]
+#define N_PCH_SPI_FREGX_BASE 0 ///< Region base bit position
+#define N_PCH_SPI_FREGX_BASE_REPR 12 ///< Region base bit represents position
+#define R_PCH_SPI_PR0 0x84 ///< Protected Region 0 Register
+#define R_PCH_SPI_PR1 0x88 ///< Protected Region 1 Register
+#define R_PCH_SPI_PR2 0x8C ///< Protected Region 2 Register
+#define R_PCH_SPI_PR3 0x90 ///< Protected Region 3 Register
+#define R_PCH_SPI_PR4 0x94 ///< Protected Region 4 Register
+#define S_PCH_SPI_PRX 4 ///< Protected Region X Register size
+#define B_PCH_SPI_PRX_WPE BIT31 ///< Write Protection Enable
+#define B_PCH_SPI_PRX_PRL_MASK 0x7FFF0000 ///< Protected Range Limit Mask, [30:16] here represents upper limit of address [26:12]
+#define N_PCH_SPI_PRX_PRL 16 ///< Protected Range Limit bit position
+#define B_PCH_SPI_PRX_RPE BIT15 ///< Read Protection Enable
+#define B_PCH_SPI_PRX_PRB_MASK 0x00007FFF ///< Protected Range Base Mask, [14:0] here represents base limit of address [26:12]
+#define N_PCH_SPI_PRX_PRB 0 ///< Protected Range Base bit position
+#define R_PCH_SPI_SFRAP 0xB0 ///< Secondary Flash Regions Access Permisions Register
+#define R_PCH_SPI_FDOC 0xB4 ///< Flash Descriptor Observability Control Register(32 bits)
+#define B_PCH_SPI_FDOC_FDSS_MASK (BIT14 | BIT13 | BIT12) ///< Flash Descritor Section Select
+#define V_PCH_SPI_FDOC_FDSS_FSDM 0x0000 ///< Flash Signature and Descriptor Map
+#define V_PCH_SPI_FDOC_FDSS_COMP 0x1000 ///< Component
+#define V_PCH_SPI_FDOC_FDSS_REGN 0x2000 ///< Region
+#define V_PCH_SPI_FDOC_FDSS_MSTR 0x3000 ///< Master
+#define V_PCH_SPI_FDOC_FDSS_PCHS 0x4000 ///< PCH soft straps
+#define V_PCH_SPI_FDOC_FDSS_SFDP 0x5000 ///< SFDP Parameter Table
+#define B_PCH_SPI_FDOC_FDSI_MASK 0x0FFC ///< Flash Descriptor Section Index
+#define R_PCH_SPI_FDOD 0xB8 ///< Flash Descriptor Observability Data Register(32 bits)
+#define R_PCH_SPI_SFDP0_VSCC0 0xC4 ///< Vendor Specific Component Capabilities Register(32 bits)
+#define B_PCH_SPI_SFDPX_VSCCX_CPPTV BIT31 ///< Component Property Parameter Table Valid
+#define B_PCH_SPI_SFDP0_VSCC0_VCL BIT30 ///< Vendor Component Lock
+#define B_PCH_SPI_SFDPX_VSCCX_EO_64K BIT29 ///< 64k Erase valid (EO_64k_valid)
+#define B_PCH_SPI_SFDPX_VSCCX_EO_4K BIT28 ///< 4k Erase valid (EO_4k_valid)
+#define B_PCH_SPI_SFDPX_VSCCX_RPMC BIT27 ///< RPMC Supported
+#define B_PCH_SPI_SFDPX_VSCCX_DPD BIT26 ///< Deep Powerdown Supported
+#define B_PCH_SPI_SFDPX_VSCCX_SUSRES BIT25 ///< Suspend/Resume Supported
+#define B_PCH_SPI_SFDPX_VSCCX_SOFTRES BIT24 ///< Soft Reset Supported
+#define B_PCH_SPI_SFDPX_VSCCX_64k_EO_MASK 0x00FF0000 ///< 64k Erase Opcode (EO_64k)
+#define B_PCH_SPI_SFDPX_VSCCX_4k_EO_MASK 0x0000FF00 ///< 4k Erase Opcode (EO_4k)
+#define B_PCH_SPI_SFDPX_VSCCX_QER (BIT7 | BIT6 | BIT5) ///< Quad Enable Requirements
+#define B_PCH_SPI_SFDPX_VSCCX_WEWS BIT4 ///< Write Enable on Write Status
+#define B_PCH_SPI_SFDPX_VSCCX_WSR BIT3 ///< Write Status Required
+#define B_PCH_SPI_SFDPX_VSCCX_WG_64B BIT2 ///< Write Granularity, 0: 1 Byte; 1: 64 Bytes
+#define R_PCH_SPI_SFDP1_VSCC1 0xC8 ///< Vendor Specific Component Capabilities Register(32 bits)
+#define R_PCH_SPI_PINTX 0xCC ///< Parameter Table Index
+#define N_PCH_SPI_PINTX_SPT 14
+#define V_PCH_SPI_PINTX_SPT_CPT0 0x0 ///< Component 0 Property Parameter Table
+#define V_PCH_SPI_PINTX_SPT_CPT1 0x1 ///< Component 1 Property Parameter Table
+#define N_PCH_SPI_PINTX_HORD 12
+#define V_PCH_SPI_PINTX_HORD_SFDP 0x0 ///< SFDP Header
+#define V_PCH_SPI_PINTX_HORD_PT 0x1 ///< Parameter Table Header
+#define V_PCH_SPI_PINTX_HORD_DATA 0x2 ///< Data
+#define R_PCH_SPI_PTDATA 0xD0 ///< Parameter Table Data
+#define R_PCH_SPI_SBRS 0xD4 ///< SPI Bus Requester Status
+#define R_PCH_SPI_SSML 0xF0 ///< Set Strap Msg Lock
+#define B_PCH_SPI_SSML_SSL BIT0 ///< Set_Strap Lock
+#define R_PCH_SPI_SSMC 0xF4 ///< Set Strap Msg Control
+#define B_PCH_SPI_SSMC_SSMS BIT0 ///< Set_Strap Mux Select
+#define R_PCH_SPI_SSMD 0xF8 ///< Set Strap Msg Data
+//
+// @todo Follow up with EDS owner if it should be 3FFF or FFFF.
+//
+#define B_PCH_SPI_SRD_SSD 0x0000FFFF ///< Set_Strap Data
+//
+// Flash Descriptor Base Address Region (FDBAR) from Flash Region 0
+//
+#define R_PCH_SPI_FDBAR_FLVALSIG 0x00 ///< Flash Valid Signature
+#define V_PCH_SPI_FDBAR_FLVALSIG 0x0FF0A55A
+#define R_PCH_SPI_FDBAR_FLASH_MAP0 0x04
+#define B_PCH_SPI_FDBAR_FCBA 0x000000FF ///< Flash Component Base Address
+#define B_PCH_SPI_FDBAR_NC 0x00000300 ///< Number Of Components
+#define N_PCH_SPI_FDBAR_NC 8 ///< Number Of Components
+#define V_PCH_SPI_FDBAR_NC_1 0x00000000
+#define V_PCH_SPI_FDBAR_NC_2 0x00000100
+#define B_PCH_SPI_FDBAR_FRBA 0x00FF0000 ///< Flash Region Base Address
+#define B_PCH_SPI_FDBAR_NR 0x07000000 ///< Number Of Regions
+#define R_PCH_SPI_FDBAR_FLASH_MAP1 0x08
+#define B_PCH_SPI_FDBAR_FMBA 0x000000FF ///< Flash Master Base Address
+#define B_PCH_SPI_FDBAR_NM 0x00000700 ///< Number Of Masters
+#define B_PCH_SPI_FDBAR_FPSBA 0x00FF0000 ///< PCH Strap Base Address, [23:16] represents [11:4]
+#define N_PCH_SPI_FDBAR_FPSBA 16 ///< PCH Strap base Address bit position
+#define N_PCH_SPI_FDBAR_FPSBA_REPR 4 ///< PCH Strap base Address bit represents position
+#define B_PCH_SPI_FDBAR_PCHSL 0xFF000000 ///< PCH Strap Length, [31:24] represents number of Dwords
+#define N_PCH_SPI_FDBAR_PCHSL 24 ///< PCH Strap Length bit position
+#define R_PCH_SPI_FDBAR_FLASH_MAP2 0x0C
+#define B_PCH_SPI_FDBAR_FCPUSBA 0x000000FF ///< CPU Strap Base Address, [7:0] represents [11:4]
+#define N_PCH_SPI_FDBAR_FCPUSBA 0 ///< CPU Strap Base Address bit position
+#define N_PCH_SPI_FDBAR_FCPUSBA_REPR 4 ///< CPU Strap Base Address bit represents position
+#define B_PCH_SPI_FDBAR_CPUSL 0x0000FF00 ///< CPU Strap Length, [15:8] represents number of Dwords
+#define N_PCH_SPI_FDBAR_CPUSL 8 ///< CPU Strap Length bit position
+//
+// Flash Component Base Address (FCBA) from Flash Region 0
+//
+#define R_PCH_SPI_FCBA_FLCOMP 0x00 ///< Flash Components Register
+#define B_PCH_SPI_FLCOMP_RIDS_FREQ (BIT29 | BIT28 | BIT27) ///< Read ID and Read Status Clock Frequency
+#define B_PCH_SPI_FLCOMP_WE_FREQ (BIT26 | BIT25 | BIT24) ///< Write and Erase Clock Frequency
+#define B_PCH_SPI_FLCOMP_FRCF_FREQ (BIT23 | BIT22 | BIT21) ///< Fast Read Clock Frequency
+#define B_PCH_SPI_FLCOMP_FR_SUP BIT20 ///< Fast Read Support.
+#define B_PCH_SPI_FLCOMP_RC_FREQ (BIT19 | BIT18 | BIT17) ///< Read Clock Frequency.
+#define V_PCH_SPI_FLCOMP_FREQ_48MHZ 0x02
+#define V_PCH_SPI_FLCOMP_FREQ_30MHZ 0x04
+#define V_PCH_SPI_FLCOMP_FREQ_17MHZ 0x06
+#define B_PCH_SPI_FLCOMP_COMP1_MASK 0xF0 ///< Flash Component 1 Size MASK
+#define N_PCH_SPI_FLCOMP_COMP1 4 ///< Flash Component 1 Size bit position
+#define B_PCH_SPI_FLCOMP_COMP0_MASK 0x0F ///< Flash Component 0 Size MASK
+#define V_PCH_SPI_FLCOMP_COMP_512KB 0x80000
+//
+// Descriptor Upper Map Section from Flash Region 0
+//
+#define R_PCH_SPI_FLASH_UMAP1 0xEFC ///< Flash Upper Map 1
+#define B_PCH_SPI_FLASH_UMAP1_VTBA 0x000000FF ///< VSCC Table Base Address
+#define B_PCH_SPI_FLASH_UMAP1_VTL 0x0000FF00 ///< VSCC Table Length
+
+#define R_PCH_SPI_VTBA_JID0 0x00 ///< JEDEC-ID 0 Register
+#define S_PCH_SPI_VTBA_JID0 0x04
+#define B_PCH_SPI_VTBA_JID0_VID 0x000000FF
+#define B_PCH_SPI_VTBA_JID0_DID0 0x0000FF00
+#define B_PCH_SPI_VTBA_JID0_DID1 0x00FF0000
+#define N_PCH_SPI_VTBA_JID0_DID0 0x08
+#define N_PCH_SPI_VTBA_JID0_DID1 0x10
+#define R_PCH_SPI_VTBA_VSCC0 0x04
+#define S_PCH_SPI_VTBA_VSCC0 0x04
+
+
+//
+// SPI Private Configuration Space Registers
+//
+#define R_PCH_PCR_SPI_CLK_CTL 0xC004
+#define R_PCH_PCR_SPI_PWR_CTL 0xC008
+#define R_PCH_PCR_SPI_ESPI_SOFTSTRAPS 0xC210
+#define B_PCH_PCR_SPI_ESPI_SOFTSTRAPS_SLAVE BIT12
+
+//
+// MMP0
+//
+#define R_PCH_SPI_STRP_MMP0 0xC4 ///< MMP0 Soft strap offset
+#define B_PCH_SPI_STRP_MMP0 0x10 ///< MMP0 Soft strap bit
+
+
+#define R_PCH_SPI_STRP_SFDP 0xF0 ///< PCH Soft Strap SFDP
+#define B_PCH_SPI_STRP_SFDP_QIORE BIT3 ///< Quad IO Read Enable
+#define B_PCH_SPI_STRP_SFDP_QORE BIT2 ///< Quad Output Read Enable
+#define B_PCH_SPI_STRP_SFDP_DIORE BIT1 ///< Dual IO Read Enable
+#define B_PCH_SPI_STRP_SFDP_DORE BIT0 ///< Dual Output Read Enable
+
+//
+// Descriptor Record 0
+//
+#define R_PCH_SPI_STRP_DSCR_0 0x00 ///< PCH Soft Strap 0
+#define B_PCH_SPI_STRP_DSCR_0_PTT_SUPP BIT22 ///< PTT Supported
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsThermal.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsThermal.h
new file mode 100644
index 0000000000..fe43d210ab
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsThermal.h
@@ -0,0 +1,107 @@
+/** @file
+ Register names for PCH Thermal Device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_THERMAL_H_
+#define _PCH_REGS_THERMAL_H_
+
+//
+// Thermal Device Registers (D20:2)
+//
+#define PCI_DEVICE_NUMBER_PCH_THERMAL 20
+#define PCI_FUNCTION_NUMBER_PCH_THERMAL 2
+
+#define R_PCH_THERMAL_TBAR 0x10
+#define V_PCH_THERMAL_TBAR_SIZE (4 * 1024)
+#define N_PCH_THREMAL_TBAR_ALIGNMENT 12
+#define B_PCH_THERMAL_TBAR_MASK 0xFFFFF000
+#define R_PCH_THERMAL_TBARH 0x14
+#define R_PCH_THERMAL_TBARB 0x40
+#define V_PCH_THERMAL_TBARB_SIZE (4 * 1024)
+#define N_PCH_THREMAL_TBARB_ALIGNMENT 12
+#define B_PCH_THERMAL_SPTYPEN BIT0
+#define R_PCH_THERMAL_TBARBH 0x44
+#define B_PCH_THERMAL_TBARB_MASK 0xFFFFF000
+
+//
+// Thermal TBAR MMIO registers
+//
+#define R_PCH_TBAR_TSC 0x04
+#define B_PCH_TBAR_TSC_PLD BIT7
+#define B_PCH_TBAR_TSC_CPDE BIT0
+#define R_PCH_TBAR_TSS 0x06
+#define R_PCH_TBAR_TSEL 0x08
+#define B_PCH_TBAR_TSEL_PLD BIT7
+#define B_PCH_TBAR_TSEL_ETS BIT0
+#define R_PCH_TBAR_TSREL 0x0A
+#define R_PCH_TBAR_TSMIC 0x0C
+#define B_PCH_TBAR_TSMIC_PLD BIT7
+#define B_PCH_TBAR_TSMIC_SMIE BIT0
+#define R_PCH_TBAR_CTT 0x10
+#define R_PCH_TBAR_TAHV 0x14
+#define R_PCH_TBAR_TALV 0x18
+#define R_PCH_TBAR_TSPM 0x1C
+#define B_PCH_TBAR_TSPM_LTT (BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+#define V_PCH_TBAR_TSPM_LTT 0x0C8
+#define B_PCH_TBAR_TSPM_MAXTSST (BIT11 | BIT10 | BIT9)
+#define V_PCH_TBAR_TSPM_MAXTSST (0x4 << 9)
+#define B_PCH_TBAR_TSPM_MINTSST BIT12
+#define B_PCH_TBAR_TSPM_DTSSIC0 BIT13
+#define B_PCH_TBAR_TSPM_DTSSS0EN BIT14
+#define B_PCH_TBAR_TSPM_TSPMLOCK BIT15
+#define R_PCH_TBAR_TL 0x40
+#define B_PCH_TBAR_TL_LOCK BIT31
+#define B_PCH_TBAR_TL_TTEN BIT29
+#define R_PCH_TBAR_TL2 0x50
+#define R_PCH_TBAR_TL2_LOCK BIT15
+#define R_PCH_TBAR_TL2_PMCTEN BIT14
+#define R_PCH_TBAR_PHL 0x60
+#define B_PCH_TBAR_PHLE BIT15
+#define R_PCH_TBAR_PHLC 0x62
+#define B_PCH_TBAR_PHLC_LOCK BIT0
+#define R_PCH_TBAR_TAS 0x80
+#define R_PCH_TBAR_TSPIEN 0x82
+#define R_PCH_TBAR_TSGPEN 0x84
+#define B_PCH_TBAR_TL2_PMCTEN BIT14
+#define R_PCH_TBAR_A4 0xA4
+#define R_PCH_TBAR_C0 0xC0
+#define R_PCH_TBAR_C4 0xC4
+#define R_PCH_TBAR_C8 0xC8
+#define R_PCH_TBAR_CC 0xCC
+#define R_PCH_TBAR_D0 0xD0
+#define R_PCH_TBAR_E0 0xE0
+#define R_PCH_TBAR_E4 0xE4
+#define R_PCH_TBAR_E8 0xE8
+#define R_PCH_TBAR_TCFD 0xF0 ///< Thermal controller function disable
+#define B_PCH_TBAR_TCFD_TCD BIT0 ///< Thermal controller disable
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsTraceHub.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsTraceHub.h
new file mode 100644
index 0000000000..513b022f08
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsTraceHub.h
@@ -0,0 +1,140 @@
+/** @file
+ Register names for PCH TraceHub device
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_TRACE_HUB_H_
+#define _PCH_REGS_TRACE_HUB_H_
+
+//
+// TraceHub Registers (D31:F7)
+//
+#define PCI_DEVICE_NUMBER_PCH_TRACE_HUB 31
+#define PCI_FUNCTION_NUMBER_PCH_TRACE_HUB 7
+
+#define R_PCH_TRACE_HUB_CSR_MTB_LBAR 0x10
+#define B_PCH_TRACE_HUB_CSR_MTB_RBAL 0xFFF00000
+#define R_PCH_TRACE_HUB_CSR_MTB_UBAR 0x14
+#define B_PCH_TRACE_HUB_CSR_MTB_RBAU 0xFFFFFFFF
+#define R_PCH_TRACE_HUB_SW_LBAR 0x18
+#define B_PCH_TRACE_HUB_SW_RBAL 0xFFE00000
+#define R_PCH_TRACE_HUB_SW_UBAR 0x1C
+#define B_PCH_TRACE_HUB_SW_RBAU 0xFFFFFFFF
+#define R_PCH_TRACE_HUB_RTIT_LBAR 0x20
+#define B_PCH_TRACE_HUB_RTIT_RBAL 0xFFFFFF00
+#define R_PCH_TRACE_HUB_RTIT_UBAR 0x24
+#define B_PCH_TRACE_HUB_RTIT_RBAU 0xFFFFFFFF
+#define R_PCH_TRACE_HUB_MSICID 0x40
+#define R_PCH_TRACE_HUB_MSINCP 0x41
+#define R_PCH_TRACE_HUB_MSIMC 0x42
+#define R_PCH_TRACE_HUB_MSILMA 0x44
+#define R_PCH_TRACE_HUB_MSIUMA 0x48
+#define R_PCH_TRACE_HUB_MSIMD 0x4C
+#define B_PCH_TRACE_HUB_FW_RBAL 0xFFFC0000
+#define B_PCH_TRACE_HUB_FW_RBAU 0xFFFFFFFF
+#define R_PCH_TRACE_HUB_DSC 0x80
+#define B_PCH_TRACE_HUB_BYP BIT0 //< TraceHub Bypass
+#define R_PCH_TRACE_HUB_DSS 0x81
+#define R_PCH_TRACE_HUB_ISTOT 0x84
+#define R_PCH_TRACE_HUB_ICTOT 0x88
+#define R_PCH_TRACE_HUB_IPAD 0x8C
+#define R_PCH_TRACE_HUB_DSD 0x90
+
+//
+// Offsets from CSR_MTB_BAR
+//
+#define R_PCH_TRACE_HUB_MTB_GTHOPT0 0x00
+#define B_PCH_TRACE_HUB_MTB_GTHOPT0_P0FLUSH BIT7
+#define B_PCH_TRACE_HUB_MTB_GTHOPT0_P1FLUSH BIT15
+#define V_PCH_TRACE_HUB_MTB_SWDEST_PTI 0x0A
+#define V_PCH_TRACE_HUB_MTB_SWDEST_MEMEXI 0x08
+#define V_PCH_TRACE_HUB_MTB_SWDEST_DISABLE 0x00
+#define R_PCH_TRACE_HUB_MTB_SWDEST_1 0x0C
+#define B_PCH_TRACE_HUB_MTB_SWDEST_CSE_1 0x0000000F
+#define B_PCH_TRACE_HUB_MTB_SWDEST_CSE_2 0x000000F0
+#define B_PCH_TRACE_HUB_MTB_SWDEST_CSE_3 0x00000F00
+#define B_PCH_TRACE_HUB_MTB_SWDEST_ISH_1 0x0000F000
+#define B_PCH_TRACE_HUB_MTB_SWDEST_ISH_2 0x000F0000
+#define B_PCH_TRACE_HUB_MTB_SWDEST_ISH_3 0x00F00000
+#define B_PCH_TRACE_HUB_MTB_SWDEST_AUDIO 0x0F000000
+#define B_PCH_TRACE_HUB_MTB_SWDEST_PMC 0xF0000000
+#define R_PCH_TRACE_HUB_MTB_SWDEST_2 0x10
+#define B_PCH_TRACE_HUB_MTB_SWDEST_FTH 0x0000000F
+#define R_PCH_TRACE_HUB_MTB_SWDEST_3 0x14
+#define B_PCH_TRACE_HUB_MTB_SWDEST_MAESTRO 0x00000F00
+#define B_PCH_TRACE_HUB_MTB_SWDEST_SKYCAM 0x0F000000
+#define B_PCH_TRACE_HUB_MTB_SWDEST_AET 0xF0000000
+#define R_PCH_TRACE_HUB_MTB_SWDEST_4 0x18
+#define R_PCH_TRACE_HUB_MTB_MSC0CTL 0xA0100
+#define R_PCH_TRACE_HUB_MTB_MSC1CTL 0xA0200
+#define V_PCH_TRACE_HUB_MTB_MSCNMODE_DCI 0x2
+#define V_PCH_TRACE_HUB_MTB_MSCNMODE_DEBUG 0x3
+#define B_PCH_TRACE_HUB_MTB_MSCNLEN (BIT10 | BIT9 | BIT8)
+#define B_PCH_TRACE_HUB_MTB_MSCNMODE (BIT5 | BIT4)
+#define N_PCH_TRACE_HUB_MTB_MSCNMODE 0x4
+#define B_PCH_TRACE_HUB_MTB_MSCN_RD_HDR_OVRD BIT2
+#define B_PCH_TRACE_HUB_MTB_WRAPENN BIT1
+#define B_PCH_TRACE_HUB_MTB_MSCNEN BIT0
+#define R_PCH_TRACE_HUB_MTB_GTHSTAT 0xD4
+#define R_PCH_TRACE_HUB_MTB_SCR2 0xD8
+#define B_PCH_TRACE_HUB_MTB_SCR2_FCD BIT0
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF2 BIT2
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF3 BIT3
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF4 BIT4
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF5 BIT5
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF6 BIT6
+#define B_PCH_TRACE_HUB_MTB_SCR2_FSEOFF7 BIT7
+#define R_PCH_TRACE_HUB_MTB_MSC0BAR 0xA0108
+#define R_PCH_TRACE_HUB_MTB_MSC0SIZE 0xA010C
+#define R_PCH_TRACE_HUB_MTB_MSC1BAR 0xA0208
+#define R_PCH_TRACE_HUB_MTB_MSC1SIZE 0xA020C
+#define R_PCH_TRACE_HUB_MTB_STREAMCFG1 0xA1000
+#define B_PCH_TRACE_HUB_MTB_STREAMCFG1_ENABLE BIT28
+#define R_PCH_TRACE_HUB_MTB_PTI_CTL 0x1C00
+#define B_PCH_TRACE_HUB_MTB_PTIMODESEL 0xF0
+#define B_PCH_TRACE_HUB_MTB_PTICLKDIV (BIT17 | BIT16)
+#define B_PCH_TRACE_HUB_MTB_PATGENMOD (BIT22 | BIT21 | BIT20)
+#define B_PCH_TRACE_HUB_MTB_PTI_EN BIT0
+#define R_PCH_TRACE_HUB_MTB_SCR 0xC8
+#define R_PCH_TRACE_HUB_MTB_GTH_FREQ 0xCC
+#define V_PCH_TRACE_HUB_MTB_SCR 0x00130000
+#define R_PCH_TRACE_HUB_CSR_MTB_SCRATCHPAD0 0xE0
+#define R_PCH_TRACE_HUB_CSR_MTB_SCRATCHPAD1 0xE4
+#define R_PCH_TRACE_HUB_CSR_MTB_SCRATCHPAD10 0xE40
+#define R_PCH_TRACE_HUB_MTB_CTPGCS 0x1C14
+#define B_PCH_TRACE_HUB_MTB_CTPEN BIT0
+#define V_PCH_TRACE_HUB_MTB_CHLCNT 0x80
+#define V_PCH_TRACE_HUB_MTB_STHMSTR 0x20
+#define R_PCH_TRACE_HUB_CSR_MTB_TSUCTRL 0x2000
+#define B_PCH_TRACE_HUB_CSR_MTB_TSUCTRL_CTCRESYNC BIT0
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsUsb.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsUsb.h
new file mode 100644
index 0000000000..7dfe90815f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Include/Register/PchRegsUsb.h
@@ -0,0 +1,490 @@
+/** @file
+ Register names for PCH USB devices
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_H_", "_PCH_LP_"
+ Registers / bits names without _H_ or _LP_ apply for both H and LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+Copyright (c) 2017, 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 that 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 _PCH_REGS_USB_H_
+#define _PCH_REGS_USB_H_
+
+//
+// USB3 (XHCI) related definitions
+//
+#define PCI_BUS_NUMBER_PCH_XHCI 0
+#define PCI_DEVICE_NUMBER_PCH_XHCI 20
+#define PCI_FUNCTION_NUMBER_PCH_XHCI 0
+
+//
+// XHCI PCI Config Space registers
+//
+#define R_PCH_XHCI_MEM_BASE 0x10
+#define R_PCH_XHCI_MEM_BASE_2 0x14
+#define V_PCH_XHCI_MEM_LENGTH 0x10000
+#define N_PCH_XHCI_MEM_SHIFT 32
+#define N_PCH_XHCI_MEM_ALIGN 16
+#define B_PCH_XHCI_MEM_ALIGN_MASK 0xFFFF
+
+#define R_PCH_XHCI_XHCC1 0x40
+#define B_PCH_XHCI_XHCC1_ACCTRL BIT31
+#define B_PCH_XHCI_XHCC1_RMTASERR BIT24
+#define B_PCH_XHCI_XHCC1_URD BIT23
+#define B_PCH_XHCI_XHCC1_URRE BIT22
+#define B_PCH_XHCI_XHCC1_IIL1E (BIT21 | BIT20 | BIT19)
+#define V_PCH_XHCI_XHCC1_IIL1E_DIS 0
+#define V_PCH_XHCI_XHCC1_IIL1E_32 (BIT19)
+#define V_PCH_XHCI_XHCC1_IIL1E_64 (BIT20)
+#define V_PCH_XHCI_XHCC1_IIL1E_128 (BIT20 | BIT19)
+#define V_PCH_XHCI_XHCC1_IIL1E_256 (BIT21)
+#define V_PCH_XHCI_XHCC1_IIL1E_512 (BIT21 | BIT19)
+#define V_PCH_XHCI_XHCC1_IIL1E_1024 (BIT21 | BIT20)
+#define V_PCH_XHCI_XHCC1_IIL1E_131072 (BIT21 | BIT20 | BIT19)
+#define B_PCH_XHCI_XHCC1_XHCIL1E BIT18
+#define B_PCH_XHCI_XHCC1_D3IL1E BIT17
+#define B_PCH_XHCI_XHCC1_UNPPA (BIT16 | BIT15 | BIT14 | BIT13 | BIT12)
+#define B_PCH_XHCI_XHCC1_SWAXHCI BIT11
+#define B_PCH_XHCI_XHCC1_L23HRAWC (BIT10 | BIT9 | BIT8)
+#define B_PCH_XHCI_XHCC1_UTAGCP (BIT7 | BIT6)
+#define B_PCH_XHCI_XHCC1_UDAGCNP (BIT5 | BIT4)
+#define B_PCH_XHCI_XHCC1_UDAGCCP (BIT3 | BIT2)
+#define B_PCH_XHCI_XHCC1_UDAGC (BIT1 | BIT0)
+
+#define R_PCH_XHCI_XHCC2 0x44
+#define B_PCH_XHCI_XHCC2_OCCFDONE BIT31
+#define B_PCH_XHCI_XHCC2_XHCUPRDROE BIT11
+#define B_PCH_XHCI_XHCC2_IOSFSRAD BIT10
+#define B_PCH_XHCI_XHCC2_SWACXIHB (BIT9 | BIT8)
+#define B_PCH_XHCI_XHCC2_SWADMIL1IHB (BIT7 | BIT6)
+#define B_PCH_XHCI_XHCC2_L1FP2CGWC (BIT5 | BIT4 | BIT3)
+#define B_PCH_XHCI_XHCC2_RDREQSZCTRL (BIT2 | BIT1 | BIT0)
+
+#define R_PCH_XHCI_XHCLKGTEN 0x50
+#define B_PCH_XHCI_XHCLKGTEN_SSLSE BIT26
+#define B_PCH_XHCI_XHCLKGTEN_USB2PLLSE BIT25
+#define B_PCH_XHCI_XHCLKGTEN_IOSFSTCGE BIT24
+#define B_PCH_XHCI_XHCLKGTEN_HSTCGE (BIT23 | BIT22 | BIT21 | BIT20)
+#define B_PCH_XHCI_XHCLKGTEN_SSTCGE (BIT19 | BIT18 | BIT17 | BIT16)
+#define B_PCH_XHCI_XHCLKGTEN_XHCIGEU3S BIT15
+#define B_PCH_XHCI_XHCLKGTEN_XHCFTCLKSE BIT14
+#define B_PCH_XHCI_XHCLKGTEN_XHCBBTCGIPISO BIT13
+#define B_PCH_XHCI_XHCLKGTEN_XHCHSTCGU2NRWE BIT12
+#define B_PCH_XHCI_XHCLKGTEN_XHCUSB2PLLSDLE (BIT11 | BIT10)
+#define B_PCH_XHCI_XHCLKGTEN_HSPLLSUE (BIT9 | BIT8)
+#define B_PCH_XHCI_XHCLKGTEN_SSPLLSUE (BIT7 | BIT6 | BIT5)
+#define B_PCH_XHCI_XHCLKGTEN_XHCBLCGE BIT4
+#define B_PCH_XHCI_XHCLKGTEN_HSLTCGE BIT3
+#define B_PCH_XHCI_XHCLKGTEN_SSLTCGE BIT2
+#define B_PCH_XHCI_XHCLKGTEN_IOSFBTCGE BIT1
+#define B_PCH_XHCI_XHCLKGTEN_IOSFGBLCGE BIT0
+
+#define R_PCH_XHCI_USB_RELNUM 0x60
+#define B_PCH_XHCI_USB_RELNUM 0xFF
+#define R_PCH_XHCI_FL_ADJ 0x61
+#define B_PCH_XHCI_FL_ADJ 0x3F
+#define R_PCH_XHCI_PWR_CAPID 0x70
+#define B_PCH_XHCI_PWR_CAPID 0xFF
+#define R_PCH_XHCI_NXT_PTR1 0x71
+#define B_PCH_XHCI_NXT_PTR1 0xFF
+#define R_PCH_XHCI_PWR_CAP 0x72
+#define B_PCH_XHCI_PWR_CAP_PME_SUP 0xF800
+#define B_PCH_XHCI_PWR_CAP_D2_SUP BIT10
+#define B_PCH_XHCI_PWR_CAP_D1_SUP BIT9
+#define B_PCH_XHCI_PWR_CAP_AUX_CUR (BIT8 | BIT7 | BIT6)
+#define B_PCH_XHCI_PWR_CAP_DSI BIT5
+#define B_PCH_XHCI_PWR_CAP_PME_CLK BIT3
+#define B_PCH_XHCI_PWR_CAP_VER (BIT2 | BIT1 | BIT0)
+#define R_PCH_XHCI_PWR_CNTL_STS 0x74
+#define B_PCH_XHCI_PWR_CNTL_STS_PME_STS BIT15
+#define B_PCH_XHCI_PWR_CNTL_STS_DATASCL (BIT14 | BIT13)
+#define B_PCH_XHCI_PWR_CNTL_STS_DATASEL (BIT12 | BIT11 | BIT10 | BIT9)
+#define B_PCH_XHCI_PWR_CNTL_STS_PME_EN BIT8
+#define B_PCH_XHCI_PWR_CNTL_STS_PWR_STS (BIT1 | BIT0)
+#define V_PCH_XHCI_PWR_CNTL_STS_PWR_STS_D3 (BIT1 | BIT0)
+#define R_PCH_XHCI_MSI_MCTL 0x82
+#define R_PCH_XHCI_HSCFG2 0xA4
+#define R_PCH_XHCI_SSCFG1 0xA8
+#define R_PCH_XHCI_HSCFG1 0xAC
+#define R_PCH_XHCI_U2OCM 0xB0
+#define R_PCH_XHCI_U3OCM 0xD0
+#define V_PCH_XHCI_NUMBER_OF_OC_PINS 8
+
+#define R_PCH_XHCI_FUS 0xE0
+#define B_PCH_XHCI_FUS_USBR (BIT5)
+#define V_PCH_XHCI_FUS_USBR_EN 0
+#define V_PCH_XHCI_FUS_USBR_DIS (BIT5)
+
+#define R_PCH_XHCI_FC 0xFC
+
+#define B_PCH_XHCI_FUS_SSPRTCNT (BIT4 | BIT3)
+#define V_PCH_XHCI_FUS_SSPRTCNT_00B 0
+#define V_PCH_XHCI_FUS_SSPRTCNT_01B (BIT3)
+#define V_PCH_XHCI_FUS_SSPRTCNT_10B (BIT4)
+#define V_PCH_XHCI_FUS_SSPRTCNT_11B (BIT4 | BIT3)
+
+#define B_PCH_XHCI_FUS_HSPRTCNT (BIT2 | BIT1)
+#define V_PCH_XHCI_FUS_HSPRTCNT_00B 0
+#define V_PCH_XHCI_FUS_HSPRTCNT_01B (BIT1)
+#define V_PCH_XHCI_FUS_HSPRTCNT_10B (BIT2)
+#define V_PCH_XHCI_FUS_HSPRTCNT_11B (BIT2 | BIT1)
+
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_00B_CNT 6
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_01B_CNT 4
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_10B_CNT 2
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_11B_CNT 0
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_00B_MASK 0x3F
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_01B_MASK 0x0F
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_10B_MASK 0x03
+#define V_PCH_H_XHCI_FUS_SSPRTCNT_11B_MASK 0x00
+
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_00B_CNT 14
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_01B_CNT 12
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_10B_CNT 10
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_11B_CNT 8
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_00B_MASK 0x3FFF
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_01B_MASK 0x3F3F
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_10B_MASK 0x03FF
+#define V_PCH_H_XHCI_FUS_HSPRTCNT_11B_MASK 0x00FF
+
+#define V_PCH_LP_XHCI_FIXED_SSPRTCNT 4
+#define V_PCH_LP_XHCI_FIXED_SSPRTCNT_MASK 0x0F
+
+#define V_PCH_LP_XHCI_FIXED_HSPRTCNT 8
+#define V_PCH_LP_XHCI_FIXED_HSPRTCNT_MASK 0x00FF
+
+//
+// xHCI MMIO registers
+//
+
+//
+// 0x00 - 0x1F - Capability Registers
+//
+#define R_PCH_XHCI_CAPLENGTH 0x00
+#define R_PCH_XHCI_HCIVERSION 0x02
+#define R_PCH_XHCI_HCSPARAMS1 0x04
+#define R_PCH_XHCI_HCSPARAMS2 0x08
+#define R_PCH_XHCI_HCSPARAMS3 0x0C
+#define B_PCH_XHCI_HCSPARAMS3_U2DEL 0xFFFF0000
+#define B_PCH_XHCI_HCSPARAMS3_U1DEL 0x0000FFFF
+#define R_PCH_XHCI_HCCPARAMS 0x10
+#define B_PCH_XHCI_HCCPARAMS_LHRC BIT5
+#define B_PCH_XHCI_HCCPARAMS_MAXPSASIZE 0xF000
+#define R_PCH_XHCI_DBOFF 0x14
+#define R_PCH_XHCI_RTSOFF 0x18
+
+//
+// 0x80 - 0xBF - Operational Registers
+//
+#define R_PCH_XHCI_USBCMD 0x80
+#define B_PCH_XHCI_USBCMD_RS BIT0 ///< Run/Stop
+#define B_PCH_XHCI_USBCMD_RST BIT1 ///< HCRST
+#define R_PCH_XHCI_USBSTS 0x84
+#define B_PCH_XHCI_USBSTS_HCH BIT0
+#define B_PCH_XHCI_USBSTS_CNR BIT11
+
+//
+// 0x480 - 0x5CF - Port Status and Control Registers
+//
+#define R_PCH_LP_XHCI_PORTSC01USB2 0x480
+#define R_PCH_LP_XHCI_PORTSC02USB2 0x490
+#define R_PCH_LP_XHCI_PORTSC03USB2 0x4A0
+#define R_PCH_LP_XHCI_PORTSC04USB2 0x4B0
+#define R_PCH_LP_XHCI_PORTSC05USB2 0x4C0
+#define R_PCH_LP_XHCI_PORTSC06USB2 0x4D0
+#define R_PCH_LP_XHCI_PORTSC07USB2 0x4E0
+#define R_PCH_LP_XHCI_PORTSC08USB2 0x4F0
+#define R_PCH_LP_XHCI_PORTSC09USB2 0x500
+#define R_PCH_LP_XHCI_PORTSC10USB2 0x510
+
+#define R_PCH_LP_XHCI_PORTSC11USBR 0x520
+#define R_PCH_LP_XHCI_PORTSC12USBR 0x530
+
+#define R_PCH_LP_XHCI_PORTSC01USB3 0x540
+#define R_PCH_LP_XHCI_PORTSC02USB3 0x550
+#define R_PCH_LP_XHCI_PORTSC03USB3 0x560
+#define R_PCH_LP_XHCI_PORTSC04USB3 0x570
+#define R_PCH_LP_XHCI_PORTSC05USB3 0x580
+#define R_PCH_LP_XHCI_PORTSC06USB3 0x590
+
+//
+// 0x480 - 0x5CF - Port Status and Control Registers
+//
+#define R_PCH_H_XHCI_PORTSC01USB2 0x480
+#define R_PCH_H_XHCI_PORTSC02USB2 0x490
+#define R_PCH_H_XHCI_PORTSC03USB2 0x4A0
+#define R_PCH_H_XHCI_PORTSC04USB2 0x4B0
+#define R_PCH_H_XHCI_PORTSC05USB2 0x4C0
+#define R_PCH_H_XHCI_PORTSC06USB2 0x4D0
+#define R_PCH_H_XHCI_PORTSC07USB2 0x4E0
+#define R_PCH_H_XHCI_PORTSC08USB2 0x4F0
+#define R_PCH_H_XHCI_PORTSC09USB2 0x500
+#define R_PCH_H_XHCI_PORTSC10USB2 0x510
+#define R_PCH_H_XHCI_PORTSC11USB2 0x520
+#define R_PCH_H_XHCI_PORTSC12USB2 0x530
+#define R_PCH_H_XHCI_PORTSC13USB2 0x540
+#define R_PCH_H_XHCI_PORTSC14USB2 0x550
+
+#define R_PCH_H_XHCI_PORTSC15USBR 0x560
+#define R_PCH_H_XHCI_PORTSC16USBR 0x570
+
+#define R_PCH_H_XHCI_PORTSC01USB3 0x580
+#define R_PCH_H_XHCI_PORTSC02USB3 0x590
+#define R_PCH_H_XHCI_PORTSC03USB3 0x5A0
+#define R_PCH_H_XHCI_PORTSC04USB3 0x5B0
+#define R_PCH_H_XHCI_PORTSC05USB3 0x5C0
+#define R_PCH_H_XHCI_PORTSC06USB3 0x5D0
+#define R_PCH_H_XHCI_PORTSC07USB3 0x5E0
+#define R_PCH_H_XHCI_PORTSC08USB3 0x5F0
+#define R_PCH_H_XHCI_PORTSC09USB3 0x600
+#define R_PCH_H_XHCI_PORTSC10USB3 0x610
+
+#define B_PCH_XHCI_PORTSCXUSB2_WPR BIT31 ///< Warm Port Reset
+#define B_PCH_XHCI_PORTSCXUSB2_CEC BIT23 ///< Port Config Error Change
+#define B_PCH_XHCI_PORTSCXUSB2_PLC BIT22 ///< Port Link State Change
+#define B_PCH_XHCI_PORTSCXUSB2_PRC BIT21 ///< Port Reset Change
+#define B_PCH_XHCI_PORTSCXUSB2_OCC BIT20 ///< Over-current Change
+#define B_PCH_XHCI_PORTSCXUSB2_WRC BIT19 ///< Warm Port Reset Change
+#define B_PCH_XHCI_PORTSCXUSB2_PEC BIT18 ///< Port Enabled Disabled Change
+#define B_PCH_XHCI_PORTSCXUSB2_CSC BIT17 ///< Connect Status Change
+#define B_PCH_XHCI_PORTSCXUSB2_LWS BIT16 ///< Port Link State Write Strobe
+#define B_PCH_XHCI_USB2_U3_EXIT (BIT5 | BIT6 | BIT7 | BIT8)
+#define B_PCH_XHCI_USB2_U0_MASK (BIT5 | BIT6 | BIT7 | BIT8)
+#define B_PCH_XHCI_PORTSCXUSB2_PP BIT9
+#define B_PCH_XHCI_PORTSCXUSB2_PLS (BIT5 | BIT6 | BIT7 | BIT8) ///< Port Link State
+#define B_PCH_XHCI_PORTSCXUSB2_PR BIT4 ///< Port Reset
+#define B_PCH_XHCI_PORTSCXUSB2_PED BIT1 ///< Port Enable/Disabled
+#define B_PCH_XHCI_PORTSCXUSB2_CCS BIT0 ///< Current Connect Status
+#define B_PCH_XHCI_PORT_CHANGE_ENABLE_MASK (B_PCH_XHCI_PORTSCXUSB2_CEC | B_PCH_XHCI_PORTSCXUSB2_PLC | B_PCH_XHCI_PORTSCXUSB2_PRC | B_PCH_XHCI_PORTSCXUSB2_OCC | B_PCH_XHCI_PORTSCXUSB2_WRC | B_PCH_XHCI_PORTSCXUSB2_PEC | B_PCH_XHCI_PORTSCXUSB2_CSC | B_PCH_XHCI_PORTSCXUSB2_PED)
+#define B_PCH_XHCI_PORTPMSCXUSB2_PTC (BIT28 | BIT29 | BIT30 | BIT31) ///< Port Test Control
+
+#define B_PCH_XHCI_PORTSCXUSB3_WPR BIT31 ///< Warm Port Reset
+#define B_PCH_XHCI_PORTSCXUSB3_CEC BIT23 ///< Port Config Error Change
+#define B_PCH_XHCI_PORTSCXUSB3_PLC BIT22 ///< Port Link State Change
+#define B_PCH_XHCI_PORTSCXUSB3_PRC BIT21 ///< Port Reset Change
+#define B_PCH_XHCI_PORTSCXUSB3_OCC BIT20 ///< Over-current Change
+#define B_PCH_XHCI_PORTSCXUSB3_WRC BIT19 ///< Warm Port Reset Change
+#define B_PCH_XHCI_PORTSCXUSB3_PEC BIT18 ///< Port Enabled Disabled Change
+#define B_PCH_XHCI_PORTSCXUSB3_CSC BIT17 ///< Connect Status Change
+#define B_PCH_XHCI_PORTSCXUSB3_LWS BIT16 ///< Port Link State Write Strobe
+#define B_PCH_XHCI_PORTSCXUSB3_PP BIT9 ///< Port Power
+#define B_PCH_XHCI_PORTSCXUSB3_PLS (BIT8 | BIT7 | BIT6 | BIT5) ///< Port Link State
+#define V_PCH_XHCI_PORTSCXUSB3_PLS_POLLING 0x000000E0 ///< Link is in the Polling State
+#define V_PCH_XHCI_PORTSCXUSB3_PLS_RXDETECT 0x000000A0 ///< Link is in the RxDetect State
+#define V_PCH_XHCI_PORTSCXUSB3_PLS_DISABLED 0x00000080 ///< Link is in the RxDetect State
+#define B_PCH_XHCI_PORTSCXUSB3_PR BIT4 ///< Port Reset
+#define B_PCH_XHCI_PORTSCXUSB3_PED BIT1 ///< Port Enable/Disabled
+#define B_PCH_XHCI_PORTSCXUSB3_CHANGE_ENABLE_MASK (B_PCH_XHCI_PORTSCXUSB3_CEC | B_PCH_XHCI_PORTSCXUSB3_PLC | B_PCH_XHCI_PORTSCXUSB3_PRC | B_PCH_XHCI_PORTSCXUSB3_OCC | B_PCH_XHCI_PORTSCXUSB3_WRC | B_PCH_XHCI_PORTSCXUSB3_PEC | B_PCH_XHCI_PORTSCXUSB3_CSC | B_PCH_XHCI_PORTSCXUSB3_PED)
+//
+// 0x2000 - 0x21FF - Runtime Registers
+// 0x3000 - 0x307F - Doorbell Registers
+//
+#define R_PCH_XHCI_XECP_SUPP_USB2_2 0x8008
+#define R_PCH_XHCI_XECP_SUPP_USB3_2 0x8028
+#define R_PCH_XHCI_HOST_CTRL_SCH_REG 0x8094
+#define R_PCH_XHCI_HOST_CTRL_IDMA_REG 0x809C
+#define R_PCH_XHCI_PMCTRL 0x80A4
+#define R_PCH_XHCI_PGCBCTRL 0x80A8 ///< PGCB Control
+#define R_PCH_XHCI_HOST_CTRL_MISC_REG 0x80B0 ///< Host Controller Misc Reg
+#define R_PCH_XHCI_HOST_CTRL_MISC_REG_2 0x80B4 ///< Host Controller Misc Reg 2
+#define R_PCH_XHCI_SSPE 0x80B8 ///< Super Speed Port Enables
+#define B_PCH_XHCI_LP_SSPE_MASK 0x3F ///< LP: Mask for 6 USB3 ports
+#define B_PCH_XHCI_H_SSPE_MASK 0x3FF ///< H: Mask for 10 USB3 ports
+#define R_PCH_XHCI_AUX_CTRL_REG 0x80C0 ///< AUX_CTRL_REG - AUX Reset Control
+#define R_PCH_XHCI_DUAL_ROLE_CFG0 0x80D8
+#define R_PCH_XHCI_DUAL_ROLE_CFG1 0x80DC
+#define R_PCH_XHCI_AUX_CTRL_REG1 0x80E0
+#define R_PCH_XHCI_HOST_CTRL_PORT_LINK_REG 0x80EC ///< SuperSpeed Port Link Control
+#define R_PCH_XHCI_XECP_CMDM_CTRL_REG1 0x818C ///< Command Manager Control 1
+#define R_PCH_XHCI_XECP_CMDM_CTRL_REG2 0x8190 ///< Command Manager Control 2
+#define R_PCH_XHCI_XECP_CMDM_CTRL_REG3 0x8194 ///< Command Manager Control 3
+#define R_PCH_XHCI_USB2_LINK_MGR_CTRL_REG1_DW1 0x80F0 ///< USB2_LINK_MGR_CTRL_REG1 - USB2 Port Link Control 1, 2, 3, 4
+#define R_PCH_XHCI_USB2_LINK_MGR_CTRL_REG1_DW2 0x80F4 ///< USB2_LINK_MGR_CTRL_REG1 - USB2 Port Link Control 1, 2, 3, 4
+#define R_PCH_XHCI_USB2_LINK_MGR_CTRL_REG1_DW3 0x80F8 ///< USB2_LINK_MGR_CTRL_REG1 - USB2 Port Link Control 1, 2, 3, 4
+#define R_PCH_XHCI_USB2_LINK_MGR_CTRL_REG1_DW4 0x80FC ///< USB2_LINK_MGR_CTRL_REG1 - USB2 Port Link Control 1, 2, 3, 4
+#define R_PCH_XHCI_HOST_CTRL_TRM_REG2 0x8110 ///< HOST_CTRL_TRM_REG2 - Host Controller Transfer Manager Control 2
+#define R_PCH_XHCI_AUX_CTRL_REG2 0x8154 ///< AUX_CTRL_REG2 - Aux PM Control Register 2
+#define R_PCH_XHCI_AUXCLKCTL 0x816C ///< xHCI Aux Clock Control Register
+#define R_PCH_XHCI_HOST_IF_PWR_CTRL_REG0 0x8140 ///< HOST_IF_PWR_CTRL_REG0 - Power Scheduler Control 0
+#define R_PCH_XHCI_HOST_IF_PWR_CTRL_REG1 0x8144 ///< HOST_IF_PWR_CTRL_REG1 - Power Scheduler Control 1
+#define R_PCH_XHCI_XHCLTVCTL2 0x8174 ///< xHC Latency Tolerance Parameters - LTV Control
+#define R_PCH_XHCI_LTVHIT 0x817C ///< xHC Latency Tolerance Parameters - High Idle Time Control
+#define R_PCH_XHCI_LTVMIT 0x8180 ///< xHC Latency Tolerance Parameters - Medium Idle Time Control
+#define R_PCH_XHCI_LTVLIT 0x8184 ///< xHC Latency Tolerance Parameters - Low Idle Time Control
+#define R_PCH_XHCI_USB2PHYPM 0x8164 ///< USB2 PHY Power Management Control
+#define R_PCH_XHCI_PDDIS 0x8198 ///< xHC Pulldown Disable Control
+#define R_PCH_XHCI_THROTT 0x819C ///< XHCI Throttle Control
+#define R_PCH_XHCI_LFPSPM 0x81A0 ///< LFPS PM Control
+#define R_PCH_XHCI_THROTT2 0x81B4 ///< XHCI Throttle
+#define R_PCH_XHCI_LFPSONCOUNT 0x81B8 ///< LFPS On Count
+#define R_PCH_XHCI_D0I2CTRL 0x81BC ///< D0I2 Control Register
+#define R_PCH_XHCI_USB2PMCTRL 0x81C4 ///< USB2 Power Management Control
+
+//
+// SKL PCH LP FUSE
+//
+#define R_PCH_XHCI_LP_FUSE1 0x8410
+#define B_PCH_XHCI_LP_FUS_HSPRTCNT (BIT1)
+#define B_PCH_XHCI_LP_FUS_USBR (BIT5)
+#define R_PCH_XHCI_STRAP2 0x8420 ///< USB3 Mode Strap
+#define B_PCH_XHCI_STRAP2_USB3_SSIC_MODE (BIT1 | BIT0) ///< USB3/SSIC Mode
+#define R_PCH_XHCI_USBLEGCTLSTS 0x8470 ///< USB Legacy Support Control Status
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIBAR BIT31 ///< SMI on BAR Status
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIPCIC BIT30 ///< SMI on PCI Command Status
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIOSC BIT29 ///< SMI on OS Ownership Change Status
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIBARE BIT15 ///< SMI on BAR Enable
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIPCICE BIT14 ///< SMI on PCI Command Enable
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIOSOE BIT13 ///< SMI on OS Ownership Enable
+#define B_PCH_XHCI_USBLEGCTLSTS_SMIHSEE BIT4 ///< SMI on Host System Error Enable
+#define B_PCH_XHCI_USBLEGCTLSTS_USBSMIE BIT0 ///< USB SMI Enable
+
+//
+// Extended Capability Registers
+//
+#define R_PCH_XHCI_USB2PDO 0x84F8
+#define B_PCH_XHCI_LP_USB2PDO_MASK 0x3FF ///< LP: Mask for 10 USB2 ports
+#define B_PCH_XHCI_H_USB2PDO_MASK 0x7FFF ///< H: Mask for 14 USB2 ports
+#define B_PCH_XHCI_USB2PDO_DIS_PORT0 BIT0
+
+#define R_PCH_XHCI_USB3PDO 0x84FC
+#define B_PCH_XHCI_LP_USB3PDO_MASK 0x3F ///< LP: Mask for 6 USB3 ports
+#define B_PCH_XHCI_H_USB3PDO_MASK 0x3FF ///< H: Mask for 10 USB3 ports
+#define B_PCH_XHCI_USB3PDO_DIS_PORT0 BIT0
+
+//
+// Debug Capability Descriptor Parameters
+//
+#define R_PCH_XHCI_DBC_DBCCTL 0x8760 ///< DBCCTL - DbC Control
+
+//
+// xDCI (OTG) USB Device Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_XDCI 20
+#define PCI_FUNCTION_NUMBER_PCH_XDCI 1
+
+//
+// xDCI (OTG) PCI Config Space Registers
+//
+#define R_PCH_XDCI_MEM_BASE 0x10
+#define V_PCH_XDCI_MEM_LENGTH 0x200000
+#define R_PCH_XDCI_PMCSR 0x84 ///< Power Management Control and Status Register
+#define R_PCH_XDCI_GENERAL_PURPOSER_REG1 0xA0 ///< General Purpose PCI RW Register1
+#define R_PCH_XDCI_CPGE 0xA2 ///< Chassis Power Gate Enable
+#define R_PCH_XDCI_GENERAL_PURPOSER_REG4 0xAC ///< General Purpose PCI RW Register4
+#define R_PCH_OTG_GENERAL_INPUT_REG 0xC0 ///< General Input Register
+
+//
+// xDCI (OTG) MMIO registers
+//
+#define R_PCH_XDCI_GCTL 0xC110 ///< Xdci Global Ctrl
+#define B_PCH_XDCI_GCTL_GHIBEREN BIT1 ///< Hibernation enable
+#define R_PCH_XDCI_GUSB2PHYCFG 0xC200 ///< Global USB2 PHY Configuration Register
+#define B_PCH_XDCI_GUSB2PHYCFG_SUSPHY BIT6 ///< Suspend USB2.0 HS/FS/LS PHY
+#define R_PCH_XDCI_GUSB3PIPECTL0 0xC2C0 ///< Global USB3 PIPE Control Register 0
+#define B_PCH_XDCI_GUSB3PIPECTL0_UX_IN_PX BIT27 ///< Ux Exit in Px
+#define R_PCH_XDCI_APBFC_U3PMU_CFG2 0x10F810
+#define R_PCH_XDCI_APBFC_U3PMU_CFG4 0x10F818
+#define R_PCH_XDCI_APBFC_U3PMU_CFG5 0x10F81C
+#define R_PCH_XDCI_APBFC_U3PMU_CFG6 0x10F820
+
+//
+// xDCI (OTG) Private Configuration Registers
+// (PID:OTG)
+//
+#define R_PCH_PCR_OTG_IOSF_A2 0xA2
+#define R_PCH_PCR_OTG_IOSF_PMCTL 0x1D0
+#define R_PCH_PCR_OTG_PCICFGCTRL1 0x200
+#define B_PCH_PCR_OTG_PCICFGCTRL_PCI_IRQ 0x0FF00000
+#define N_PCH_PCR_OTG_PCICFGCTRL_PCI_IRQ 20
+#define B_PCH_PCR_OTG_PCICFGCTRL_ACPI_IRQ 0x000FF000
+#define N_PCH_PCR_OTG_PCICFGCTRL_ACPI_IRQ 12
+#define B_PCH_PCR_OTG_PCICFGCTRL_INT_PIN 0x00000F00
+#define N_PCH_PCR_OTG_PCICFGCTRL_INT_PIN 8
+#define B_PCH_PCR_OTG_PCICFGCTRL_BAR1_DIS 0x00000080
+#define B_PCH_PCR_OTG_PCICFGCTRL_PME_SUP 0x0000007C
+#define B_PCH_PCR_OTG_PCICFGCTRL_ACPI_INT_EN 0x00000002
+#define B_PCH_PCR_OTG_PCICFGCTRL_PCI_CFG_DIS 0x00000001
+
+//
+// USB2 Private Configuration Registers
+// USB2 HIP design featured
+// (PID:USB2)
+//
+#define R_PCH_PCR_USB2_GLOBAL_PORT 0x4001 ///< USB2 GLOBAL PORT
+#define R_PCH_PCR_USB2_400C 0x400C
+#define R_PCH_PCR_USB2_PP_LANE_BASE_ADDR 0x4000 ///< PP LANE base address
+#define V_PCH_PCR_USB2_PER_PORT 0x00 ///< USB2 PER PORT Addr[7:2] = 0x00
+#define V_PCH_PCR_USB2_UTMI_MISC_PER_PORT 0x08 ///< UTMI MISC REG PER PORT Addr[7:2] = 0x08
+#define V_PCH_PCR_USB2_PER_PORT_2 0x26 ///< USB2 PER PORT 2 Addr[7:2] = 0x26
+#define R_PCH_PCR_USB2_402A 0x402A
+#define R_PCH_PCR_USB2_GLB_ADP_VBUS_REG 0x402B ///< GLB ADP VBUS REG
+#define R_PCH_PCR_USB2_GLOBAL_PORT_2 0x402C ///< USB2 GLOBAL PORT 2
+#define R_PCH_PCR_USB2_7034 0x7034
+#define R_PCH_PCR_USB2_7038 0x7038
+#define R_PCH_PCR_USB2_703C 0x703C
+#define R_PCH_PCR_USB2_7040 0x7040
+#define R_PCH_PCR_USB2_7044 0x7044
+#define R_PCH_PCR_USB2_7048 0x7048
+#define R_PCH_PCR_USB2_704C 0x704C
+#define R_PCH_PCR_USB2_CFG_COMPBG 0x7F04 ///< USB2 COMPBG
+
+//
+// xHCI SSIC registers
+//
+#define R_PCH_XHCI_SSIC_GLOBAL_CONF_CTRL 0x8804 ///< SSIC Global Configuration Control
+#define R_PCH_XHCI_SSIC_CONF_REG1_PORT_1 0x8808 ///< SSIC Configuration Register 1 Port 1
+#define R_PCH_XHCI_SSIC_CONF_REG2_PORT_1 0x880C ///< SSIC Configuration Register 2 Port 1
+#define R_PCH_XHCI_SSIC_CONF_REG3_PORT_1 0x8810 ///< SSIC Configuration Register 3 Port 1
+#define R_PCH_XHCI_SSIC_CONF_REG1_PORT_2 0x8838 ///< SSIC Configuration Register 1 Port 2
+#define R_PCH_XHCI_SSIC_CONF_REG2_PORT_2 0x883C ///< SSIC Configuration Register 2 Port 2
+#define R_PCH_XHCI_SSIC_CONF_REG3_PORT_2 0x8840 ///< SSIC Configuration Register 3 Port 2
+#define B_PCH_XHCI_SSIC_CONF_REG2_PORT_UNUSED BIT31
+#define B_PCH_XHCI_SSIC_CONF_REG2_PROG_DONE BIT30
+
+#define R_PCH_XHCI_SSIC_PROF_ATTR_PORT_1 0x8900 ///< Profile Attributes: Port 1 ... N
+#define R_PCH_XHCI_SSIC_ACCESS_CONT_PORT_1 0x8904 ///< SSIC Port N Register Access Control: Port 1
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_0C 0x890C
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_10 0x8910
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_14 0x8914
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_18 0x8918
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_1C 0x891C
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_20 0x8920
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_24 0x8924
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P1_28 0x8928
+
+#define R_PCH_XHCI_SSIC_PROF_ATTR_PORT_2 0x8A10 ///< Profile Attributes: Port 2 ... N
+#define R_PCH_XHCI_SSIC_ACCESS_CONT_PORT_2 0x8A14 ///< SSIC Port N Register Access Control: Port 2
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_0C 0x8A1C
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_10 0x8A20
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_14 0x8A24
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_18 0x8A28
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_1C 0x8A2C
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_20 0x8A30
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_24 0x8A34
+#define R_PCH_XHCI_SSIC_PROF_ATTR_P2_28 0x8A38
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/DxePchHdaNhlt.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/DxePchHdaNhlt.h
new file mode 100644
index 0000000000..5e7674a412
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/DxePchHdaNhlt.h
@@ -0,0 +1,128 @@
+/** @file
+ Header file for DxePchHdaLib - NHLT structure definitions.
+
+Copyright (c) 2017, 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 that 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 _DXE_PCH_HDA_NHLT_H_
+#define _DXE_PCH_HDA_NHLT_H_
+
+#include <IndustryStandard/Acpi.h>
+
+//
+// ACPI support protocol instance signature definition.
+//
+#define NHLT_ACPI_TABLE_SIGNATURE SIGNATURE_32 ('N', 'H', 'L', 'T')
+
+// MSFT defined structures
+#define SPEAKER_FRONT_LEFT 0x1
+#define SPEAKER_FRONT_RIGHT 0x2
+#define SPEAKER_FRONT_CENTER 0x4
+#define SPEAKER_BACK_LEFT 0x10
+#define SPEAKER_BACK_RIGHT 0x20
+
+#define KSAUDIO_SPEAKER_MONO (SPEAKER_FRONT_CENTER)
+#define KSAUDIO_SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)
+#define KSAUDIO_SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
+
+#define WAVE_FORMAT_EXTENSIBLE 0xFFFE /* Microsoft */
+#define KSDATAFORMAT_SUBTYPE_PCM \
+ {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}
+
+#pragma pack (push, 1)
+
+typedef struct {
+ UINT16 wFormatTag;
+ UINT16 nChannels;
+ UINT32 nSamplesPerSec;
+ UINT32 nAvgBytesPerSec;
+ UINT16 nBlockAlign;
+ UINT16 wBitsPerSample;
+ UINT16 cbSize;
+} WAVEFORMATEX;
+
+typedef struct {
+ WAVEFORMATEX Format;
+ union {
+ UINT16 wValidBitsPerSample;
+ UINT16 wSamplesPerBlock;
+ UINT16 wReserved;
+ } Samples;
+ UINT32 dwChannelMask;
+ GUID SubFormat;
+} WAVEFORMATEXTENSIBLE;
+
+//
+// List of supported link type.
+//
+enum NHLT_LINK_TYPE
+{
+ HdaNhltLinkHd = 0,
+ HdaNhltLinkDsp = 1,
+ HdaNhltLinkDmic = 2,
+ HdaNhltLinkSsp = 3,
+ HdaNhltLinkInvalid
+};
+
+//
+// List of supported device type.
+//
+enum NHLT_DEVICE_TYPE
+{
+ HdaNhltDeviceBt = 0,
+ HdaNhltDeviceDmic = 1,
+ HdaNhltDeviceI2s = 4,
+ HdaNhltDeviceInvalid
+};
+
+typedef struct {
+ UINT32 CapabilitiesSize;
+ UINT8 Capabilities[1];
+} SPECIFIC_CONFIG;
+
+typedef struct {
+ WAVEFORMATEXTENSIBLE Format;
+ SPECIFIC_CONFIG FormatConfiguration;
+} FORMAT_CONFIG;
+
+typedef struct {
+ UINT8 FormatsCount;
+ FORMAT_CONFIG FormatsConfiguration[1];
+} FORMATS_CONFIG;
+
+typedef struct {
+ UINT32 EndpointDescriptorLength;
+ UINT8 LinkType;
+ UINT8 InstanceId;
+ UINT16 HwVendorId;
+ UINT16 HwDeviceId;
+ UINT16 HwRevisionId;
+ UINT32 HwSubsystemId;
+ UINT8 DeviceType;
+ UINT8 Direction;
+ UINT8 VirtualBusId;
+ SPECIFIC_CONFIG EndpointConfig;
+ FORMATS_CONFIG FormatsConfig;
+} ENDPOINT_DESCRIPTOR;
+
+//
+// High Level Table structure
+//
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header; //{'N', 'H', 'L', 'T'}
+ UINT8 EndpointCount; // Actual number of endpoints
+ ENDPOINT_DESCRIPTOR EndpointDescriptors[1];
+ SPECIFIC_CONFIG OedConfiguration;
+} NHLT_ACPI_TABLE;
+
+#pragma pack (pop)
+
+#endif // _DXE_PCH_HDA_NHLT_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/GpioPrivateLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/GpioPrivateLib.h
new file mode 100644
index 0000000000..f555182bc4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/GpioPrivateLib.h
@@ -0,0 +1,212 @@
+/** @file
+ Header file for GpioPrivateLib.
+ All function in this library is available for PEI, DXE, and SMM,
+
+Copyright (c) 2017, 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 that 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 _GPIO_PRIVATE_LIB_H_
+#define _GPIO_PRIVATE_LIB_H_
+
+#include <GpioConfig.h>
+
+/**
+ This procedure will get value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[out] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ OUT UINT32 *RegVal
+ );
+
+/**
+ This procedure will set value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[in] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ IN UINT32 RegVal
+ );
+
+/**
+ This procedure is used by PchSmiDispatcher and will return information
+ needed to register GPI SMI. Relation between Index and GpioPad number is:
+ Index = GpioGroup + 24 * GpioPad
+
+ @param[in] Index GPI SMI number
+ @param[out] GpioPin GPIO pin
+ @param[out] GpiSmiBitOffset GPI SMI bit position within GpiSmi Registers
+ @param[out] GpiSmiEnRegAddress Address of GPI SMI Enable register
+ @param[out] GpiSmiStsRegAddress Address of GPI SMI status register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadAndSmiRegs (
+ IN UINT32 Index,
+ OUT GPIO_PAD *GpioPin,
+ OUT UINT8 *GpiSmiBitOffset,
+ OUT UINT32 *GpiSmiEnRegAddress,
+ OUT UINT32 *GpiSmiStsRegAddress
+ );
+
+/**
+ This procedure will clear GPIO_UNLOCK_SMI_STS
+
+ @param[in] None
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearUnlockSmiSts (
+ VOID
+ );
+
+/**
+ This procedure will set GPIO Driver IRQ number
+
+ @param[in] Irq Irq number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid IRQ number
+**/
+EFI_STATUS
+GpioSetIrq (
+ IN UINT8 Irq
+ );
+
+/**
+ This procedure will perform special handling of GPP_A_12 on PCH-LP.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+GpioA12SpecialHandling (
+ VOID
+ );
+
+/**
+ This function sets ISH I2C controller pins into native mode
+
+ @param[in] IshI2cControllerNumber I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshI2cPinsIntoNativeMode (
+ IN UINT32 IshI2cControllerNumber
+ );
+
+/**
+ This function sets ISH UART controller pins into native mode
+
+ @param[in] IshUartControllerNumber UART controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshUartPinsIntoNativeMode (
+ IN UINT32 IshUartControllerNumber
+ );
+
+/**
+ This function sets ISH SPI controller pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshSpiPinsIntoNativeMode (
+ VOID
+ );
+
+/**
+ This function sets ISH GP pins into native mode
+
+ @param[in] IshGpPinNumber ISH GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshGpPinsIntoNativeMode (
+ IN UINT32 IshGpPinNumber
+ );
+
+/**
+ Returns pad for given CLKREQ# index.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return CLKREQ# pad.
+**/
+GPIO_PAD
+GpioGetClkreqPad (
+ IN UINT32 ClkreqIndex
+ );
+
+/**
+ Enables CLKREQ# pad in native mode.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return none
+**/
+VOID
+GpioEnableClkreq (
+ IN UINT32 ClkreqIndex
+ );
+
+/**
+ This function checks if GPIO pin for PCHHOTB is in NATIVE MODE
+
+ @param[in] none
+
+ @retval TRUE Pin is in PCHHOTB native mode
+ FALSE Pin is in gpio mode or is not owned by HOST
+**/
+BOOLEAN
+GpioIsPchHotbPinInNativeMode (
+ VOID
+ );
+
+/**
+ This function sets CPU GP pins into native mode
+
+ @param[in] CpuGpPinNum CPU GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCpuGpPinsIntoNativeMode (
+ IN UINT32 CpuGpPinNum
+ );
+
+#endif // _GPIO_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/I2cMasterCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/I2cMasterCommonLib.h
new file mode 100644
index 0000000000..8f0a1adf38
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/I2cMasterCommonLib.h
@@ -0,0 +1,290 @@
+/** @file
+ Implement the I2C port control.
+
+Copyright (c) 2017, 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 that 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 _I2C_MASTER_COMMON_LIB_H_
+#define _I2C_MASTER_COMMON_LIB_H_
+
+///
+/// Each I2C port instance uses an I2C_MASTER_CONTEXT structure
+/// to maintain its context.
+///
+typedef struct {
+ EFI_I2C_CONTROLLER_CAPABILITIES Capabilities;
+ //
+ // I2C master's mmio addresses cached to speed up operation
+ //
+ UINTN MmioAddress;
+ UINTN ConfigAddress;
+ //
+ // copy of all pointers and data provided in StartRequest call
+ // if transfer didn't finish in one go, those will be needed to continue it
+ //
+ EFI_I2C_REQUEST_PACKET *Request;
+ //
+ // Internal copy of Transfer status, to be returned from StartRequest()
+ //
+ EFI_STATUS TransferStatus;
+ //
+ // Index (Operation:Postition in Buffer) of next operation to be performed
+ // Write is for both R/W operations as both need to be put in fifo
+ // Read is for Read only, for filling buffer with data retrieved from bus
+ //
+ UINTN WriteOp;
+ UINTN WritePos;
+ UINTN ReadOp;
+ UINTN ReadPos;
+ BOOLEAN TransferInProgress;
+} I2C_MASTER_CONTEXT;
+
+/**
+ Prepare I2c controller for use: enable its mmio range, put in D0, get out of reset
+
+ @param[in] Context - driver context
+**/
+VOID
+PrepareController (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Determine the state of the I2C controller
+
+ @param[in] Context - driver context
+
+ @retval TRUE The I2C controller is active
+ @retval FALSE The I2C controller is idle
+**/
+BOOLEAN
+IsHardwareActive (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Updates WriteOperation and WritePosition, two variables that determine
+ which part of Request is being committed to I2C bus.
+ This iterates over both Read and Write operations from a request, because
+ things that need to be written to WriteFifo are both I2c bus writes
+ and I2c bus reads (the command to perform bus read needs to be put into Write Fifo)
+
+ @param[in] Context - driver context
+**/
+VOID
+UpdateWritePosition (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ FindReadOp checks if current Operation is of Read type. If so, returns.
+ If not, increases ReadOp until it finds one or goes beyond Request's OperationCount
+
+ @param[in] Context - driver context
+**/
+VOID
+FindReadOp (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Updates ReadOperation and ReadPosition, two variables that determine
+ which part of Request is being filled with data incoming from I2C reads.
+ This iterates only over Read operations from a request.
+
+ @param[in] Context - driver context
+**/
+VOID
+UpdateReadPosition (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ ValidateRequest checks if Request is valid and can be started
+
+ @param[in] Context driver context
+ @param[in] RequestPacket content of I2C request package
+
+ @retval EFI_SUCCESS Request is valid and can be started
+ @retval EFI_ALREADY_STARTED The controller is busy with another transfer
+ @retval EFI_BAD_BUFFER_SIZE Transfer size too big
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL, invalid Operation flags
+ @retval EFI_UNSUPPORTED 10bit I2C address or "ping" operation attempted (0-byte transfer, address byte not followed by any data)
+**/
+EFI_STATUS
+ValidateRequest (
+ I2C_MASTER_CONTEXT *Context,
+ CONST EFI_I2C_REQUEST_PACKET *RequestPacket
+ );
+
+/**
+ IsLastFromRequest checks if WritePos and WriteOp point to the last byte of the request
+
+ @param[in] Context - driver context
+**/
+BOOLEAN
+IsLastFromRequest (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ IsLastFromRequest checks if WritePos and WriteOp point to the first byte of an operation
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsFirstFromOperation (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ InitializeTransfer checks if HW is ready to accept new transfer.
+ If so, sets up slave address
+
+ @param[in] Context - driver context
+
+ @retval Status
+**/
+EFI_STATUS
+InitializeTransfer (
+ I2C_MASTER_CONTEXT *Context,
+ UINTN SlaveAddress,
+ CONST EFI_I2C_REQUEST_PACKET *RequestPacket
+ );
+
+/**
+ WriteFifo writes to I2c controller's transmit Fifo. Data written to Fifo could be
+ - data bytes to be written to an I2C slave
+ - read requests that trigger I2C bus reads
+ First transfer from each operation adds Restart bit which triggers Restart condition on bus
+ Last transfer from the whole Request adds Stop bit which triggers Stop condtion on bus
+ Driver keeps track of which parts of Request were already committed to hardware using
+ pointer consisting of WritePosition and WriteOperation variables. This pointer is updated
+ every time data byte/read request is committed to FIFO
+ WriteFifo executes while there's anything more to write and the write fifo isn't full
+
+ @param[in] Context - driver context
+**/
+VOID
+WriteFifo (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ ReadFifo reads from I2c controller's receive Fifo. It contains data retrieved
+ from slave device as a result of executing read transfers, which were
+ triggered by putting read requests into Write Fifo. Retrieved data is copied into buffers
+ pointed to by Request structure.
+ Driver keeps track where to copy incoming data using pointer consisting of
+ ReadPosition and ReadOperation variables. This pointer is updated
+ every time data was retrieved from hardware
+ ReadFifo executes while there's data available and receive buffers were not filled
+
+ @param[in] Context - driver context
+**/
+VOID
+ReadFifo (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ CheckErrors checks if there were any transfer errors.
+
+ @param[in] Context - driver context
+**/
+VOID
+CheckErrors (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Transfer is finished when all requested operations were placed in fifo,
+ all read requests were filled and hardware is inactive
+ The last part is necessary for write-only transfers where after
+ placing all writes in fifo sw needs to wait until they flush down the bus
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsTransferFinished (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Clean up Hw activity and errors
+ Return status to Request's submitter and signal the event that tells
+ it that the request is complete
+ Clear up Sw context to allow new request to start
+
+ @param[in] Context - driver context
+**/
+VOID
+FinishTransfer (
+ I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ PerformTransfer. For synchronous transfer this function is called in a loop
+ and for asynchronous transfers, as a timer callback. It writes data and/or
+ read requests to hadrware, copies read data to destination buffers. When
+ transfer completes, it cleans up Sw context and Hw registers in preparation
+ for new transfer
+
+ @param[in] Context - driver context
+**/
+VOID
+PerformTransfer (
+ IN I2C_MASTER_CONTEXT *Context
+ );
+
+/**
+ Set the I2C controller bus clock frequency.
+
+ This routine must be called at or below TPL_NOTIFY.
+
+ The software and controller do a best case effort of using the specified
+ frequency for the I2C bus. If the frequency does not match exactly then
+ the controller will use lower frequency for the I2C to avoid exceeding
+ the operating conditions for any of the I2C devices on the bus.
+ For example if 400 KHz was specified and the controller's divide network
+ only supports 402 KHz or 398 KHz then the controller would be set to 398
+ KHz.
+
+ @param[in] MmioAddress Address of I2C controller
+ @param[in] BusClockHertz New I2C bus clock frequency in Hertz
+
+ @retval EFI_SUCCESS The bus frequency was set successfully.
+ @retval EFI_UNSUPPORTED The controller does not support this frequency.
+**/
+
+EFI_STATUS
+FrequencySet (
+ IN UINTN MmioAddress,
+ IN OUT UINTN *BusClockHertz
+ );
+
+/**
+ Reset the I2C controller
+
+ @param[in] MmioAddress Address of I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+I2cReset (
+ IN UINTN MmioAddress
+ );
+
+#endif // _I2C_MASTER_COMMON_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchHdaLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchHdaLib.h
new file mode 100644
index 0000000000..f3f7c27340
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchHdaLib.h
@@ -0,0 +1,62 @@
+/** @file
+ This library provides PCH HD Audio functions.
+
+Copyright (c) 2017, 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 that 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 _PCH_HDA_LIB_H_
+#define _PCH_HDA_LIB_H_
+
+#include <Library/DxePchHdaNhlt.h>
+#include <PchHdaEndpoints.h>
+
+/**
+ Prints NHLT (Non HDA-Link Table) to be exposed via ACPI (aka. OED (Offload Engine Driver) Configuration Table).
+
+ @param[in] *NhltAcpiTable The NHLT table to print
+**/
+VOID
+NhltAcpiTableDump(
+ IN NHLT_ACPI_TABLE *NhltTable
+ );
+
+/**
+ Constructs EFI_ACPI_DESCRIPTION_HEADER structure for NHLT table.
+
+ @param[in][out] *NhltTable NHLT table for which header will be created
+ @param[in] NhltTableSize Size of NHLT table
+
+ @retval None
+**/
+VOID
+NhltAcpiHeaderConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable,
+ IN UINT32 NhltTableSize
+ );
+
+/**
+ Constructs NHLT_ACPI_TABLE structure based on given Endpoints list.
+
+ @param[in] *EndpointTable List of endpoints for NHLT
+ @param[in][out] **NhltTable NHLT table to be created
+ @param[in][out] *NhltTableSize Size of created NHLT table
+
+ @retval EFI_SUCCESS NHLT created successfully
+ @retval EFI_BAD_BUFFER_SIZE Not enough resources to allocate NHLT
+**/
+EFI_STATUS
+NhltConstructor(
+ IN PCH_HDA_NHLT_ENDPOINTS *EndpointTable,
+ IN OUT NHLT_ACPI_TABLE **NhltTable,
+ IN OUT UINT32 *NhltTableSize
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchInitCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchInitCommonLib.h
new file mode 100644
index 0000000000..8c016c624f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchInitCommonLib.h
@@ -0,0 +1,191 @@
+/** @file
+ Header file for PCH Init Common Lib
+
+Copyright (c) 2017, 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 that 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 _PCH_INIT_COMMON_LIB_H_
+#define _PCH_INIT_COMMON_LIB_H_
+
+#include <PchPolicyCommon.h>
+#include <PchAccess.h>
+
+/**
+ This function returns PID according to PCIe controller index
+
+ @param[in] ControllerIndex PCIe controller index
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+PchGetPcieControllerSbiPid (
+ IN UINT32 ControllerIndex
+ );
+
+/**
+ This function returns PID according to Root Port Number
+
+ @param[in] RpPort Root Port Number
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+GetRpSbiPid (
+ IN UINTN RpPort
+ );
+
+/**
+ Calculate root port device number based on physical port index.
+
+ @param[in] RpIndex Root port index (0-based).
+
+ @retval Root port device number.
+**/
+UINT32
+PchGetPcieRpDevice (
+ IN UINT32 RpIndex
+ );
+
+/**
+ This function reads Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[out] *Data32 Value of Config register
+
+ @retval EFI_SUCCESS SBI Read successful.
+**/
+EFI_STATUS
+PchSbiRpPciRead32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ OUT UINT32 *Data32
+ );
+
+/**
+ This function And then Or Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[in] Data32And Value of Config register to be And-ed
+ @param[in] Data32AOr Value of Config register to be Or-ed
+
+ @retval EFI_SUCCESS SBI Read and Write successful.
+**/
+EFI_STATUS
+PchSbiRpPciAndThenOr32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ IN UINT32 Data32And,
+ IN UINT32 Data32Or
+ );
+
+/**
+ Configure root port function number mapping
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+PchConfigureRpfnMapping (
+ VOID
+ );
+
+/**
+ This function lock down the P2sb SBI before going into OS.
+
+ @param[in] SbiUnlock
+**/
+VOID
+ConfigureP2sbSbiLock (
+ IN CONST BOOLEAN SbiUnlock
+ );
+
+/**
+ Bios will remove the host accessing right to Sideband register range
+ prior to any 3rd party code execution.
+
+ 1) Set EPMASK5 Offset C4 (bits 29, 28, 27, 26, 17, 16, 10, 1) to disable Sideband access for PSF and MIPI controller
+ 2) Set EPMASK7 Offset CC (bits 6, 5) to disable Sideband access for XHCI controller
+ 3) Set the "Endpoint Mask Lock!", P2SB PCI offset E2h bit[1] to 1.
+**/
+VOID
+RemoveSidebandAccess(
+ VOID
+ );
+
+/**
+ Configure PMC static function disable lock
+**/
+VOID
+ConfigurePmcStaticFunctionDisableLock (
+ VOID
+ );
+
+/**
+ Print registers value
+
+ @param[in] PrintMmioBase Mmio base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+PrintRegisters (
+ IN UINTN PrintMmioBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ );
+
+VOID
+PrintPchPciConfigSpace (
+ VOID
+ );
+
+/**
+ Check if RST PCIe Storage Remapping is enabled based on policy
+
+ @param[in] RstPcieStorageRemap The PCH PCIe Storage remapping
+
+ @retval TRUE RST PCIe Storage Remapping is enabled
+ @retval FALSE RST PCIe Storage Remapping is disabled
+**/
+BOOLEAN
+IsRstPcieStorageRemapEnabled (
+ IN CONST PCH_RST_PCIE_STORAGE_CONFIG *RstPcieStorageRemap
+ );
+
+/**
+ Disable the RST remap address decoding range while RST is disabled.
+
+ @param[in] AhciBar ABAR address
+**/
+VOID
+DisableRstRemapDecoding (
+ UINT32 AhciBar
+ );
+
+/**
+ Program Xhci Port Disable Override
+
+ @param[in] XhciMmioBase xHCI controller MBAR0 address
+ @param[in] Usb2DisabledPorts Disabled USB2 ports where each port has its disabling bit
+ @param[in] Usb3DisabledPorts Disabled USB3 ports where each port has its disabling bit
+
+ @retval TRUE if platform reset is needed, otherwise FALSE is returned
+**/
+BOOLEAN
+UsbPdoProgramming (
+ IN UINTN XhciMmioBase,
+ IN UINT32 Usb2DisabledPorts,
+ IN UINT32 Usb3DisabledPorts
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPciExpressHelpersLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPciExpressHelpersLib.h
new file mode 100644
index 0000000000..49c89a2fcc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPciExpressHelpersLib.h
@@ -0,0 +1,284 @@
+/** @file
+ Header file for PCH PCI Express helpers library
+
+Copyright (c) 2017, 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 that 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 _PCH_PCI_EXPRESS_HELPERS_LIB_H_
+#define _PCH_PCI_EXPRESS_HELPERS_LIB_H_
+
+#include <PchPolicyCommon.h>
+
+typedef enum {
+ TpoScale2us,
+ TpoScale10us,
+ TpoScale100us,
+ TpoScaleMax
+} T_PO_SCALE;
+
+typedef struct {
+ UINT32 Value;
+ T_PO_SCALE Scale;
+} T_POWER_ON;
+//
+// Function prototypes
+//
+T_POWER_ON GetTpoCapability (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset
+ );
+
+T_POWER_ON GetTpo (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset
+ );
+
+/*
+ Sets Tpower_on in a device
+
+ According to spec, Tpower_on can only be updated while L1_2 is disabled
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+ @param[in] Tpo value to be programmed into Tpower_on
+*/
+VOID SetTpo (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset,
+ T_POWER_ON Tpo
+ );
+
+/*
+ Converts Tpower_on from value:scale notation to microseconds
+*/
+UINT32 TpoToUs (
+ T_POWER_ON Tpo
+ );
+
+/**
+ Find the Offset to a given Capabilities ID
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId CAPID to search for
+
+ @retval 0 CAPID not found
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT8
+PcieFindCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ );
+
+/**
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Rreporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId Extended CAPID to search for
+
+ @retval 0 CAPID not found
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT16
+PcieFindExtendedCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ );
+
+/**
+ This returns ClkReq Number from Port Number
+
+ @param[in] PortIndex PCIe Port Number (Zero Base. Please use 23 for GBe)
+
+ @retval ClkReq Number
+**/
+UINT8
+GetPortClkReqNumber (
+ IN UINT8 PortIndex
+ );
+
+/**
+ Set Common clock to Root port and Endpoint PCI device
+
+ @param[in] Bus1 Root port Pci Bus Number
+ @param[in] Device1 Root port Pci Device Number
+ @param[in] Function1 Root port Pci Function Number
+ @param[in] Bus2 Endpoint Pci Bus Number
+ @param[in] Device2 Endpoint Pci Device Number
+
+ @exception EFI_UNSUPPORTED Unsupported operation.
+ @retval EFI_SUCCESS VC mapping correctly initialized
+**/
+EFI_STATUS
+PcieSetCommonClock (
+ IN UINT8 Bus1,
+ IN UINT8 Device1,
+ IN UINT8 Function1,
+ IN UINT8 Bus2,
+ IN UINT8 Device2
+ );
+
+/**
+ This function enables the CLKREQ# PM on all the end point functions
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] RootDevice Rootport Device Number
+ @param[in] RootFunction Rootport Function Number
+
+ @retval None
+**/
+VOID
+PcieSetClkreq (
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction
+ );
+
+/**
+ This function get or set the Max Payload Size on all the end point functions
+
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] EndPointDevice The Device Number of the Endpoint
+ @param[in] MaxPayload The Max Payolad Size of the root port
+ @param[in] Operation True: Set the Max Payload Size on all the end point functions
+ False: Get the Max Payload Size on all the end point functions
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieMaxPayloadSize (
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN OUT UINT16 *MaxPayload,
+ IN BOOLEAN Operation
+ );
+
+/**
+ This function disable the forwarding of EOI messages unless it discovers
+ an IOAPIC behind this root port.
+
+ @param[in] RootBus The Bus Number of the root port
+ @param[in] RootDevice The Device Number of the root port
+ @param[in] RootFunction The Function Number of the root port
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] EndPointDevice The Device Number of the Endpoint
+
+ @exception EFI_UNSUPPORTED Unsupported operation.
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieSetEoiFwdDisable (
+ IN UINT8 RootBus,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction,
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice
+ );
+
+
+/**
+ Initializes the root port and its down stream devices
+
+ @param[in] RootPortBus Pci Bus Number of the root port
+ @param[in] RootPortDevice Pci Device Number of the root port
+ @param[in] RootPortFunc Pci Function Number of the root port
+ @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary
+ bus number) and its down stream switches
+ @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate
+ bus number) and its down stream switches
+ @param[in] EnableCpm Enables Clock Power Management; even if disabled, CLKREQ# can still be used by L1 PM substates mechanism
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device.
+**/
+EFI_STATUS
+PchPcieInitRootPortDownstreamDevices (
+ IN UINT8 RootPortBus,
+ IN UINT8 RootPortDevice,
+ IN UINT8 RootPortFunc,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax,
+ IN BOOLEAN EnableCpm
+ );
+
+/**
+ Get current PCIe link speed.
+
+ @param[in] RpBase Root Port base address
+ @return Link speed
+**/
+UINT32
+GetLinkSpeed (
+ UINTN RpBase
+ );
+
+/**
+ Get max PCIe link speed supported by the root port.
+
+ @param[in] RpBase Root Port base address
+ @return Max link speed
+**/
+UINT32
+GetMaxLinkSpeed (
+ UINTN RpBase
+ );
+
+/**
+ Get Pch Maximum Pcie Controller Number
+
+ @retval Pch Maximum Pcie Controller Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPcieControllerNum (
+ VOID
+ );
+
+/**
+ PCIe controller configuration.
+**/
+typedef enum {
+ Pcie4x1 = 0,
+ Pcie1x2_2x1 = 1,
+ Pcie2x2 = 2,
+ Pcie1x4 = 3
+} PCIE_CONTROLLER_CONFIG;
+
+/**
+ Returns the PCIe controller configuration (4x1, 1x2-2x1, 2x2, 1x4)
+
+ @param[in] ControllerIndex Number of PCIe controller (0 based)
+
+ @retval PCIe controller configuration
+**/
+PCIE_CONTROLLER_CONFIG
+GetPcieControllerConfig (
+ IN UINT32 ControllerIndex
+ );
+#endif // _PEI_DXE_SMM_PCH_PCI_EXPRESS_HELPERS_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPsfPrivateLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPsfPrivateLib.h
new file mode 100644
index 0000000000..ad390103ce
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchPsfPrivateLib.h
@@ -0,0 +1,401 @@
+/** @file
+ Header file for PchPsfPrivateLib.
+
+Copyright (c) 2017, 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 that 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 _PCH_PSF_PRIVATE_LIB_H_
+#define _PCH_PSF_PRIVATE_LIB_H_
+
+/**
+ Hide CIO2 devices PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideCio2Device (
+ VOID
+ );
+
+/**
+ Disable CIO2 device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableCio2Device (
+ VOID
+ );
+
+/**
+ Disable HDAudio device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableHdaDevice (
+ VOID
+ );
+
+/**
+ Disable xDCI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableXdciDevice (
+ VOID
+ );
+
+/**
+ Disable xHCI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableXhciDevice (
+ VOID
+ );
+
+/**
+ Disable SATA device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableSataDevice (
+ VOID
+ );
+
+typedef enum {
+ PchPsfEmmc = 0,
+ PchPsfSdio,
+ PchPsfSdcard,
+ PchPsfUfs,
+ PchPsfMaxScsDevNum
+} PCH_PSF_SCS_DEV_NUM;
+
+/**
+ Disable SCS device at PSF level
+
+ @param[in] ScsDevNum SCS Device
+
+ @retval None
+**/
+VOID
+PsfDisableScsDevice (
+ IN PCH_PSF_SCS_DEV_NUM ScsDevNum
+ );
+
+/**
+ Disable SCS devices BAR1 PSF level
+
+ @param[in] ScsDevNum SCS Device
+
+ @retval None
+**/
+VOID
+PsfDisableScsBar1 (
+ IN PCH_PSF_SCS_DEV_NUM ScsDevNum
+ );
+
+/**
+ Disable ISH device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIshDevice (
+ VOID
+ );
+
+/**
+ Disable ISH BAR1 at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIshBar1 (
+ VOID
+ );
+
+/**
+ Disable GbE device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableGbeDevice (
+ VOID
+ );
+
+/**
+ Disable SMBUS device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableSmbusDevice (
+ VOID
+ );
+
+/**
+ Disable Thermal device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableThermalDevice (
+ VOID
+ );
+
+/**
+ Hide Thermal device PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideThermalDevice (
+ VOID
+ );
+
+/**
+ Hide TraceHub ACPI devices PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideTraceHubAcpiDevice (
+ VOID
+ );
+
+/**
+ This procedure will hide TraceHub PciCfgSpace at PSF level
+
+ @retval None
+**/
+VOID
+PsfHideTraceHubDevice (
+ VOID
+ );
+
+/**
+ This procedure will reveal TraceHub PciCfgSpace at PSF level
+
+ @retval None
+**/
+VOID
+PsfRevealTraceHubDevice (
+ VOID
+ );
+
+/**
+ This procedure will disable TraceHub device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableTraceHubDevice (
+ VOID
+ );
+
+/**
+ Re-enable PCIe Root Port at PSF level after it was disabled
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfEnablePcieRootPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Disable PCIe Root Port at PSF level
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfDisablePcieRootPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Disable PCIe Root Port at PSF level.
+ This function will also perform S3 boot script programming
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfDisablePcieRootPortWithS3BootScript (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Program PSF grant counts for PCI express depending on controllers configuration
+
+ @param[in] Controller PCIe controller index
+ @param[in] ControllerConfig Port configuration of controller
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurePcieGrantCounts (
+ UINT8 Controller,
+ UINT8 ControllerConfig
+ );
+
+/**
+ Disable ISM NP Completion Tracking for GbE PSF port
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIsmNpCompletionTrackForGbe (
+ VOID
+ );
+
+/**
+ Program PSF EOI Multicast configuration
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfSetEoiMulticastConfiguration (
+ VOID
+ );
+
+/**
+ This function enables EOI message forwarding in PSF for PCIe ports
+ for cases where IOAPIC is present behind this root port.
+
+ @param[in] RpIndex Root port index (0 based)
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurEoiForPciePort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Reload default RP PSF device number and function number.
+ The PSF register doesn't got reset after system reset, which will result in mismatch between
+ PSF register setting and PCIE PCR PCD register setting. Reset PSF register in early phase
+ to avoid cycle decoding confusing.
+
+ @param[in] None
+
+ @retval Status
+**/
+VOID
+PsfReloadDefaultPcieRpDevFunc (
+ VOID
+ );
+
+/**
+ Assign new function number for PCIe Port Number.
+ This function will also perform S3 boot script programming
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+ @param[in] NewFunction New Function number
+
+ @retval None
+**/
+VOID
+PsfSetPcieFunctionWithS3BootScript (
+ IN UINT32 RpIndex,
+ IN UINT32 NewFunction
+ );
+
+/**
+ This function enables PCIe Relaxed Order in PSF
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfEnablePcieRelaxedOrder (
+ VOID
+ );
+
+/**
+ Configure PSF power management.
+ Must be called after all PSF configuration is completed.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfConfigurePowerManagement (
+ VOID
+ );
+
+/**
+ Enable VTd support in PSF.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PchPsfEnableVtd (
+ VOID
+ );
+
+/**
+ Disable PSF address-based peer-to-peer decoding.
+**/
+VOID
+PchPsfDisableP2pDecoding (
+ VOID
+ );
+
+
+#endif // _PCH_PSF_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSmbusCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSmbusCommonLib.h
new file mode 100644
index 0000000000..5c2a6c30e2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSmbusCommonLib.h
@@ -0,0 +1,166 @@
+/** @file
+ PCH Smbus Protocol
+
+Copyright (c) 2017, 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 that 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 _PCH_SMBUS_COMMON_LIB_H
+#define _PCH_SMBUS_COMMON_LIB_H
+
+//
+// Definitions
+//
+#define STALL_PERIOD 10 * STALL_ONE_MICRO_SECOND ///< 10 microseconds
+#define STALL_TIME STALL_ONE_SECOND ///< 1 second
+#define BUS_TRIES 3 ///< How many times to retry on Bus Errors
+#define SMBUS_NUM_RESERVED 38 ///< Number of device addresses that are reserved by the SMBus spec.
+#define SMBUS_ADDRESS_ARP 0xC2 >> 1
+#define SMBUS_DATA_PREPARE_TO_ARP 0x01
+#define SMBUS_DATA_RESET_DEVICE 0x02
+#define SMBUS_DATA_GET_UDID_GENERAL 0x03
+#define SMBUS_DATA_ASSIGN_ADDRESS 0x04
+#define SMBUS_GET_UDID_LENGTH 17 ///< 16 byte UDID + 1 byte address
+//
+// Private data and functions
+//
+
+typedef
+UINT8
+(EFIAPI *SMBUS_IO_READ) (
+ IN UINT8 Offset
+ );
+
+typedef
+VOID
+(EFIAPI *SMBUS_IO_WRITE) (
+ IN UINT8 Offset,
+ IN UINT8 Data
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *SMBUS_IO_DONE) (
+ IN UINT8 *StsReg
+ );
+
+#define PCH_SMBUS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('p', 's', 'm', 'b')
+
+/**
+ Get SMBUS IO Base address
+
+
+ @retval UINT32 The SMBUS IO Base Address
+**/
+UINT32
+SmbusGetIoBase (
+ VOID
+ );
+
+/**
+ This function provides a standard way to read PCH Smbus IO registers.
+
+ @param[in] Offset Register offset from Smbus base IO address.
+
+ @retval UINT8 Returns data read from IO.
+**/
+UINT8
+EFIAPI
+SmbusIoRead (
+ IN UINT8 Offset
+ );
+
+/**
+ This function provides a standard way to write PCH Smbus IO registers.
+
+ @param[in] Offset Register offset from Smbus base IO address.
+ @param[in] Data Data to write to register.
+
+**/
+VOID
+EFIAPI
+SmbusIoWrite (
+ IN UINT8 Offset,
+ IN UINT8 Data
+ );
+
+/**
+ This function provides a standard way to check if an SMBus transaction has
+ completed.
+
+ @param[in] StsReg Not used for input. On return, contains the
+ value of the SMBus status register.
+
+ @retval TRUE Transaction is complete
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+IoDone (
+ IN UINT8 *StsReg
+ );
+
+/**
+ Check if it's ok to use the bus.
+
+
+ @retval EFI_SUCCESS SmBus is acquired and it's safe to send commands.
+ @retval EFI_TIMEOUT SmBus is busy, it's not safe to send commands.
+**/
+EFI_STATUS
+AcquireBus (
+ VOID
+ );
+
+/**
+ This function provides a standard way to execute Smbus protocols
+ as defined in the SMBus Specification. The data can either be of
+ the Length byte, word, or a block of data. The resulting transaction will be
+ either the SMBus Slave Device accepts this transaction or this function
+ returns with an error
+
+ @param[in] SlaveAddress Smbus Slave device the command is directed at
+ @param[in] Command Slave Device dependent
+ @param[in] Operation Which SMBus protocol will be used
+ @param[in] PecCheck Defines if Packet Error Code Checking is to be used
+ @param[in, out] Length How many bytes to read. Must be 0 <= Length <= 32 depending on Operation
+ It will contain the actual number of bytes read/written.
+ @param[in, out] Buffer Contain the data read/written.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @exception EFI_UNSUPPORTED The operation is unsupported.
+
+ @retval EFI_INVALID_PARAMETER Length or Buffer is NULL for any operation besides
+ quick read or quick write.
+ @retval EFI_TIMEOUT The transaction did not complete within an internally
+ specified timeout period, or the controller is not
+ available for use.
+ @retval EFI_DEVICE_ERROR There was an Smbus error (NACK) during the operation.
+ This could indicate the slave device is not present
+ or is in a hung condition.
+**/
+EFI_STATUS
+SmbusExec (
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ This function initializes the Smbus Registers.
+
+**/
+VOID
+InitializeSmbusRegisters (
+ VOID
+ );
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSpiCommonLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSpiCommonLib.h
new file mode 100644
index 0000000000..8b6b6a6c97
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PchSpiCommonLib.h
@@ -0,0 +1,401 @@
+/** @file
+ Header file for the PCH SPI Common Driver.
+
+Copyright (c) 2017, 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 that 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 _PCH_SPI_COMMON_LIB_H_
+#define _PCH_SPI_COMMON_LIB_H_
+
+//
+// Maximum time allowed while waiting the SPI cycle to complete
+// Wait Time = 6 seconds = 6000000 microseconds
+// Wait Period = 10 microseconds
+//
+#define WAIT_TIME 6000000 ///< Wait Time = 6 seconds = 6000000 microseconds
+#define WAIT_PERIOD 10 ///< Wait Period = 10 microseconds
+
+///
+/// Flash cycle Type
+///
+typedef enum {
+ FlashCycleRead,
+ FlashCycleWrite,
+ FlashCycleErase,
+ FlashCycleReadSfdp,
+ FlashCycleReadJedecId,
+ FlashCycleWriteStatus,
+ FlashCycleReadStatus,
+ FlashCycleMax
+} FLASH_CYCLE_TYPE;
+
+///
+/// Flash Component Number
+///
+typedef enum {
+ FlashComponent0,
+ FlashComponent1,
+ FlashComponentMax
+} FLASH_COMPONENT_NUM;
+
+///
+/// Private data structure definitions for the driver
+///
+#define PCH_SPI_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'S', 'P', 'I')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ PCH_SPI_PROTOCOL SpiProtocol;
+ UINT16 PchAcpiBase;
+ UINTN PchSpiBase;
+ UINT8 ReadPermission;
+ UINT8 WritePermission;
+ UINT32 SfdpVscc0Value;
+ UINT32 SfdpVscc1Value;
+ UINT16 PchStrapBaseAddr;
+ UINT16 PchStrapSize;
+ UINT16 CpuStrapBaseAddr;
+ UINT16 CpuStrapSize;
+ UINT8 NumberOfComponents;
+ UINT32 Component1StartAddr;
+ UINT32 TotalFlashSize;
+} SPI_INSTANCE;
+
+#define SPI_INSTANCE_FROM_SPIPROTOCOL(a) CR (a, SPI_INSTANCE, SpiProtocol, PCH_SPI_PRIVATE_DATA_SIGNATURE)
+
+//
+// Function prototypes used by the SPI protocol.
+//
+
+/**
+ Initialize an SPI protocol instance.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @exception EFI_UNSUPPORTED The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ Acquire pch spi mmio address.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval PchSpiBar0 return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ Release pch spi mmio address.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Write data to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ );
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ );
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ );
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ );
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ );
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ );
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ This function sends the programmed SPI command to the slave device.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SpiRegionType The SPI Region type for flash cycle which is listed in the Descriptor
+ @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in,out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+ @retval EFI_SUCCESS SPI command completes successfully.
+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+**/
+EFI_STATUS
+SendSpiCmd (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN FLASH_CYCLE_TYPE FlashCycleType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN OUT UINT8 *Buffer
+ );
+
+/**
+ Wait execution cycle to complete on the SPI interface.
+
+ @param[in] This The SPI protocol instance
+ @param[in] PchSpiBar0 Spi MMIO base address
+ @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check
+
+ @retval TRUE SPI cycle completed on the interface.
+ @retval FALSE Time out while waiting the SPI cycle to complete.
+ It's not safe to program the next command on the SPI interface.
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINTN PchSpiBar0,
+ IN BOOLEAN ErrorCheck
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PeiI2cMasterLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PeiI2cMasterLib.h
new file mode 100644
index 0000000000..da4cfc6d19
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/PeiI2cMasterLib.h
@@ -0,0 +1,49 @@
+/** @file
+ PEI I2C Master module
+
+Copyright (c) 2017, 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 that 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 _PEI_I2C_MASTER_LIB_H_
+#define _PEI_I2C_MASTER_LIB_H_
+
+#include <Ppi/I2cMaster.h>
+#include <Library/PchSerialIoLib.h>
+
+/*
+ Installs I2cMaster PPIs for each I2c controller.
+
+ @param[in] Controller - SerialIo controller number
+
+ @retval EFI_INVALID_PARAMETER - wrong Controller number
+ @retval EFI_ALREADY_STARTED - I2cMaster Ppi was already installed on given controller
+ @retval EFI_SUCCESS - I2cMaster Ppi succesfully installed
+ @retval any other return value - internal error of InstallPpi function
+*/
+EFI_STATUS
+InstallI2cMasterPpi (
+ PCH_SERIAL_IO_CONTROLLER Controller
+ );
+
+/*
+ Finds I2cMasterPpi instance for a specified controller
+
+ @param[in] Controller - SerialIo controller number
+
+ @retval NULL - couldn't locate I2cMaster Ppi for given controller
+ @retval not-NULL - pointer to I2cMaster Ppi
+*/
+EFI_PEI_I2C_MASTER_PPI*
+LocateI2cMasterPpi (
+ PCH_SERIAL_IO_CONTROLLER Controller
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/RstPrivateLib.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/RstPrivateLib.h
new file mode 100644
index 0000000000..2301c9fc0f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Library/RstPrivateLib.h
@@ -0,0 +1,91 @@
+/** @file
+ Header file for Rst Library
+
+Copyright (c) 2017, 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 that 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 _RST_PRIVATE_LIB_
+#define _RST_PRIVATE_LIB_
+#include <Uefi/UefiBaseType.h>
+#include <Library/PchInfoLib.h>
+#include <PchLimits.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchInitCommonLib.h>
+#include <PcieRegs.h>
+
+#define RST_PCIE_STORAGE_INTERFACE_NONE 0
+#define RST_PCIE_STORAGE_INTERFACE_AHCI 1
+#define RST_PCIE_STORAGE_INTERFACE_NVME 2
+
+#define RST_STONY_BEACH_VENDOR_ID 0x8086
+#define RST_STONY_BEACH_DEVICE_ID 0x2522
+
+#define PCI_CLASS_MASS_STORAGE_NVME 0x08
+#define PCI_CLASS_MASS_STORAGE_AHCI PCI_CLASS_MASS_STORAGE_SATADPA
+
+
+/**
+ Check if there is a remap capable storage device present on Root Port
+
+ @param[in] RpNumber Number of a Root Port to check
+ @param[in] TempPciBus Temporary Pci Bus Number
+
+ @retval UINT8 Device Programming interface, 0 if no remap capable device present
+
+**/
+UINT8
+RstGetProgInterfaceForRemapDevice (
+ IN UINT32 RpNumber,
+ IN UINT32 TempPciBus
+ );
+
+/**
+ Check the lane occupied by certain root port according to the root port number and configuration strap
+ Return 8-bit bitmap where each bit represents the lane number (e.g.: return 00000011b means the root port owns 2 lane)
+
+ @param[in] RootPortNum Root Port Number
+
+ @retval UINT8 Lane Occupied by the Root Port (bitmap)
+**/
+UINT8
+RstGetRpLaneOccupyMask (
+ IN UINT32 RootPortNum
+ );
+
+
+/**
+ Checks PCH generation and returns SATA's GCR.PLS bit number according to root port number with a PCIe storage device
+ connected to.
+
+ @param[in] RootPortNum Root port number which PCIe storage device is connected to
+
+ @retval UINT32 Number of GCR.PLS bit representing root port
+**/
+UINT32
+RstPlsBitNumber (
+ IN UINT32 RootPortNum
+ );
+
+/**
+ Checks if device with given PCI config space address is Intel's Stony Beach.
+
+ @param[in] EndPointPciBase Address of device's PCI config space
+
+ @retval BOOLEAN TRUE if device is Intel's Stony Beach, FALSE othrwise
+**/
+BOOLEAN
+RstIsStonyBeach (
+ IN UINTN EndPointPciBase
+ );
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h
new file mode 100644
index 0000000000..fb372e92ac
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h
@@ -0,0 +1,298 @@
+/** @file
+ The GUID definition for PchConfigHob
+
+Copyright (c) 2017, 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 that 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 _PCH_CONFIG_HOB_H_
+#define _PCH_CONFIG_HOB_H_
+
+#include <ConfigBlock.h>
+#include <PchAccess.h>
+#include <ConfigBlock/SmbusConfig.h>
+#include <ConfigBlock/InterruptConfig.h>
+#include <ConfigBlock/PcieRpConfig.h>
+#include <ConfigBlock/SataConfig.h>
+#include <ConfigBlock/FlashProtectionConfig.h>
+
+extern EFI_GUID gPchConfigHobGuid;
+
+#pragma pack (push,1)
+
+///
+/// This structure contains the HOB which are related to PCH general config.
+///
+typedef struct {
+ /**
+ This member describes whether or not the Compatibility Revision ID (CRID) feature
+ of PCH should be enabled. <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 Crid : 1;
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} GENERAL_HOB;
+
+///
+/// The SMBUS_CONFIG block lists the reserved addresses for non-ARP capable devices in the platform.
+///
+typedef struct {
+ UINT8 RsvdBytes[3];
+ UINT8 NumRsvdSmbusAddresses; ///< The number of elements in the RsvdSmbusAddressTable.
+ /**
+ Array of addresses reserved for non-ARP-capable SMBus devices.
+ **/
+ UINT8 RsvdSmbusAddressTable[PCH_MAX_SMBUS_RESERVED_ADDRESS];
+} SMBUS_HOB;
+
+///
+/// The INTERRUPT describes interrupt settings for PCH HOB.
+///
+typedef struct {
+ UINT8 NumOfDevIntConfig; ///< Number of entries in DevIntConfig table
+ UINT8 GpioIrqRoute; ///< Interrupt routing for GPIO. Default is <b>14</b>.
+ UINT8 Rsvd0[2]; ///< Reserved bytes, align to multiple 4.
+ PCH_DEVICE_INTERRUPT_CONFIG DevIntConfig[PCH_MAX_DEVICE_INTERRUPT_CONFIG]; ///< Array which stores PCH devices interrupts settings
+} INTERRUPT_HOB;
+
+///
+/// The CIO2_HOB block describes SkyCam CIO2 device.
+///
+typedef struct {
+ /**
+ NOTE: For SKL PCH, while CIO2 is enabled,
+ RC will configure CIO2 controller as ACPI mode when PCH stepping < C0, and configure to PCI mode for C0 onwards.
+ **/
+ UINT32 DeviceEnable : 2; ///< 0: Disabled, <b>1: Enabled</b>
+ UINT32 RsvdBits0 : 30;
+} CIO2_HOB;
+
+/**
+ The SERIAL_IO block provides the configurations to set the Serial IO controllers
+ to Acpi devices or Pci controllers, and also set the interrupt type to Acpi or Pci
+ through Policy. It also provides to configure the I2c0 and I2c1 voltage
+ to 1.8v or 3.3v by platform setting.
+ Please refer to PeiDxeSmmPchSerialIoLib.h for definition of device numbers and enum values for the below fields
+**/
+typedef struct {
+ /**
+ 0: Disabled; 1: ACPI Mode; <b>2: PCI Mode</b>; 3: Hidden mode, 4: Legacy UART mode, 5: Skip Init
+ NOTE: Considering the PcdSerialIoUartDebugEnable and PcdSerialIoUartNumber for all SerialIo UARTx,
+ the PCD is more meaningful to represent the board design. It means, if PcdSerialIoUartDebugEnable is not 0,
+ the board is designed to use the SerialIo UART for debug message and the PcdSerialIoUartNumber is dedicated
+ to be Debug UART usage. Therefore, it should grayout the option from setup menu since no other options
+ available for this UART controller on this board, and also override the policy default accordingly.
+ While PcdSerialIoUartDebugEnable is 0, then it's allowed to configure the UART controller by policy.
+ NOTE: While DevMode is set to 5 (Skip Init), BIOS will not initialize this controller. Platform is resonsible for
+ configuring this controller. If platform initializes the Serial IO controller in Hidden Mode, it MUST
+ follow the predefined BAR address for the controller.
+ **/
+ UINT8 DevMode[PCH_SERIALIO_MAX_CONTROLLERS]; ///< serial io max controllers default is <b>11</b>.
+ UINT8 Gpio; ///< 0: Disabled; <b>1: Enabled</b>.
+ UINT32 DebugUartNumber : 2; ///< UART number for debug purpose. 0:UART0, 1: UART1, <b>2:UART2</b>
+ UINT32 EnableDebugUartAfterPost : 1; ///< Enable debug UART controller after post. 0: diabled, <b>1: enabled</b>
+ UINT32 RsvdBits0 : 29;
+} SERIAL_IO_HOB;
+
+
+///
+/// The PCH_PCIE_CONFIG block describes the expected configuration of the PCH PCI Express controllers
+///
+typedef struct {
+ ///
+ /// These members describe the configuration of each PCH PCIe root port.
+ ///
+ PCH_PCIE_ROOT_PORT_CONFIG RootPort[PCH_MAX_PCIE_ROOT_PORTS];
+ /**
+ This member allows BIOS to control ICC PLL Shutdown by determining PCIe devices are LTR capable
+ or leaving untouched.
+ - <b>0: Disable, ICC PLL Shutdown is determined by PCIe device LTR capablility.</b>
+ - To allow ICC PLL shutdown if all present PCIe devices are LTR capable or if no PCIe devices are
+ presented for maximum power savings where possible.
+ - To disable ICC PLL shutdown when BIOS detects any non-LTR capable PCIe device for ensuring device
+ functionality.
+ - 1: Enable, To allow ICC PLL shutdown even if some devices do not support LTR capability.
+ **/
+ UINT32 AllowNoLtrIccPllShutdown : 1;
+ UINT32 RsvdBits0 : 31;
+} PCIERP_HOB;
+
+typedef struct {
+ UINT32 DspEnable : 1; ///< DSP enablement: 0: Disable; <b>1: Enable</b>
+ /**
+ Bitmask of supported DSP endpoint configuration exposed via NHLT ACPI table:
+ **/
+ UINT32 DspEndpointDmic : 2; ///< DMIC Select (PCH_HDAUDIO_DMIC_TYPE enum): 0: Disable; 1: 2ch array; <b>2: 4ch array</b>; 3: 1ch array
+ UINT32 DspEndpointBluetooth : 1; ///< Bluetooth enablement: <b>0: Disable</b>; 1: Enable
+ UINT32 DspEndpointI2s : 1; ///< I2S enablement: <b>0: Disable</b>; 1: Enable
+ UINT32 RsvdBits0 : 27; ///< Reserved bits
+ /**
+ Bitmask of supported DSP features:
+ [BIT0] - WoV; [BIT1] - BT Sideband; [BIT2] - Codec VAD; [BIT5] - BT Intel HFP; [BIT6] - BT Intel A2DP
+ [BIT7] - DSP based speech pre-processing disabled; [BIT8] - 0: Intel WoV, 1: Windows Voice Activation
+ Default is <b>zero</b>.
+ **/
+ UINT32 DspFeatureMask;
+} HDAUDIO_HOB;
+
+typedef struct {
+ ///
+ /// This member describes whether or not the SATA controllers should be enabled. 0: Disable; <b>1: Enable</b>.
+ ///
+ UINT32 Enable : 1;
+ UINT32 TestMode : 1; ///< <b>(Test)</b> <b>0: Disable</b>; 1: Allow entrance to the PCH SATA test modes
+ UINT32 RsvdBits0 : 30; ///< Reserved bits
+ /**
+ This member configures the features, property, and capability for each SATA port.
+ **/
+ PCH_SATA_PORT_CONFIG PortSettings[PCH_MAX_SATA_PORTS];
+ /**
+ This member describes the details of implementation of Intel RST for PCIe Storage remapping (Intel RST Driver is required)
+ **/
+ PCH_RST_PCIE_STORAGE_CONFIG RstPcieStorageRemap[PCH_MAX_RST_PCIE_STORAGE_CR];
+} SATA_HOB;
+
+/**
+ The THERMAL_HOB block describes the expected configuration of the PCH for Thermal.
+**/
+typedef struct {
+ UINT32 ThermalDeviceEnable : 2; ///< 0: Disabled, <b>1: Enabled in PCI mode</b>, 2: Enabled in ACPI mode
+ UINT32 RsvdBits0 : 30; ///< Reserved bits
+} THERMAL_HOB;
+
+/**
+ This structure is used for the emulation feature for Port61h read. The port is trapped
+ and the SMI handler will toggle bit4 according to the handler's internal state.
+**/
+typedef struct {
+ UINT32 Enable : 1; ///< 0: Disable; <b>1: Enable</b> the emulation
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PORT61H_SMM_HOB;
+
+///
+/// The SCS_HOB block describes Storage and Communication Subsystem (SCS) settings for PCH.
+///
+typedef struct {
+ UINT32 ScsEmmcEnabled : 2; ///< Determine if eMMC is enabled - 0: Disabled, <b>1: Enabled</b>.
+ UINT32 ScsEmmcHs400Enabled : 1; ///< Determine eMMC HS400 Mode if ScsEmmcEnabled - <b>0: Disabled</b>, 1: Enabled
+ /**
+ Determine if HS400 Training is required, set to FALSE if Hs400 Data is valid. <b>0: Disabled</b>, 1: Enabled.
+ First Boot or CMOS clear, system boot with Default settings, set tuning required.
+ Subsequent Boots, Get Variable 'Hs400TuningData'
+ - if failed to get variable, set tuning required
+ - if passed, retrieve Hs400DataValid, Hs400RxStrobe1Dll and Hs400TxDataDll from variable. Set tuning not required.
+ **/
+ UINT32 ScsEmmcHs400TuningRequired : 1;
+ UINT32 ScsEmmcHs400DllDataValid : 1; ///< Set if HS400 Tuning Data Valid
+ UINT32 ScsEmmcHs400DriverStrength : 3; ///< I/O driver strength: <b>0 - 33 Ohm</b>, 1 - 40 Ohm, 2 - 50 Ohm
+ UINT32 RsvdBits : 24;
+
+} SCS_HOB;
+
+/**
+ The PCH_LOCK_DOWN_CONFIG block describes the expected configuration of the PCH
+ for security requirement.
+**/
+typedef struct {
+ UINT32 GlobalSmi : 1;
+ /**
+ <b>(Test)</b> Enable BIOS Interface Lock Down bit to prevent writes to the Backup Control Register
+ Top Swap bit and the General Control and Status Registers Boot BIOS Straps. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 BiosInterface : 1;
+ /**
+ <b>(Test)</b> Enable RTC lower and upper 128 byte Lock bits to lock Bytes 38h-3Fh in the upper
+ and lower 128-byte bank of RTC RAM. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 RtcLock : 1;
+ /**
+ Enable the BIOS Lock Enable (BLE) feature and set EISS bit (D31:F5:RegDCh[5])
+ for the BIOS region protection. When it is enabled, the BIOS Region can only be
+ modified from SMM after EndOfDxe protocol is installed.
+ Note: When BiosLock is enabled, platform code also needs to update to take care
+ of BIOS modification (including SetVariable) in DXE or runtime phase after
+ EndOfDxe protocol is installed. <b>0: Disable</b>; 1: Enable.
+ **/
+ UINT32 BiosLock : 1;
+ UINT32 RsvdBits : 28;
+} LOCK_DOWN_HOB;
+
+/**
+ The PM_HOB block describes expected miscellaneous power management settings.
+ The PowerResetStatusClear field would clear the Power/Reset status bits, please
+ set the bits if you want PCH Init driver to clear it, if you want to check the
+ status later then clear the bits.
+**/
+typedef struct {
+ /**
+ <b>(Test)</b>
+ When set to true, this bit disallows host reads to PMC XRAM.
+ BIOS must set this bit (to disable and lock the feature) prior to passing control to OS
+ 0:Disable, <b>1:Enable</b>
+ **/
+ UINT32 PmcReadDisable : 1;
+ UINT32 RsvdBits1 : 31;
+} PM_HOB;
+
+/**
+ This structure contains the HOB which are related to P2SB device.
+**/
+typedef struct {
+ /**
+ <b>(Test)</b>
+ This unlock the SBI lock bit to allow SBI after post time. <b>0: Disable</b>; 1: Enable.
+ NOTE: Do not set this policy "SbiUnlock" unless necessary.
+ **/
+ UINT32 SbiUnlock : 1;
+ /**
+ <b>(Test)</b>
+ The PSF registers will be locked before 3rd party code execution.
+ This policy unlock the PSF space. <b>0: Disable</b>; 1: Enable.
+ NOTE: Do not set this policy "SbAccessUnlock" unless necessary.
+ **/
+ UINT32 PsfUnlock : 1; //@deprecated
+ UINT32 SbAccessUnlock : 1;
+ UINT32 RsvdBits : 29;
+} P2SB_HOB;
+
+/**
+ This structure holds information about disabled USB2 and USB3 ports through Port Disable Override functionality
+**/
+typedef struct {
+ UINT32 DelayPdoProgramming : 1; ///< Flag informing about delaying PDO programming to DXE phase
+ UINT32 Usb2DisabledPorts : 16; ///< USB2 Disabled ports
+ UINT32 Usb3DisabledPorts : 10; ///< USB3 Disabled ports
+ UINT32 RsvdBits : 5;
+} USB_HOB;
+
+
+///
+/// Pch Config Hob
+///
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType; ///< GUID HOB type structure for gPchConfigHobGuid
+ GENERAL_HOB General; ///< Pch general HOB definition
+ INTERRUPT_HOB Interrupt; ///< Interrupt HOB definition
+ SERIAL_IO_HOB SerialIo; ///< Serial io HOB definition
+ PCIERP_HOB PcieRp; ///< PCIE root port HOB definition
+ THERMAL_HOB Thermal; ///< Thermal HOB definition
+ SCS_HOB Scs; ///< Scs HOB definition
+ CIO2_HOB Cio2; ///< CIO2 HOB definition
+ LOCK_DOWN_HOB LockDown; ///< Lock down HOB definition
+ PM_HOB Pm; ///< PM HOB definition
+ P2SB_HOB P2sb; ///< P2sb HOB definition
+ HDAUDIO_HOB HdAudio; ///< HD audio definition
+ SATA_HOB Sata; ///< SATA definition
+ PROTECTED_RANGE ProtectRange[PCH_FLASH_PROTECTED_RANGES];
+ PORT61H_SMM_HOB Port61hSmm;
+ SMBUS_HOB Smbus;
+ USB_HOB Usb;
+
+} PCH_CONFIG_HOB;
+#pragma pack (pop)
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchHdaEndpoints.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchHdaEndpoints.h
new file mode 100644
index 0000000000..97f7be6c11
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/PchHdaEndpoints.h
@@ -0,0 +1,129 @@
+/** @file
+ Header file for PchHdaLib Endpoint descriptors.
+
+Copyright (c) 2017, 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 that 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 _PCH_HDA_ENDPOINTS_H_
+#define _PCH_HDA_ENDPOINTS_H_
+
+#include <Library/DxePchHdaNhlt.h>
+
+typedef enum {
+ HdaDmicX1 = 0,
+ HdaDmicX2,
+ HdaDmicX4,
+ HdaBtRender,
+ HdaBtCapture,
+ HdaI2sRender1,
+ HdaI2sRender2,
+ HdaI2sCapture,
+ HdaEndpointMax
+} NHLT_ENDPOINT;
+
+typedef struct {
+ NHLT_ENDPOINT EndpointType;
+ UINT32 EndpointFormatsBitmask;
+ BOOLEAN Enable;
+} PCH_HDA_NHLT_ENDPOINTS;
+
+#define PCH_HDA_NHLT_TABLE_SIZE 0x2000
+
+// Format bitmask
+#define B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT BIT0
+#define B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT BIT1
+#define B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT BIT2
+#define B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT BIT3
+#define B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT BIT4
+#define B_HDA_BT_NARROWBAND_FORMAT BIT5
+#define B_HDA_BT_WIDEBAND_FORMAT BIT6
+#define B_HDA_BT_A2DP_FORMAT BIT7
+#define B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT BIT8
+#define B_HDA_I2S_RTK298_CAPTURE_4CH_48KHZ_24BIT_FORMAT BIT9
+#define B_HDA_I2S_RTK286S_2CH_48KHZ_24BIT_FORMAT BIT10
+#define B_HDA_I2S_ADI_4CH_48KHZ_32BIT_FORMAT BIT11
+#define B_HDA_I2S_48KHZ_24BIT_MASTER_FORMAT BIT12
+#define B_HDA_I2S_48KHZ_24BIT_SLAVE_FORMAT BIT13
+#define B_HDA_I2S_PCM_8KHZ_16BIT_MASTER_FORMAT BIT14
+#define B_HDA_I2S_PCM_8KHZ_16BIT_SLAVE_FORMAT BIT15
+#define V_HDA_FORMAT_MAX 16
+
+// Formats
+extern CONST WAVEFORMATEXTENSIBLE Ch1_48kHz16bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE Ch2_48kHz16bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE Ch2_48kHz24bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE Ch2_48kHz32bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE Ch4_48kHz16bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE Ch4_48kHz32bitFormat;
+extern CONST WAVEFORMATEXTENSIBLE NarrowbandFormat;
+extern CONST WAVEFORMATEXTENSIBLE WidebandFormat;
+extern CONST WAVEFORMATEXTENSIBLE A2dpFormat;
+
+// Format Config
+extern CONST UINT32 DmicStereo16BitFormatConfig[];
+extern CONST UINT32 DmicStereo16BitFormatConfigSize;
+extern CONST UINT32 DmicStereo32BitFormatConfig[];
+extern CONST UINT32 DmicStereo32BitFormatConfigSize;
+extern CONST UINT32 DmicQuad16BitFormatConfig[];
+extern CONST UINT32 DmicQuad16BitFormatConfigSize;
+extern CONST UINT32 DmicQuad32BitFormatConfig[];
+extern CONST UINT32 DmicQuad32BitFormatConfigSize;
+extern CONST UINT32 DmicMono16BitFormatConfig[];
+extern CONST UINT32 DmicMono16BitFormatConfigSize;
+extern CONST UINT32 I2sRtk298Render4ch48kHz24bitFormatConfig[];
+extern CONST UINT32 I2sRtk298Render4ch48kHz24bitFormatConfigSize;
+extern CONST UINT32 I2sRtk298Capture4ch48kHz24bitFormatConfig[];
+extern CONST UINT32 I2sRtk298Capture4ch48kHz24bitFormatConfigSize;
+extern CONST UINT32 I2sRtk286S2ch48kHzFormatConfig[];
+extern CONST UINT32 I2sRtk286S2ch48kHzFormatConfigSize;
+extern CONST UINT32 I2sAdi4ch48kHzFormatConfig[];
+extern CONST UINT32 I2sAdi4ch48kHzFormatConfigSize;
+extern CONST UINT32 I2s48kHz24bitMasterFormatConfig[];
+extern CONST UINT32 I2s48kHz24bitMasterFormatConfigSize;
+extern CONST UINT32 I2s48kHz24bitSlaveFormatConfig[];
+extern CONST UINT32 I2s48kHz24bitSlaveFormatConfigSize;
+extern CONST UINT32 I2sPcm8kHz16bitMasterFormatConfig[];
+extern CONST UINT32 I2sPcm8kHz16bitMasterFormatConfigSize;
+extern CONST UINT32 I2sPcm8kHz16bitSlaveFormatConfig[];
+extern CONST UINT32 I2sPcm8kHz16bitSlaveFormatConfigSize;
+extern CONST UINT32 BtFormatConfig[];
+extern CONST UINT32 BtFormatConfigSize;
+
+// Endpoints
+extern ENDPOINT_DESCRIPTOR HdaEndpointDmicX1;
+extern ENDPOINT_DESCRIPTOR HdaEndpointDmicX2;
+extern ENDPOINT_DESCRIPTOR HdaEndpointDmicX4;
+extern ENDPOINT_DESCRIPTOR HdaEndpointBtRender;
+extern ENDPOINT_DESCRIPTOR HdaEndpointBtCapture;
+extern ENDPOINT_DESCRIPTOR HdaEndpointI2sRender;
+extern ENDPOINT_DESCRIPTOR HdaEndpointI2sCapture;
+
+// Endpoint Config
+extern CONST UINT8 DmicX1Config[];
+extern CONST UINT32 DmicX1ConfigSize;
+extern CONST UINT8 DmicX2Config[];
+extern CONST UINT32 DmicX2ConfigSize;
+extern CONST UINT8 DmicX4Config[];
+extern CONST UINT32 DmicX4ConfigSize;
+extern CONST UINT8 BtConfig[];
+extern CONST UINT32 BtConfigSize;
+extern CONST UINT8 I2sRender1Config[];
+extern CONST UINT32 I2sRender1ConfigSize;
+extern CONST UINT8 I2sRender2Config[];
+extern CONST UINT32 I2sRender2ConfigSize;
+extern CONST UINT8 I2sCaptureConfig[];
+extern CONST UINT32 I2sCaptureConfigSize;
+
+// Oed Configuration
+extern CONST UINT32 NhltConfiguration[];
+extern CONST UINT32 NhltConfigurationSize;
+
+#endif // _PCH_HDA_ENDPOINTS_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvs.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvs.h
new file mode 100644
index 0000000000..ac288a56d0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvs.h
@@ -0,0 +1,33 @@
+/** @file
+ This file defines the PCH NVS Protocol.
+
+Copyright (c) 2017, 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 that 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 _PCH_NVS_H_
+#define _PCH_NVS_H_
+
+#include "PchNvsArea.h"
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchNvsAreaProtocolGuid;
+
+/**
+ This protocol is used to sync PCH information from POST to runtime ASL.
+ This protocol exposes the pointer of PCH NVS Area only. Please refer to
+ ASL definition for PCH NVS AREA.
+**/
+typedef struct {
+ PCH_NVS_AREA *Area;
+} PCH_NVS_AREA_PROTOCOL;
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h
new file mode 100644
index 0000000000..66c119f577
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h
@@ -0,0 +1,243 @@
+/**@file
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+ //
+ // Define PCH NVS Area operatino region.
+ //
+
+#ifndef _PCH_NVS_AREA_H_
+#define _PCH_NVS_AREA_H_
+
+#pragma pack (push,1)
+typedef struct {
+ UINT16 PchSeries; ///< Offset 0 PCH Series
+ UINT16 PchGeneration; ///< Offset 2 PCH Generation
+ UINT32 RpAddress[24]; ///< Offset 4 Root Port address 1
+ ///< Offset 8 Root Port address 2
+ ///< Offset 12 Root Port address 3
+ ///< Offset 16 Root Port address 4
+ ///< Offset 20 Root Port address 5
+ ///< Offset 24 Root Port address 6
+ ///< Offset 28 Root Port address 7
+ ///< Offset 32 Root Port address 8
+ ///< Offset 36 Root Port address 9
+ ///< Offset 40 Root Port address 10
+ ///< Offset 44 Root Port address 11
+ ///< Offset 48 Root Port address 12
+ ///< Offset 52 Root Port address 13
+ ///< Offset 56 Root Port address 14
+ ///< Offset 60 Root Port address 15
+ ///< Offset 64 Root Port address 16
+ ///< Offset 68 Root Port address 17
+ ///< Offset 72 Root Port address 18
+ ///< Offset 76 Root Port address 19
+ ///< Offset 80 Root Port address 20
+ ///< Offset 84 Root Port address 21
+ ///< Offset 88 Root Port address 22
+ ///< Offset 92 Root Port address 23
+ ///< Offset 96 Root Port address 24
+ UINT64 NHLA; ///< Offset 100 HD-Audio NHLT ACPI address
+ UINT32 NHLL; ///< Offset 108 HD-Audio NHLT ACPI length
+ UINT32 ADFM; ///< Offset 112 HD-Audio DSP Feature Mask
+ UINT32 SBRG; ///< Offset 116 SBREG_BAR
+ UINT32 GPEM; ///< Offset 120 GPP_X to GPE_DWX mapping
+ UINT32 GP2T[10]; ///< Offset 124 GPE 2-tier level edged enabled Gpio pads (Group Index 0)
+ ///< Offset 128 GPE 2-tier level edged enabled Gpio pads (Group Index 1)
+ ///< Offset 132 GPE 2-tier level edged enabled Gpio pads (Group Index 2)
+ ///< Offset 136 GPE 2-tier level edged enabled Gpio pads (Group Index 3)
+ ///< Offset 140 GPE 2-tier level edged enabled Gpio pads (Group Index 4)
+ ///< Offset 144 GPE 2-tier level edged enabled Gpio pads (Group Index 5)
+ ///< Offset 148 GPE 2-tier level edged enabled Gpio pads (Group Index 6)
+ ///< Offset 152 GPE 2-tier level edged enabled Gpio pads (Group Index 7)
+ ///< Offset 156 GPE 2-tier level edged enabled Gpio pads (Group Index 8)
+ ///< Offset 160 GPE 2-tier level edged enabled Gpio pads (Group Index 9)
+ UINT16 PcieLtrMaxSnoopLatency[24]; ///< Offset 164 PCIE LTR max snoop Latency 1
+ ///< Offset 166 PCIE LTR max snoop Latency 2
+ ///< Offset 168 PCIE LTR max snoop Latency 3
+ ///< Offset 170 PCIE LTR max snoop Latency 4
+ ///< Offset 172 PCIE LTR max snoop Latency 5
+ ///< Offset 174 PCIE LTR max snoop Latency 6
+ ///< Offset 176 PCIE LTR max snoop Latency 7
+ ///< Offset 178 PCIE LTR max snoop Latency 8
+ ///< Offset 180 PCIE LTR max snoop Latency 9
+ ///< Offset 182 PCIE LTR max snoop Latency 10
+ ///< Offset 184 PCIE LTR max snoop Latency 11
+ ///< Offset 186 PCIE LTR max snoop Latency 12
+ ///< Offset 188 PCIE LTR max snoop Latency 13
+ ///< Offset 190 PCIE LTR max snoop Latency 14
+ ///< Offset 192 PCIE LTR max snoop Latency 15
+ ///< Offset 194 PCIE LTR max snoop Latency 16
+ ///< Offset 196 PCIE LTR max snoop Latency 17
+ ///< Offset 198 PCIE LTR max snoop Latency 18
+ ///< Offset 200 PCIE LTR max snoop Latency 19
+ ///< Offset 202 PCIE LTR max snoop Latency 20
+ ///< Offset 204 PCIE LTR max snoop Latency 21
+ ///< Offset 206 PCIE LTR max snoop Latency 22
+ ///< Offset 208 PCIE LTR max snoop Latency 23
+ ///< Offset 210 PCIE LTR max snoop Latency 24
+ UINT16 PcieLtrMaxNoSnoopLatency[24]; ///< Offset 212 PCIE LTR max no snoop Latency 1
+ ///< Offset 214 PCIE LTR max no snoop Latency 2
+ ///< Offset 216 PCIE LTR max no snoop Latency 3
+ ///< Offset 218 PCIE LTR max no snoop Latency 4
+ ///< Offset 220 PCIE LTR max no snoop Latency 5
+ ///< Offset 222 PCIE LTR max no snoop Latency 6
+ ///< Offset 224 PCIE LTR max no snoop Latency 7
+ ///< Offset 226 PCIE LTR max no snoop Latency 8
+ ///< Offset 228 PCIE LTR max no snoop Latency 9
+ ///< Offset 230 PCIE LTR max no snoop Latency 10
+ ///< Offset 232 PCIE LTR max no snoop Latency 11
+ ///< Offset 234 PCIE LTR max no snoop Latency 12
+ ///< Offset 236 PCIE LTR max no snoop Latency 13
+ ///< Offset 238 PCIE LTR max no snoop Latency 14
+ ///< Offset 240 PCIE LTR max no snoop Latency 15
+ ///< Offset 242 PCIE LTR max no snoop Latency 16
+ ///< Offset 244 PCIE LTR max no snoop Latency 17
+ ///< Offset 246 PCIE LTR max no snoop Latency 18
+ ///< Offset 248 PCIE LTR max no snoop Latency 19
+ ///< Offset 250 PCIE LTR max no snoop Latency 20
+ ///< Offset 252 PCIE LTR max no snoop Latency 21
+ ///< Offset 254 PCIE LTR max no snoop Latency 22
+ ///< Offset 256 PCIE LTR max no snoop Latency 23
+ ///< Offset 258 PCIE LTR max no snoop Latency 24
+ UINT32 SerialIoDebugUart0Bar0; ///< Offset 260 SerialIo Hidden UART0 BAR 0
+ UINT32 SerialIoDebugUart1Bar0; ///< Offset 264 SerialIo Hidden UART1 BAR 0
+ UINT8 XHPC; ///< Offset 268 Number of HighSpeed ports implemented in XHCI controller
+ UINT8 XRPC; ///< Offset 269 Number of USBR ports implemented in XHCI controller
+ UINT8 XSPC; ///< Offset 270 Number of SuperSpeed ports implemented in XHCI controller
+ UINT8 XSPA; ///< Offset 271 Address of 1st SuperSpeed port
+ UINT32 HPTB; ///< Offset 272 HPET base address
+ UINT8 HPTE; ///< Offset 276 HPET enable
+ //SerialIo block
+ UINT8 SMD[11]; ///< Offset 277 SerialIo controller 0 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 278 SerialIo controller 1 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 279 SerialIo controller 2 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 280 SerialIo controller 3 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 281 SerialIo controller 4 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 282 SerialIo controller 5 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 283 SerialIo controller 6 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 284 SerialIo controller 7 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 285 SerialIo controller 8 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 286 SerialIo controller 9 mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ ///< Offset 287 SerialIo controller A mode (0: disabled, 1: pci, 2: acpi, 3: debug port)
+ UINT8 SIR[11]; ///< Offset 288 SerialIo controller 0 irq number
+ ///< Offset 289 SerialIo controller 1 irq number
+ ///< Offset 290 SerialIo controller 2 irq number
+ ///< Offset 291 SerialIo controller 3 irq number
+ ///< Offset 292 SerialIo controller 4 irq number
+ ///< Offset 293 SerialIo controller 5 irq number
+ ///< Offset 294 SerialIo controller 6 irq number
+ ///< Offset 295 SerialIo controller 7 irq number
+ ///< Offset 296 SerialIo controller 8 irq number
+ ///< Offset 297 SerialIo controller 9 irq number
+ ///< Offset 298 SerialIo controller A irq number
+ UINT64 SB0[11]; ///< Offset 299 SerialIo controller 0 BAR0
+ ///< Offset 307 SerialIo controller 1 BAR0
+ ///< Offset 315 SerialIo controller 2 BAR0
+ ///< Offset 323 SerialIo controller 3 BAR0
+ ///< Offset 331 SerialIo controller 4 BAR0
+ ///< Offset 339 SerialIo controller 5 BAR0
+ ///< Offset 347 SerialIo controller 6 BAR0
+ ///< Offset 355 SerialIo controller 7 BAR0
+ ///< Offset 363 SerialIo controller 8 BAR0
+ ///< Offset 371 SerialIo controller 9 BAR0
+ ///< Offset 379 SerialIo controller A BAR0
+ UINT64 SB1[11]; ///< Offset 387 SerialIo controller 0 BAR1
+ ///< Offset 395 SerialIo controller 1 BAR1
+ ///< Offset 403 SerialIo controller 2 BAR1
+ ///< Offset 411 SerialIo controller 3 BAR1
+ ///< Offset 419 SerialIo controller 4 BAR1
+ ///< Offset 427 SerialIo controller 5 BAR1
+ ///< Offset 435 SerialIo controller 6 BAR1
+ ///< Offset 443 SerialIo controller 7 BAR1
+ ///< Offset 451 SerialIo controller 8 BAR1
+ ///< Offset 459 SerialIo controller 9 BAR1
+ ///< Offset 467 SerialIo controller A BAR1
+ //end of SerialIo block
+ UINT8 GPEN; ///< Offset 475 GPIO enabled
+ UINT8 SGIR; ///< Offset 476 GPIO IRQ
+ UINT8 RstPcieStorageInterfaceType[3]; ///< Offset 477 RST PCIe Storage Cycle Router#1 Interface Type
+ ///< Offset 478 RST PCIe Storage Cycle Router#2 Interface Type
+ ///< Offset 479 RST PCIe Storage Cycle Router#3 Interface Type
+ UINT8 RstPcieStoragePmCapPtr[3]; ///< Offset 480 RST PCIe Storage Cycle Router#1 Power Management Capability Pointer
+ ///< Offset 481 RST PCIe Storage Cycle Router#2 Power Management Capability Pointer
+ ///< Offset 482 RST PCIe Storage Cycle Router#3 Power Management Capability Pointer
+ UINT8 RstPcieStoragePcieCapPtr[3]; ///< Offset 483 RST PCIe Storage Cycle Router#1 PCIe Capabilities Pointer
+ ///< Offset 484 RST PCIe Storage Cycle Router#2 PCIe Capabilities Pointer
+ ///< Offset 485 RST PCIe Storage Cycle Router#3 PCIe Capabilities Pointer
+ UINT16 RstPcieStorageL1ssCapPtr[3]; ///< Offset 486 RST PCIe Storage Cycle Router#1 L1SS Capability Pointer
+ ///< Offset 488 RST PCIe Storage Cycle Router#2 L1SS Capability Pointer
+ ///< Offset 490 RST PCIe Storage Cycle Router#3 L1SS Capability Pointer
+ UINT8 RstPcieStorageEpL1ssControl2[3]; ///< Offset 492 RST PCIe Storage Cycle Router#1 Endpoint L1SS Control Data2
+ ///< Offset 493 RST PCIe Storage Cycle Router#2 Endpoint L1SS Control Data2
+ ///< Offset 494 RST PCIe Storage Cycle Router#3 Endpoint L1SS Control Data2
+ UINT32 RstPcieStorageEpL1ssControl1[3]; ///< Offset 495 RST PCIe Storage Cycle Router#1 Endpoint L1SS Control Data1
+ ///< Offset 499 RST PCIe Storage Cycle Router#2 Endpoint L1SS Control Data1
+ ///< Offset 503 RST PCIe Storage Cycle Router#3 Endpoint L1SS Control Data1
+ UINT16 RstPcieStorageLtrCapPtr[3]; ///< Offset 507 RST PCIe Storage Cycle Router#1 LTR Capability Pointer
+ ///< Offset 509 RST PCIe Storage Cycle Router#2 LTR Capability Pointer
+ ///< Offset 511 RST PCIe Storage Cycle Router#3 LTR Capability Pointer
+ UINT32 RstPcieStorageEpLtrData[3]; ///< Offset 513 RST PCIe Storage Cycle Router#1 Endpoint LTR Data
+ ///< Offset 517 RST PCIe Storage Cycle Router#2 Endpoint LTR Data
+ ///< Offset 521 RST PCIe Storage Cycle Router#3 Endpoint LTR Data
+ UINT16 RstPcieStorageEpLctlData16[3]; ///< Offset 525 RST PCIe Storage Cycle Router#1 Endpoint LCTL Data
+ ///< Offset 527 RST PCIe Storage Cycle Router#2 Endpoint LCTL Data
+ ///< Offset 529 RST PCIe Storage Cycle Router#3 Endpoint LCTL Data
+ UINT16 RstPcieStorageEpDctlData16[3]; ///< Offset 531 RST PCIe Storage Cycle Router#1 Endpoint DCTL Data
+ ///< Offset 533 RST PCIe Storage Cycle Router#2 Endpoint DCTL Data
+ ///< Offset 535 RST PCIe Storage Cycle Router#3 Endpoint DCTL Data
+ UINT16 RstPcieStorageEpDctl2Data16[3]; ///< Offset 537 RST PCIe Storage Cycle Router#1 Endpoint DCTL2 Data
+ ///< Offset 539 RST PCIe Storage Cycle Router#2 Endpoint DCTL2 Data
+ ///< Offset 541 RST PCIe Storage Cycle Router#3 Endpoint DCTL2 Data
+ UINT16 RstPcieStorageRpDctl2Data16[3]; ///< Offset 543 RST PCIe Storage Cycle Router#1 RootPort DCTL2 Data
+ ///< Offset 545 RST PCIe Storage Cycle Router#2 RootPort DCTL2 Data
+ ///< Offset 547 RST PCIe Storage Cycle Router#3 RootPort DCTL2 Data
+ UINT32 RstPcieStorageUniqueTableBar[3]; ///< Offset 549 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X Table BAR
+ ///< Offset 553 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X Table BAR
+ ///< Offset 557 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X Table BAR
+ UINT32 RstPcieStorageUniqueTableBarValue[3]; ///< Offset 561 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X Table BAR value
+ ///< Offset 565 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X Table BAR value
+ ///< Offset 569 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X Table BAR value
+ UINT32 RstPcieStorageUniquePbaBar[3]; ///< Offset 573 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X PBA BAR
+ ///< Offset 577 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X PBA BAR
+ ///< Offset 581 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X PBA BAR
+ UINT32 RstPcieStorageUniquePbaBarValue[3]; ///< Offset 585 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X PBA BAR value
+ ///< Offset 589 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X PBA BAR value
+ ///< Offset 593 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X PBA BAR value
+ UINT32 RstPcieStorageRootPortNum[3]; ///< Offset 597 RST PCIe Storage Cycle Router#1 Root Port number
+ ///< Offset 601 RST PCIe Storage Cycle Router#2 Root Port number
+ ///< Offset 605 RST PCIe Storage Cycle Router#3 Root Port number
+ UINT8 ExitBootServicesFlag; ///< Offset 609 Flag indicating Exit Boot Service, to inform SMM
+ UINT32 SxMemBase; ///< Offset 610 Sx handler reserved MMIO base
+ UINT32 SxMemSize; ///< Offset 614 Sx handler reserved MMIO size
+ UINT8 Cio2EnabledAsAcpiDevice; ///< Offset 618 Cio2 Device Enabled as ACPI device
+ UINT8 Cio2IrqNumber; ///< Offset 619 Cio2 Interrupt Number
+ UINT8 ThermalDeviceAcpiEnabled; ///< Offset 620 Thermal Device Acpi mode enabled
+ UINT8 ThermalDeviceInterruptLine; ///< Offset 621 Thermal Device IRQ number
+ UINT32 XhciRsvdMemBase; ///< Offset 622 XHCI memory base address
+ UINT8 EMH4; ///< Offset 626 eMMC HS400 mode enabled
+ UINT8 EMDS; ///< Offset 627 eMMC Driver Strength
+ UINT8 CpuSku; ///< Offset 628 CPU SKU
+ UINT16 IoTrapAddress[4]; ///< Offset 629
+ ///< Offset 631
+ ///< Offset 633
+ ///< Offset 635
+ UINT8 IoTrapStatus[4]; ///< Offset 637
+ ///< Offset 638
+ ///< Offset 639
+ ///< Offset 640
+ UINT16 PMBS; ///< Offset 641 ACPI IO BASE address
+ UINT32 PWRM; ///< Offset 643 PWRM MEM BASE address
+} PCH_NVS_AREA;
+
+#pragma pack(pop)
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h
new file mode 100644
index 0000000000..26d13b7a7d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h
@@ -0,0 +1,42 @@
+/** @file
+ This file defines the PCH PCIE IoTrap Protocol.
+
+Copyright (c) 2017, 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 that 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 _PCH_PCIE_IOTRAP_H_
+#define _PCH_PCIE_IOTRAP_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchPcieIoTrapProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_PCIE_IOTRAP_PROTOCOL PCH_PCIE_IOTRAP_PROTOCOL;
+
+///
+/// Pcie Trap valid types
+///
+typedef enum {
+ PciePmTrap,
+ PcieTrapTypeMaximum
+} PCH_PCIE_TRAP_TYPE;
+
+/**
+ This protocol is used to provide the IoTrap address to trigger PCH PCIE call back events
+**/
+struct _PCH_PCIE_IOTRAP_PROTOCOL {
+ UINT16 PcieTrapAddress;
+};
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
new file mode 100644
index 0000000000..ec1a69e4de
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
@@ -0,0 +1,161 @@
+/** @file
+ System reset library services.
+
+Copyright (c) 2017, 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 that 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 <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <PchAccess.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mBaseResetSystemABase;
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_HARDRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ UINT16 ABase;
+ UINT32 Data32;
+
+ ABase = mBaseResetSystemABase;
+ if (ABase == 0) {
+ PchAcpiBaseGet (&ABase);
+ }
+ ///
+ /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system from S5
+ ///
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_GPE0_EN_127_96), 0);
+
+ ///
+ /// Secondly, PwrSts register must be cleared
+ ///
+ /// Write a "1" to bit[8] of power button status register at
+ /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
+ ///
+ IoWrite16 ((UINTN) (ABase + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_PWRBTN);
+
+ ///
+ /// Finally, transform system into S5 sleep state
+ ///
+ Data32 = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT));
+
+ Data32 = (UINT32) ((Data32 &~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S5);
+
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ return;
+}
+
+/**
+ Calling this function causes the system to enter a power state for platform specific.
+
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library instance.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+**/
+EFI_STATUS
+EFIAPI
+BaseResetSystemLibConstructor (
+ VOID
+ )
+{
+ PchAcpiBaseGet (&mBaseResetSystemABase);
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
new file mode 100644
index 0000000000..2af43b5091
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = BaseResetSystemLib
+FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+CONSTRUCTOR = BaseResetSystemLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+PciLib
+BaseLib
+DebugLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseResetSystemLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.c
new file mode 100644
index 0000000000..17e42dfd0b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.c
@@ -0,0 +1,996 @@
+/** @file
+ PCH SMBUS library implementation built upon I/O library.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Library/SmbusLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/DebugLib.h>
+#include <PchAccess.h>
+#include <Library/MmPciLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mSmbusIoBase = 0;
+
+/**
+ Gets Io port base address of Smbus Host Controller.
+
+ @retval The Io port base address of Smbus host controller.
+
+**/
+UINT16
+InternalGetSmbusIoPortBaseAddress (
+ VOID
+ )
+{
+ UINTN SmbusPciBase;
+ UINT16 IoPortBaseAddress;
+
+ if (mSmbusIoBase != 0) {
+ return mSmbusIoBase;
+ }
+
+ SmbusPciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+ IoPortBaseAddress = (UINT16) MmioRead32 (SmbusPciBase + R_PCH_SMBUS_BASE);
+
+ //
+ // Make sure that the IO port base address has been properly set.
+ //
+ if ((IoPortBaseAddress == 0) || (IoPortBaseAddress == 0xFFFF)) {
+ ASSERT (FALSE);
+ return 0;
+ }
+
+ IoPortBaseAddress &= B_PCH_SMBUS_BASE_BAR;
+ mSmbusIoBase = IoPortBaseAddress;
+
+ return IoPortBaseAddress;
+}
+
+
+/**
+ Acquires the ownership of SMBUS.
+
+ This internal function reads the host state register.
+ If the SMBUS is not available, RETURN_TIMEOUT is returned;
+ Otherwise, it performs some basic initializations and returns
+ RETURN_SUCCESS.
+
+ @param[in] IoPortBaseAddress The Io port base address of Smbus Host controller.
+
+ @retval RETURN_SUCCESS The SMBUS command was executed successfully.
+ @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command.
+
+**/
+RETURN_STATUS
+InternalSmBusAcquire (
+ IN UINT16 IoPortBaseAddress
+ )
+{
+ UINT8 HostStatus;
+
+ HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS);
+ if ((HostStatus & B_PCH_SMBUS_IUS) != 0) {
+ return RETURN_TIMEOUT;
+ } else if ((HostStatus & B_PCH_SMBUS_HBSY) != 0) {
+ //
+ // Clear host status register and exit.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ return RETURN_TIMEOUT;
+ }
+ //
+ // Clear out any odd status information (Will Not Clear In Use).
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, HostStatus);
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Starts the SMBUS transaction and waits until the end.
+
+ This internal function start the SMBUS transaction and waits until the transaction
+ of SMBUS is over by polling the INTR bit of Host status register.
+ If the SMBUS is not available, RETURN_TIMEOUT is returned;
+ Otherwise, it performs some basic initializations and returns
+ RETURN_SUCCESS.
+
+ @param[in] IoPortBaseAddress The Io port base address of Smbus Host controller.
+ @param[in] HostControl The Host control command to start SMBUS transaction.
+
+ @retval RETURN_SUCCESS The SMBUS command was executed successfully.
+ @retval RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect).
+ @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected
+ in the Host Status Register bit. Device errors are
+ a result of a transaction collision, illegal command field,
+ unclaimed cycle (host initiated), or bus errors (collisions).
+
+**/
+RETURN_STATUS
+InternalSmBusStart (
+ IN UINT16 IoPortBaseAddress,
+ IN UINT8 HostControl
+ )
+{
+ UINT8 HostStatus;
+ UINT8 AuxiliaryStatus;
+
+ //
+ // Set Host Control Register (Initiate Operation, Interrupt disabled).
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL, (UINT8)(HostControl + B_PCH_SMBUS_START));
+
+ do {
+ //
+ // Poll INTR bit of Host Status Register.
+ //
+ HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS);
+ } while ((HostStatus & (B_PCH_SMBUS_INTR | B_PCH_SMBUS_ERROR | B_PCH_SMBUS_BYTE_DONE_STS)) == 0);
+
+ if ((HostStatus & B_PCH_SMBUS_ERROR) == 0) {
+ return RETURN_SUCCESS;
+ }
+ //
+ // Clear error bits of Host Status Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_ERROR);
+ //
+ // Read Auxiliary Status Register to judge CRC error.
+ //
+ AuxiliaryStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS);
+ if ((AuxiliaryStatus & B_PCH_SMBUS_CRCE) != 0) {
+ return RETURN_CRC_ERROR;
+ }
+
+ return RETURN_DEVICE_ERROR;
+}
+
+/**
+ Executes an SMBUS quick, byte or word command.
+
+ This internal function executes an SMBUS quick, byte or word commond.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+
+ @param[in] HostControl The value of Host Control Register to set.
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] Value The byte/word write to the SMBUS.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The byte/word read from the SMBUS.
+
+**/
+UINT16
+InternalSmBusNonBlock (
+ IN UINT8 HostControl,
+ IN UINTN SmBusAddress,
+ IN UINT16 Value,
+ OUT RETURN_STATUS *Status
+ )
+{
+ RETURN_STATUS ReturnStatus;
+ UINT16 IoPortBaseAddress;
+ UINT8 AuxiliaryControl;
+
+ IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
+
+ //
+ // Try to acquire the ownership of SMBUS.
+ //
+ ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
+ if (RETURN_ERROR (ReturnStatus)) {
+ goto Done;
+ }
+ //
+ // Set the appropriate Host Control Register and auxiliary Control Register.
+ //
+ AuxiliaryControl = 0;
+ if (SMBUS_LIB_PEC (SmBusAddress)) {
+ AuxiliaryControl |= B_PCH_SMBUS_AAC;
+ HostControl |= B_PCH_SMBUS_PEC_EN;
+ }
+ //
+ // Set Host Commond Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
+ //
+ // Write value to Host Data 0 and Host Data 1 Registers.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) Value);
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD1, (UINT8) (Value >> 8));
+ //
+ // Set Auxiliary Control Regiester.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl);
+ //
+ // Set SMBUS slave address for the device to send/receive from.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_TSA, (UINT8) SmBusAddress);
+ //
+ // Start the SMBUS transaction and wait for the end.
+ //
+ ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
+ //
+ // Read value from Host Data 0 and Host Data 1 Registers.
+ //
+ Value = (UINT16)(IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD1) << 8);
+ Value = (UINT16)(Value | IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0));
+ //
+ // Clear Host Status Register and Auxiliary Status Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
+
+Done:
+ if (Status != NULL) {
+ *Status = ReturnStatus;
+ }
+
+ return Value;
+}
+
+/**
+ Executes an SMBUS quick read command.
+
+ Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address field of SmBusAddress is required.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If PEC is set in SmBusAddress, then ASSERT().
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+**/
+VOID
+EFIAPI
+SmBusQuickRead (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if (SMBUS_LIB_PEC (SmBusAddress) ||
+ (SMBUS_LIB_COMMAND (SmBusAddress) != 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return;
+ }
+
+ InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_QUICK,
+ SmBusAddress | B_PCH_SMBUS_READ,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS quick write command.
+
+ Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address field of SmBusAddress is required.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If PEC is set in SmBusAddress, then ASSERT().
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+**/
+VOID
+EFIAPI
+SmBusQuickWrite (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if (SMBUS_LIB_PEC (SmBusAddress) ||
+ (SMBUS_LIB_COMMAND (SmBusAddress) != 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return;
+ }
+
+ InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_QUICK,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS receive byte command.
+
+ Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address field of SmBusAddress is required.
+ The byte received from the SMBUS is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The byte received from the SMBUS.
+
+**/
+UINT8
+EFIAPI
+SmBusReceiveByte (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_COMMAND (SmBusAddress) != 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_BYTE,
+ SmBusAddress | B_PCH_SMBUS_READ,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS send byte command.
+
+ Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress.
+ The byte specified by Value is sent.
+ Only the SMBUS slave address field of SmBusAddress is required. Value is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Command in SmBusAddress is not zero, then ASSERT().
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] Value The 8-bit value to send.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The parameter of Value.
+
+**/
+UINT8
+EFIAPI
+SmBusSendByte (
+ IN UINTN SmBusAddress,
+ IN UINT8 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_COMMAND (SmBusAddress) != 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_BYTE,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ Value,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS read data byte command.
+
+ Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ The 8-bit value read from the SMBUS is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The byte read from the SMBUS.
+
+**/
+UINT8
+EFIAPI
+SmBusReadDataByte (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_BYTE_DATA,
+ SmBusAddress | B_PCH_SMBUS_READ,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS write data byte command.
+
+ Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress.
+ The 8-bit value specified by Value is written.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ Value is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] Value The 8-bit value to write.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The parameter of Value.
+
+**/
+UINT8
+EFIAPI
+SmBusWriteDataByte (
+ IN UINTN SmBusAddress,
+ IN UINT8 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return (UINT8) InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_BYTE_DATA,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ Value,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS read data word command.
+
+ Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ The 16-bit value read from the SMBUS is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The byte read from the SMBUS.
+
+**/
+UINT16
+EFIAPI
+SmBusReadDataWord (
+ IN UINTN SmBusAddress,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_WORD_DATA,
+ SmBusAddress | B_PCH_SMBUS_READ,
+ 0,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS write data word command.
+
+ Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress.
+ The 16-bit value specified by Value is written.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ Value is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] Value The 16-bit value to write.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The parameter of Value.
+
+**/
+UINT16
+EFIAPI
+SmBusWriteDataWord (
+ IN UINTN SmBusAddress,
+ IN UINT16 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_WORD_DATA,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ Value,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS process call command.
+
+ Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress.
+ The 16-bit value specified by Value is written.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ The 16-bit value returned by the process call command is returned.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] Value The 16-bit value to write.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The 16-bit value returned by the process call command.
+
+**/
+UINT16
+EFIAPI
+SmBusProcessCall (
+ IN UINTN SmBusAddress,
+ IN UINT16 Value,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusNonBlock (
+ V_PCH_SMBUS_SMB_CMD_PROCESS_CALL,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ Value,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS block command.
+
+ Executes an SMBUS block read, block write and block write-block read command
+ on the SMBUS device specified by SmBusAddress.
+ Bytes are read from the SMBUS and stored in Buffer.
+ The number of bytes read is returned, and will never return a value larger than 32-bytes.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+ SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
+
+ @param[in] HostControl The value of Host Control Register to set.
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] WriteBuffer Pointer to the buffer of bytes to write to the SMBUS.
+ @param[out] ReadBuffer Pointer to the buffer of bytes to read from the SMBUS.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The number of bytes read from the SMBUS.
+
+**/
+UINTN
+InternalSmBusBlock (
+ IN UINT8 HostControl,
+ IN UINTN SmBusAddress,
+ IN UINT8 *WriteBuffer,
+ OUT UINT8 *ReadBuffer,
+ OUT RETURN_STATUS *Status
+ )
+{
+ RETURN_STATUS ReturnStatus;
+ UINTN Index;
+ UINTN BytesCount;
+ UINT16 IoPortBaseAddress;
+ UINT8 AuxiliaryControl;
+
+ IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
+
+ BytesCount = SMBUS_LIB_LENGTH (SmBusAddress);
+
+ //
+ // Try to acquire the ownership of SMBUS.
+ //
+ ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
+ if (RETURN_ERROR (ReturnStatus)) {
+ goto Done;
+ }
+ //
+ // Set the appropriate Host Control Register and auxiliary Control Register.
+ //
+ AuxiliaryControl = B_PCH_SMBUS_E32B;
+ if (SMBUS_LIB_PEC (SmBusAddress)) {
+ AuxiliaryControl |= B_PCH_SMBUS_AAC;
+ HostControl |= B_PCH_SMBUS_PEC_EN;
+ }
+ //
+ // Set Host Command Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
+ //
+ // Set Auxiliary Control Regiester.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl);
+ //
+ // Clear byte pointer of 32-byte buffer.
+ //
+ IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL);
+
+ if (WriteBuffer != NULL) {
+ //
+ // Write the number of block to Host Block Data Byte Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) BytesCount);
+ //
+ // Write data block to Host Block Data Register.
+ //
+ for (Index = 0; Index < BytesCount; Index++) {
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HBD, WriteBuffer[Index]);
+ }
+ }
+ //
+ // Set SMBUS slave address for the device to send/receive from.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_TSA, (UINT8) SmBusAddress);
+ //
+ // Start the SMBUS transaction and wait for the end.
+ //
+ ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
+ if (RETURN_ERROR (ReturnStatus)) {
+ goto Done;
+ }
+
+ if (ReadBuffer != NULL) {
+ //
+ // Read the number of block from host block data byte register.
+ //
+ BytesCount = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0);
+ //
+ // Write data block from Host Block Data Register.
+ //
+ for (Index = 0; Index < BytesCount; Index++) {
+ ReadBuffer[Index] = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HBD);
+ }
+ }
+
+Done:
+ //
+ // Clear Host Status Register and Auxiliary Status Register.
+ //
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
+
+ if (Status != NULL) {
+ *Status = ReturnStatus;
+ }
+
+ return BytesCount;
+}
+
+/**
+ Executes an SMBUS read block command.
+
+ Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress.
+ Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
+ Bytes are read from the SMBUS and stored in Buffer.
+ The number of bytes read is returned, and will never return a value larger than 32-bytes.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+ SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
+ If Length in SmBusAddress is not zero, then ASSERT().
+ If Buffer is NULL, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Buffer Pointer to the buffer to store the bytes read from the SMBUS.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The number of bytes read.
+
+**/
+UINTN
+EFIAPI
+SmBusReadBlock (
+ IN UINTN SmBusAddress,
+ OUT VOID *Buffer,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (Buffer != NULL);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((Buffer == NULL) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) != 0) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusBlock (
+ V_PCH_SMBUS_SMB_CMD_BLOCK,
+ SmBusAddress | B_PCH_SMBUS_READ,
+ NULL,
+ Buffer,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS write block command.
+
+ Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress.
+ The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
+ Bytes are written to the SMBUS from Buffer.
+ The number of bytes written is returned, and will never return a value larger than 32-bytes.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ If Length in SmBusAddress is zero or greater than 32, then ASSERT().
+ If Buffer is NULL, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[out] Buffer Pointer to the buffer to store the bytes read from the SMBUS.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The number of bytes written.
+
+**/
+UINTN
+EFIAPI
+SmBusWriteBlock (
+ IN UINTN SmBusAddress,
+ OUT VOID *Buffer,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (Buffer != NULL);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((Buffer == NULL) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) == 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) > 32) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusBlock (
+ V_PCH_SMBUS_SMB_CMD_BLOCK,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ Buffer,
+ NULL,
+ Status
+ );
+}
+
+/**
+ Executes an SMBUS block process call command.
+
+ Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress.
+ The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
+ Bytes are written to the SMBUS from WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer.
+ If Status is not NULL, then the status of the executed command is returned in Status.
+ It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read.
+ SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
+ If Length in SmBusAddress is zero or greater than 32, then ASSERT().
+ If WriteBuffer is NULL, then ASSERT().
+ If ReadBuffer is NULL, then ASSERT().
+ If any reserved bits of SmBusAddress are set, then ASSERT().
+
+ @param[in] SmBusAddress Address that encodes the SMBUS Slave Address,
+ SMBUS Command, SMBUS Data Length, and PEC.
+ @param[in] WriteBuffer Pointer to the buffer of bytes to write to the SMBUS.
+ @param[out] ReadBuffer Pointer to the buffer of bytes to read from the SMBUS.
+ @param[out] Status Return status for the executed command.
+ This is an optional parameter and may be NULL.
+
+ @retval The number of bytes written.
+
+**/
+UINTN
+EFIAPI
+SmBusBlockProcessCall (
+ IN UINTN SmBusAddress,
+ IN VOID *WriteBuffer,
+ OUT VOID *ReadBuffer,
+ OUT RETURN_STATUS *Status OPTIONAL
+ )
+{
+ ASSERT (WriteBuffer != NULL);
+ ASSERT (ReadBuffer != NULL);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
+ ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
+ ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
+
+ if ((WriteBuffer == NULL) ||
+ (ReadBuffer == NULL) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) == 0) ||
+ (SMBUS_LIB_LENGTH (SmBusAddress) > 32) ||
+ (SMBUS_LIB_RESERVED (SmBusAddress) != 0))
+ {
+ if (Status != NULL) {
+ *Status = RETURN_INVALID_PARAMETER;
+ }
+ return 0;
+ }
+
+ return InternalSmBusBlock (
+ V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS,
+ SmBusAddress | B_PCH_SMBUS_WRITE,
+ WriteBuffer,
+ ReadBuffer,
+ Status
+ );
+}
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library instance.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+**/
+RETURN_STATUS
+EFIAPI
+BaseSmbusLibConstructor (
+ VOID
+ )
+{
+ UINTN SmbusPciBase;
+ UINT16 IoPortBaseAddress;
+
+ //
+ // Init mSmbusIoBase variable.
+ //
+ SmbusPciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+ IoPortBaseAddress = (UINT16) MmioRead32 (SmbusPciBase + R_PCH_SMBUS_BASE);
+
+ if ((IoPortBaseAddress != 0) && (IoPortBaseAddress != 0xFFFF)) {
+ mSmbusIoBase = IoPortBaseAddress & B_PCH_SMBUS_BASE_BAR;
+ }
+
+ return RETURN_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.inf
new file mode 100644
index 0000000000..a737f7105f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/BaseSmbusLib/BaseSmbusLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file for PCH Smbus Library.
+#
+# SMBUS Library that layers on top of the I/O Library to directly
+# access a standard SMBUS host controller.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = BaseSmbusLib
+FILE_GUID = 5C4D0430-F81B-42D3-BB88-4A6CD2796FF8
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SmbusLib
+CONSTRUCTOR = BaseSmbusLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[LibraryClasses]
+BaseLib
+DebugLib
+IoLib
+MmPciLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+BaseSmbusLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.c
new file mode 100644
index 0000000000..9526560b95
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.c
@@ -0,0 +1,325 @@
+/** @file
+ System reset library services.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <PchAccess.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Protocol/PchReset.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mDxeResetSystemPmcBase;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mDxeResetSystemABase;
+
+/**
+ Dump reset message for debug build readability
+**/
+VOID
+DumpResetMessage (
+ VOID
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINTN Index;
+ //
+ // ******************************
+ // ** SYSTEM REBOOT !!! **
+ // ******************************
+ //
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n** SYSTEM REBOOT !!! **\n"));
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] ResetType Reset Types which includes GlobalReset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of
+ callback protocol is installed.
+**/
+EFI_STATUS
+EFIAPI
+PchResetCallback (
+ IN PCH_RESET_TYPE ResetType
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ PCH_RESET_CALLBACK_PROTOCOL *PchResetCallback;
+
+ ///
+ /// Retrieve all instances of Pch Reset Callback protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gPchResetCallbackProtocolGuid,
+ NULL,
+ &NumHandles,
+ &HandleBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ///
+ /// Those drivers that need to install Pch Reset Callback protocol have the responsibility
+ /// to make sure themselves execute before Reset driver.
+ ///
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "None of Pch Reset Callback protocol is installed.\n"));
+ }
+ return Status;
+ }
+
+ for (Index = 0; Index < NumHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gPchResetCallbackProtocolGuid,
+ (VOID **) &PchResetCallback
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ PchResetCallback->ResetCallback (ResetType);
+ } else {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "Failed to locate Pch Reset Callback protocol.\n"));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetCold);
+
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetWarm);
+
+ DumpResetMessage ();
+ //
+ // In case there are pending capsules to process, need to flush the cache.
+ //
+ AsmWbinvd ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_HARDRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetShutdown);
+
+ ///
+ /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system from S5
+ ///
+ IoWrite32 ((UINTN) (mDxeResetSystemABase + R_PCH_ACPI_GPE0_EN_127_96), 0);
+
+ ///
+ /// Secondly, PwrSts register must be cleared
+ ///
+ /// Write a "1" to bit[8] of power button status register at
+ /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
+ ///
+ IoWrite16 ((UINTN) (mDxeResetSystemABase + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_PWRBTN);
+
+ ///
+ /// Finally, transform system into S5 sleep state
+ ///
+ Data32 = IoRead32 ((UINTN) (mDxeResetSystemABase + R_PCH_ACPI_PM1_CNT));
+
+ Data32 = (UINT32) ((Data32 &~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S5);
+
+ IoWrite32 ((UINTN) (mDxeResetSystemABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ DumpResetMessage ();
+
+ IoWrite32 ((UINTN) (mDxeResetSystemABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ return;
+}
+
+/**
+ Internal function to execute the required HECI command for GlobalReset,
+ if failed will use PCH Reest.
+
+**/
+STATIC
+VOID
+DxePchGlobalReset (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback (PchGlobalReset);
+
+ //
+ // PCH BIOS Spec Section 4.6 GPIO Reset Requirement
+ //
+ MmioOr32 (mDxeResetSystemPmcBase + R_PCH_PMC_ETR3, (UINT32) B_PCH_PMC_ETR3_CF9GR);
+
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state for platform specific.
+
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ EFI_GUID *GuidPtr;
+
+ if (ResetData == NULL) {
+ DEBUG ((DEBUG_ERROR, "[DxeResetSystemLib] ResetData is not available.\n"));
+ return;
+ }
+ GuidPtr = (EFI_GUID *) ((UINT8 *) ResetData + DataSize - sizeof (EFI_GUID));
+ if (CompareGuid (GuidPtr, &gPchGlobalResetGuid)) {
+ DxePchGlobalReset();
+ } else {
+ return;
+ }
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library DXE instance.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+ It will ASSERT on error for debug version.
+**/
+EFI_STATUS
+EFIAPI
+DxeResetSystemLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Get ACPI Base Address and PMC Base Address
+ //
+ PchAcpiBaseGet (&mDxeResetSystemABase);
+
+ mDxeResetSystemPmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.inf
new file mode 100644
index 0000000000..1736c3189e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeResetSystemLib/DxeResetSystemLib.inf
@@ -0,0 +1,56 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = DxeResetSystemLib
+FILE_GUID = 239383BC-499E-4DC5-8CDC-F85AF27B1BC4
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+CONSTRUCTOR = DxeResetSystemLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+BaseLib
+DebugLib
+TimerLib
+BaseMemoryLib
+UefiBootServicesTableLib
+MmPciLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxeResetSystemLib.c
+
+
+[Protocols]
+gPchResetCallbackProtocolGuid ## CONSUMES
+
+
+[Guids]
+gPchGlobalResetGuid
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.c
new file mode 100644
index 0000000000..919cb407e0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.c
@@ -0,0 +1,367 @@
+/** @file
+ System reset library services.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <PchAccess.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Protocol/PchReset.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mDxeRuntimeResetSystemPmcBase;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mDxeRuntimeResetSystemABase;
+
+/**
+ Dump reset message for debug build readability
+**/
+VOID
+DumpResetMessage (
+ VOID
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINTN Index;
+ //
+ // ******************************
+ // ** SYSTEM REBOOT !!! **
+ // ******************************
+ //
+ if (!EfiAtRuntime ()) {
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n** SYSTEM REBOOT !!! **\n"));
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+ DEBUG_CODE_END ();
+}
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] ResetType Reset Types which includes GlobalReset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of
+ callback protocol is installed.
+**/
+EFI_STATUS
+EFIAPI
+PchResetCallback (
+ IN PCH_RESET_TYPE ResetType
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ PCH_RESET_CALLBACK_PROTOCOL *PchResetCallback;
+
+ if (!EfiAtRuntime ()) {
+ ///
+ /// Retrieve all instances of Pch Reset Callback protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gPchResetCallbackProtocolGuid,
+ NULL,
+ &NumHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ ///
+ /// Those drivers that need to install Pch Reset Callback protocol have the responsibility
+ /// to make sure themselves execute before Pch Reset Runtime driver.
+ ///
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "None of Pch Reset Callback protocol is installed.\n"));
+ }
+ return Status;
+ }
+
+ for (Index = 0; Index < NumHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gPchResetCallbackProtocolGuid,
+ (VOID **) &PchResetCallback
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ PchResetCallback->ResetCallback (ResetType);
+ } else {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "Failed to locate Pch Reset Callback protocol.\n"));
+ return Status;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetCold);
+
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetWarm);
+
+ DumpResetMessage ();
+ //
+ // In case there are pending capsules to process, need to flush the cache.
+ //
+ AsmWbinvd ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_HARDRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetShutdown);
+
+ ///
+ /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system from S5
+ ///
+ IoWrite32 ((UINTN) (mDxeRuntimeResetSystemABase + R_PCH_ACPI_GPE0_EN_127_96), 0);
+
+ ///
+ /// Secondly, PwrSts register must be cleared
+ ///
+ /// Write a "1" to bit[8] of power button status register at
+ /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
+ ///
+ IoWrite16 ((UINTN) (mDxeRuntimeResetSystemABase + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_PWRBTN);
+
+ ///
+ /// Finally, transform system into S5 sleep state
+ ///
+ Data32 = IoRead32 ((UINTN) (mDxeRuntimeResetSystemABase + R_PCH_ACPI_PM1_CNT));
+
+ Data32 = (UINT32) ((Data32 &~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S5);
+
+ IoWrite32 ((UINTN) (mDxeRuntimeResetSystemABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ DumpResetMessage ();
+
+ IoWrite32 ((UINTN) (mDxeRuntimeResetSystemABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ return;
+}
+
+/**
+ Internal function to execute the required HECI command for GlobalReset,
+ if failed will use PCH Reest.
+
+**/
+STATIC
+VOID
+DxeRuntimePchGlobalReset (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback Protocol
+ //
+ PchResetCallback (PchGlobalReset);
+
+ //
+ // PCH BIOS Spec Section 4.6 GPIO Reset Requirement
+ //
+ MmioOr32 (mDxeRuntimeResetSystemPmcBase + R_PCH_PMC_ETR3, (UINT32) B_PCH_PMC_ETR3_CF9GR);
+
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state for platform specific.
+
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ EFI_GUID *GuidPtr;
+
+ if (ResetData == NULL) {
+ if (!EfiAtRuntime ()) {
+ DEBUG ((DEBUG_ERROR, "[DxeRuntimeResetSystemLib] ResetData is not available.\n"));
+ }
+ return;
+ }
+ GuidPtr = (EFI_GUID *) ((UINT8 *) ResetData + DataSize - sizeof (EFI_GUID));
+ if (CompareGuid (GuidPtr, &gPchGlobalResetGuid)) {
+ DxeRuntimePchGlobalReset();
+ } else {
+ return;
+ }
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Convert the physical PMC base addresses to virtual addresses.
+
+ @param[in] Event The event that is being processed.
+ @param[in] Context The Event Context.
+**/
+VOID
+EFIAPI
+ResetSystemLibVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0x0, (VOID **) &mDxeRuntimeResetSystemPmcBase);
+}
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library instance.
+
+ The PMC PCI configuration space memory range is converted into EFI_RUNTIME_XXX
+ in PciHostBridgeEntryPoint
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+ It will ASSERT on error for debug version.
+ @retval EFI_ERROR Please reference LocateProtocol for error code details.
+**/
+EFI_STATUS
+EFIAPI
+DxeRuntimeResetSystemLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT AddressChangeEvent;
+
+ //
+ // Get ACPI Base Address and PMC Base Address
+ //
+ PchAcpiBaseGet (&mDxeRuntimeResetSystemABase);
+
+ mDxeRuntimeResetSystemPmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ //
+ // Create Address Change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ ResetSystemLibVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &AddressChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf
new file mode 100644
index 0000000000..801876dd93
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf
@@ -0,0 +1,58 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = DxeRuntimeResetSystemLib
+FILE_GUID = 1026813A-E46F-43D1-B709-FF1F996F2E72
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_RUNTIME_DRIVER
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+CONSTRUCTOR = DxeRuntimeResetSystemLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+BaseLib
+DebugLib
+TimerLib
+BaseMemoryLib
+UefiRuntimeLib
+UefiBootServicesTableLib
+MmPciLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxeRuntimeResetSystemLib.c
+
+
+[Protocols]
+gPchResetCallbackProtocolGuid ## CONSUMES
+
+
+[Guids]
+gPchGlobalResetGuid
+gEfiEventVirtualAddressChangeGuid
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c
new file mode 100644
index 0000000000..6e0c1c8b46
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioInit.c
@@ -0,0 +1,505 @@
+/** @file
+ This file contains routines for GPIO initialization
+
+Copyright (c) 2017, 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 that 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 "GpioLibrary.h"
+
+/**
+ This procedure will handle requirement on gSPIx_CSB pins.
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO PadMode value
+ @param[in out] Dw0Reg Value for PADCFG_DW0 register
+ @param[in out] Dw0RegMask Mask of bits which will change in PADCFG_DWO register
+
+ @retval None
+**/
+STATIC
+VOID
+GpioHandleGSpiCSBPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadMode,
+ IN OUT UINT32 *Dw0Reg,
+ IN OUT UINT32 *Dw0RegMask
+ )
+{
+ //
+ // For gSPIx_CSB pins if are going to be used in native mode then skip setting
+ // pad mode here.
+ //
+ if (GpioIsGpioPadAGSpiCsbPin (GpioPad, PadMode)) {
+ //
+ // Skip setting PadMode to native, leave it in GPIO mode.
+ // Setting it to native should be done after Serial IO initialization
+ //
+ *Dw0RegMask |= B_PCH_GPIO_PAD_MODE;
+ *Dw0Reg &= ~B_PCH_GPIO_PAD_MODE;
+ *Dw0Reg |= ((GpioPadModeGpio >> 1) << N_PCH_GPIO_PAD_MODE);
+ }
+}
+
+/**
+ This procedure will handle requirement on SATA DEVSLPx pins.
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO PadMode value
+ @param[in out] Dw0Reg Value for PADCFG_DW0 register
+ @param[in out] Dw0RegMask Mask of bits which will change in PADCFG_DWO register
+
+ @retval None
+
+**/
+STATIC
+VOID
+GpioHandleSataDevSlpPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadMode,
+ IN OUT UINT32 *Dw0Reg,
+ IN OUT UINT32 *Dw0RegMask
+ )
+{
+ //
+ // For SATA DEVSLPx pins if used in native 1 mode then ensure that PadRstCfg
+ // is set to "00" - Powergood
+ //
+ if (GpioIsPadASataDevSlpPin (GpioPad, PadMode)) {
+ //
+ // Set PadRstCfg to Powergood
+ //
+ *Dw0RegMask |= B_PCH_GPIO_RST_CONF;
+ *Dw0Reg &= ~B_PCH_GPIO_RST_CONF;
+ *Dw0Reg |= ((GpioResumeReset >> 1) << N_PCH_GPIO_RST_CONF);
+ }
+}
+
+//
+// GPIO_DW_REG_VALUE structure is used by GpioConfigureSklPch function
+// to cache values which will be programmed into respective GPIO registers
+// after all GpioPads are processed. This way MMIO accesses are decreased
+// and instead of doing one programming for one GpioPad there is only
+// one access for whole register.
+//
+typedef struct {
+ UINT32 HostSoftOwnReg;
+ UINT32 HostSoftOwnRegMask;
+ UINT32 GpiGpeEnReg;
+ UINT32 GpiGpeEnRegMask;
+ UINT32 GpiNmiEnReg;
+ UINT32 GpiNmiEnRegMask;
+ UINT32 PadsToLock;
+ UINT32 PadsToLockTx;
+} GPIO_DW_REG_VALUE;
+
+//
+// GPIO_DW_REG_NUMBER contains number of DWords required to
+// store Pad data for all groups. Each pad uses one bit.
+//
+// For Skylake and Kabylake each group has <32 pads what
+// makes GPIO_DW_REG_NUMBER = 1
+//
+#define GPIO_DW_REG_NUMBER 1
+
+/**
+ Get GPIO DW Register values (HOSTSW_OWN, GPE_EN, NMI_EN, Lock).
+
+ @param[in] PadNumber GPIO pad number
+ @param[in] GpioConfig GPIO Config data
+ @param[in out] DwRegsValues Values for GPIO DW Registers
+
+ @retval None
+**/
+STATIC
+VOID
+GpioDwRegValueFromGpioConfig (
+ IN UINT32 PadNumber,
+ IN GPIO_CONFIG *GpioConfig,
+ IN OUT GPIO_DW_REG_VALUE *DwRegsValues
+ )
+{
+ UINT32 PadBitPosition;
+ UINT32 DwNum;
+
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+
+ if (DwNum >= GPIO_DW_REG_NUMBER) {
+ ASSERT (FALSE);
+ return;
+ }
+ //
+ // Update value to be programmed in HOSTSW_OWN register
+ //
+ DwRegsValues[DwNum].HostSoftOwnRegMask |= (GpioConfig->HostSoftPadOwn & 0x1) << PadBitPosition;
+ DwRegsValues[DwNum].HostSoftOwnReg |= (GpioConfig->HostSoftPadOwn >> 0x1) << PadBitPosition;
+
+ //
+ // Update value to be programmed in GPI_GPE_EN register
+ //
+ DwRegsValues[DwNum].GpiGpeEnRegMask |= (GpioConfig->InterruptConfig & 0x1) << PadBitPosition;
+ DwRegsValues[DwNum].GpiGpeEnReg |= ((GpioConfig->InterruptConfig & GpioIntSci) >> 3) << PadBitPosition;
+
+ //
+ // Update value to be programmed in GPI_NMI_EN register
+ //
+ DwRegsValues[DwNum].GpiNmiEnRegMask |= (GpioConfig->InterruptConfig & 0x1) << PadBitPosition;
+ DwRegsValues[DwNum].GpiNmiEnReg |= ((GpioConfig->InterruptConfig & GpioIntNmi) >> 1) << PadBitPosition;
+
+ //
+ // Update information on Pad Configuration Lock
+ //
+ DwRegsValues[DwNum].PadsToLock |= ((GpioConfig->LockConfig >> 0x1) & 0x1) << PadBitPosition;
+
+ //
+ // Update information on Pad Configuration Lock Tx
+ //
+ DwRegsValues[DwNum].PadsToLockTx |= ((GpioConfig->LockConfig >> 0x2) & 0x1) << PadBitPosition;
+}
+
+/**
+ This SKL PCH specific procedure will initialize multiple SKL PCH GPIO pins
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+STATIC
+EFI_STATUS
+GpioConfigureSklPch (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ )
+{
+ UINT32 Index;
+ UINT32 PadCfgDwReg[2];
+ UINT32 PadCfgDwRegMask[2];
+ UINT32 PadCfgReg;
+ GPIO_DW_REG_VALUE DwRegsValues[GPIO_DW_REG_NUMBER];
+ UINT32 DwNum;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ GPIO_GROUP GpioGroupOffset;
+ UINT32 NumberOfGroups;
+ GPIO_PAD_OWN PadOwnVal;
+ GPIO_INIT_CONFIG *GpioData;
+ GPIO_GROUP Group;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ PadOwnVal = GpioPadOwnHost;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+ NumberOfGroups = GpioGetNumberOfGroups ();
+
+ Index = 0;
+ while (Index < NumberOfItems) {
+
+ GpioData = &GpioInitTableAddress[Index];
+ Group = GpioGetGroupFromGpioPad (GpioData->GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioData->GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad);
+
+ if (GroupIndex >= V_PCH_GPIO_GROUP_MAX) {
+ // @todo SKL PCH: one platform code ready we should add this back ASSERT (FALSE);
+ continue;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ if (!(((PchSeries == PchH) && (GPIO_GET_CHIPSET_ID (GpioData->GpioPad) == GPIO_SKL_H_CHIPSET_ID)) ||
+ ((PchSeries == PchLp) && (GPIO_GET_CHIPSET_ID (GpioData->GpioPad) == GPIO_SKL_LP_CHIPSET_ID)))) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ DEBUG_CODE_END ();
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if ((Group < GpioGroupOffset) || (Group >= NumberOfGroups + GpioGroupOffset)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Invalid group %d\n", GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (DwRegsValues, sizeof (DwRegsValues));
+ //
+ // Loop through pads for one group. If pad belongs to a different group then
+ // break and move to register programming.
+ //
+ while (Index < NumberOfItems) {
+
+ GpioData = &GpioInitTableAddress[Index];
+ if (GroupIndex != GpioGetGroupIndexFromGpioPad (GpioData->GpioPad)) {
+ //if next pad is from different group then break loop
+ break;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad);
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for group %d\n", PadNumber, GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH
+ //
+ GpioGetPadOwnership (GpioData->GpioPad, &PadOwnVal);
+
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ DEBUG ((DEBUG_ERROR, "** Please make sure the GPIO usage in sync between CSME and BIOS configuration. \n"));
+ DEBUG ((DEBUG_ERROR, "** All the GPIO occupied by CSME should not do any configuration by BIOS.\n"));
+ //Move to next item
+ Index++;
+ continue;
+ }
+ DEBUG_CODE_END ();
+
+ ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg));
+ ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask));
+ //
+ // Get GPIO PADCFG register value from GPIO config data
+ //
+ GpioPadCfgRegValueFromGpioConfig (
+ GpioData->GpioPad,
+ &GpioData->GpioConfig,
+ PadCfgDwReg,
+ PadCfgDwRegMask
+ );
+
+ //
+ // Check for additional requirements on setting PADCFG register
+ //
+ GpioHandleGSpiCSBPad (GpioData->GpioPad, GpioData->GpioConfig.PadMode, &PadCfgDwReg[0], &PadCfgDwRegMask[0]);
+ GpioHandleSataDevSlpPad (GpioData->GpioPad, GpioData->GpioConfig.PadMode, &PadCfgDwReg[0], &PadCfgDwRegMask[0]);
+
+ //
+ // Create PADCFG register offset using group and pad number
+ //
+ PadCfgReg = PAD_CFG_SIZE * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+
+ //
+ // Write PADCFG DW0 register
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ ~PadCfgDwRegMask[0],
+ PadCfgDwReg[0]
+ );
+
+ //
+ // Write PADCFG DW1 register
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg + 0x4),
+ ~PadCfgDwRegMask[1],
+ PadCfgDwReg[1]
+ );
+
+ //
+ // Get GPIO DW register values from GPIO config data
+ //
+ GpioDwRegValueFromGpioConfig (
+ PadNumber,
+ &GpioData->GpioConfig,
+ DwRegsValues
+ );
+
+ //Move to next item
+ Index++;
+ }
+
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ //
+ // Write HOSTSW_OWN registers
+ //
+ if (GpioGroupInfo[GroupIndex].HostOwnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].HostOwnOffset + DwNum * 0x4),
+ ~DwRegsValues[DwNum].HostSoftOwnRegMask,
+ DwRegsValues[DwNum].HostSoftOwnReg
+ );
+ }
+
+ //
+ // Write GPI_GPE_EN registers
+ //
+ if (GpioGroupInfo[GroupIndex].GpiGpeEnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiGpeEnOffset + DwNum * 0x4),
+ ~DwRegsValues[DwNum].GpiGpeEnRegMask,
+ DwRegsValues[DwNum].GpiGpeEnReg
+ );
+ }
+
+ //
+ // Write GPI_NMI_EN registers
+ //
+ if (GpioGroupInfo[GroupIndex].NmiEnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].NmiEnOffset + DwNum * 0x4),
+ ~DwRegsValues[DwNum].GpiNmiEnRegMask,
+ DwRegsValues[DwNum].GpiNmiEnReg
+ );
+ } else if (DwRegsValues[DwNum].GpiNmiEnReg != 0x0) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting NMI\n", GroupIndex));
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+ }
+
+ //
+ // Write Pad Configuration Lock
+ //
+ if (DwRegsValues[DwNum].PadsToLock != 0) {
+ GpioLockPadCfgForGroupDw (GroupIndex + GpioGroupOffset, DwNum, DwRegsValues[DwNum].PadsToLock);
+ }
+
+ //
+ // Write Pad Configuration Lock Tx
+ //
+ if (DwRegsValues[DwNum].PadsToLockTx != 0) {
+ GpioLockPadCfgTxForGroupDw (GroupIndex + GpioGroupOffset, DwNum, DwRegsValues[DwNum].PadsToLockTx);
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will clear all status bits of any GPIO interrupts.
+
+ @param[in] none
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+STATIC
+EFI_STATUS
+GpioClearAllGpioInterrupts (
+ VOID
+ )
+{
+ GPIO_GROUP Group;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ GPIO_GROUP GpioGroupLowest;
+ GPIO_GROUP GpioGroupHighest;
+ UINT32 GroupIndex;
+ UINTN GpioGroupInfoLength;
+ UINT32 DwNum;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupLowest = GpioGetLowestGroup ();
+ GpioGroupHighest = GpioGetHighestGroup ();
+
+ for (Group = GpioGroupLowest; Group <= GpioGroupHighest; Group++) {
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ //
+ // Check if group has GPI IS register
+ //
+ if (GpioGroupInfo[GroupIndex].GpiIsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all GPI_IS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiIsOffset + DwNum * 0x4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ //
+ // Check if group has GPI_GPE_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].GpiGpeStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all GPI_GPE_STS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiGpeStsOffset + DwNum * 0x4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ //
+ // Check if group has SMI_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].SmiStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all SMI_STS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].SmiStsOffset + DwNum * 4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ //
+ // Check if group has NMI_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].NmiStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all NMI_STS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].NmiStsOffset + DwNum * 4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will initialize multiple GPIO pins. Use GPIO_INIT_CONFIG structure.
+ Structure contains fields that can be used to configure each pad.
+ Pad not configured using GPIO_INIT_CONFIG will be left with hardware default values.
+ Separate fields could be set to hardware default if it does not matter, except
+ GpioPad and PadMode.
+ Some GpioPads are configured and switched to native mode by RC, those include:
+ SerialIo pins, ISH pins, ClkReq Pins
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioConfigurePads (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ )
+{
+ EFI_STATUS Status;
+ Status = GpioConfigureSklPch (NumberOfItems, GpioInitTableAddress);
+ GpioClearAllGpioInterrupts ();
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c
new file mode 100644
index 0000000000..bf76d40963
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLib.c
@@ -0,0 +1,2691 @@
+/** @file
+ This file contains routines for GPIO
+
+Copyright (c) 2017, 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 that 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 "GpioLibrary.h"
+
+/**
+ This procedure will check if GpioPad is owned by host.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is owned by host
+ @retval FALSE GPIO pad is not owned by host and should not be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadHostOwned (
+ IN GPIO_PAD GpioPad
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_PAD_OWN PadOwnVal;
+
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH
+ // If GPIO is not owned by Host all access to PadCfg will be dropped
+ //
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Gpio pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This procedure will check if GpioPad argument is valid.
+ Function will check below conditions:
+ - GpioPad represents a pad for current PCH
+ - GpioPad belongs to valid GpioGroup
+ - GPIO PadNumber is not greater than number of pads for this group
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is valid and can be used with GPIO lib API
+ @retval FALSE GPIO pad is invalid and cannot be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadValid (
+ IN GPIO_PAD GpioPad
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return FALSE;
+ }
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ return FALSE;
+ }
+
+ if ((GroupIndex < GpioGetGroupIndexFromGroup (GpioGetLowestGroup ())) ||
+ (GroupIndex > GpioGetGroupIndexFromGroup (GpioGetHighestGroup ()))) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) is not within range of possible groups for this PCH\n", GroupIndex));
+ return FALSE;
+ }
+
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This procedure will check if GpioGroup argument is correct and
+ supplied DW reg number can be used for this group to access DW registers.
+ Function will check below conditions:
+ - Valid GpioGroup
+ - DwNum is has valid value for this group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+
+ @retval TRUE DW Reg number and GpioGroup is valid
+ @retval FALSE DW Reg number and GpioGroup is invalid
+**/
+STATIC
+BOOLEAN
+GpioIsGroupAndDwNumValid (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum
+ )
+{
+ UINT32 GroupIndex;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ return FALSE;
+ }
+
+ if ((GroupIndex < GpioGetGroupIndexFromGroup (GpioGetLowestGroup ())) ||
+ (GroupIndex > GpioGetGroupIndexFromGroup (GpioGetHighestGroup ()))) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) is not within range of possible groups for this PCH\n", GroupIndex));
+ return FALSE;
+ }
+
+ //
+ // Check if DwNum argument does not exceed number of DWord registers
+ // resulting from available pads for certain group
+ //
+ if (DwNum > GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup - 1)){
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[out] PadCfgRegValue Read data
+
+ @retval none
+**/
+VOID
+GpioReadPadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ OUT UINT32 *PadCfgRegValue
+ )
+{
+ UINT32 PadCfgReg;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = GpioGroupInfo[GroupIndex].PadCfgOffset + PAD_CFG_SIZE * PadNumber + 0x4 * DwReg;
+
+ *PadCfgRegValue = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg));
+}
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[in] PadCfgAndMask Mask to be AND'ed with PADCFG reg value
+ @param[in] PadCfgOrMask Mask to be OR'ed with PADCFG reg value
+
+ @retval none
+**/
+VOID
+GpioWritePadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ IN UINT32 PadCfgAndMask,
+ IN UINT32 PadCfgOrMask
+ )
+{
+ UINT32 PadCfgReg;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = GpioGroupInfo[GroupIndex].PadCfgOffset + PAD_CFG_SIZE * PadNumber + 0x4 * DwReg;
+
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ PadCfgAndMask,
+ PadCfgOrMask
+ );
+}
+
+//
+// Possible registers to be accessed using GpioReadReg()/GpioWriteReg() functions
+//
+typedef enum {
+ GpioHostOwnershipRegister = 0,
+ GpioGpeEnableRegister,
+ GpioGpeStatusRegister,
+ GpioSmiEnableRegister,
+ GpioSmiStatusRegister,
+ GpioNmiEnableRegister,
+ GpioPadConfigLockRegister,
+ GpioPadLockOutputRegister
+} GPIO_REG;
+
+/**
+ This procedure will read GPIO register
+
+ @param[in] RegType GPIO register type
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] ReadVal Read data
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+STATIC
+EFI_STATUS
+GpioReadReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *ReadVal
+ )
+{
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ RegOffset = NO_REGISTER_FOR_PROPERTY;
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ switch (RegType) {
+ case GpioHostOwnershipRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset;
+ break;
+ case GpioGpeEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset;
+ break;
+ case GpioGpeStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset;
+ break;
+ case GpioSmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset;
+ break;
+ case GpioSmiStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset;
+ break;
+ case GpioNmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset;
+ break;
+ case GpioPadConfigLockRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
+ break;
+ case GpioPadLockOutputRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ //
+ if ((RegType == GpioPadConfigLockRegister) || (RegType == GpioPadLockOutputRegister)) {
+ //
+ // PadConfigLock and OutputLock registers when used for group containing more than 32 pads
+ // are not placed in a continuous way, e.g:
+ // 0x0 - PadConfigLock_DW0
+ // 0x4 - OutputLock_DW0
+ // 0x8 - PadConfigLock_DW1
+ // 0xC - OutputLock_DW1
+ //
+ RegOffset += DwNum * 0x8;
+ } else {
+ RegOffset += DwNum * 0x4;
+ }
+
+ *ReadVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will write GPIO register
+
+ @param[in] RegType GPIO register type
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] RegAndMask Mask which will be AND'ed with register value
+ @param[in] RegOrMask Mask which will be OR'ed with register value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+STATIC
+EFI_STATUS
+GpioWriteReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 RegAndMask,
+ IN UINT32 RegOrMask
+ )
+{
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ RegOffset = NO_REGISTER_FOR_PROPERTY;
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ switch (RegType) {
+ case GpioHostOwnershipRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset;
+ break;
+ case GpioGpeEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset;
+ break;
+ case GpioGpeStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset;
+ break;
+ case GpioSmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset;
+ break;
+ case GpioSmiStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset;
+ break;
+ case GpioNmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset;
+ break;
+ case GpioPadConfigLockRegister:
+ case GpioPadLockOutputRegister:
+ ASSERT (FALSE);
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ //
+ RegOffset += DwNum * 0x4;
+
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset),
+ RegAndMask,
+ RegOrMask
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will write GPIO Lock/LockTx register using SBI.
+
+ @param[in] RegType GPIO register (Lock or LockTx)
+ @param[in] Group GPIO group number
+ @param[in] DwNum Register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] LockRegAndMask Mask which will be AND'ed with Lock register value
+ @param[in] LockRegOrMask Mask which will be Or'ed with Lock register value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+STATIC
+EFI_STATUS
+GpioWriteLockReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 LockRegAndMask,
+ IN UINT32 LockRegOrMask
+ )
+{
+ UINT8 Response;
+ EFI_STATUS Status;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 RegOffset;
+ UINT32 OldPadCfgLockRegVal;
+ UINT32 NewPadCfgLockRegVal;
+ UINT32 GroupIndex;
+
+ RegOffset = NO_REGISTER_FOR_PROPERTY;
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ switch (RegType) {
+ case GpioPadConfigLockRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
+ break;
+ case GpioPadLockOutputRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ // PadConfigLock and OutputLock registers when used for group containing more than 32 pads
+ // are not placed in a continuous way, e.g:
+ // 0x0 - PadConfigLock_DW0
+ // 0x4 - OutputLock_DW0
+ // 0x8 - PadConfigLock_DW1
+ // 0xC - OutputLock_DW1
+ //
+ RegOffset += DwNum *0x8;
+
+ GpioGetPadCfgLockForGroupDw (Group, DwNum, &OldPadCfgLockRegVal);
+
+ NewPadCfgLockRegVal = (OldPadCfgLockRegVal & LockRegAndMask) | LockRegOrMask;
+
+ Status = PchSbiExecution (
+ GpioGroupInfo[GroupIndex].Community,
+ RegOffset,
+ GpioLockUnlock,
+ FALSE,
+ &NewPadCfgLockRegVal,
+ &Response
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This internal procedure will calculate GPIO_RESET_CONFIG value (new type)
+ based on provided PadRstCfg for a specific GPIO Pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] PadRstCfg GPIO PadRstCfg value
+
+ @retval GpioResetConfig GPIO Reset configuration (new type)
+**/
+GPIO_RESET_CONFIG
+GpioResetConfigFromPadRstCfg (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadRstCfg
+ )
+{
+ GPIO_GROUP Group;
+
+ static GPIO_RESET_CONFIG GppPadRstCfgToGpioResetConfigMap[] = {
+ GpioResumeReset,
+ GpioHostDeepReset,
+ GpioPlatformReset};
+ static GPIO_RESET_CONFIG GpdPadRstCfgToGpioResetConfigMap[] = {
+ GpioDswReset,
+ GpioHostDeepReset,
+ GpioPlatformReset,
+ GpioResumeReset};
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+
+ if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
+ ASSERT (PadRstCfg < 4);
+ if (PadRstCfg >= 4) return GpioResumeReset;
+ return GpdPadRstCfgToGpioResetConfigMap[PadRstCfg];
+ } else {
+ ASSERT (PadRstCfg < 3);
+ if (PadRstCfg >= 3) return GpioResumeReset;
+ return GppPadRstCfgToGpioResetConfigMap[PadRstCfg];
+ }
+}
+
+/**
+ This internal procedure will calculate PadRstCfg register value based
+ on provided GPIO Reset configuration for a certain pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioResetConfig GPIO Reset configuration
+ @param[out] PadRstCfg GPIO PadRstCfg value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid configuration
+**/
+EFI_STATUS
+GpioPadRstCfgFromResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG GpioResetConfig,
+ OUT UINT32 *PadRstCfg
+ )
+{
+ GPIO_GROUP Group;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+
+ switch (GpioResetConfig) {
+ case GpioResetDefault:
+ *PadRstCfg = 0x0;
+ break;
+ case GpioResetPwrGood: //old reset type
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_POW_GOOD;
+ break;
+ case GpioResetDeep: //old reset type
+ case GpioHostDeepReset: //new reset type
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_DEEP_RST;
+ break;
+ case GpioResetNormal: //old reset type
+ case GpioPlatformReset: //new reset type
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_GPIO_RST;
+ break;
+ case GpioResetResume: //old reset type
+ if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_RESUME_RST;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Only GPD group pads can use GpioResetResume (Group=%d, Pad=%d)!\n", GpioGetGroupIndexFromGpioPad (GpioPad), GpioGetPadNumberFromGpioPad (GpioPad)));
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ case GpioResumeReset: //new reset type
+ if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_RESUME_RST;
+ } else {
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_POW_GOOD;
+ }
+ break;
+ case GpioDswReset: //new reset type
+ if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
+ *PadRstCfg = V_PCH_GPIO_RST_CONF_POW_GOOD;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Only GPD group pads can use GpioDswReset (Group=%d, Pad=%d)!\n", GpioGetGroupIndexFromGpioPad (GpioPad), GpioGetPadNumberFromGpioPad (GpioPad)));
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This internal procedure will get GPIO_CONFIG data from PADCFG registers value
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] PadCfgDwReg PADCFG DWx register values
+ @param[out] GpioData GPIO Configuration data
+
+ @retval Status
+**/
+STATIC
+VOID
+GpioConfigFromPadCfgRegValue (
+ IN GPIO_PAD GpioPad,
+ IN CONST UINT32 *PadCfgDwReg,
+ OUT GPIO_CONFIG *GpioConfig
+ )
+{
+ UINT32 PadRstCfg;
+
+ //
+ // Get Reset Type (PadRstCfg)
+ //
+ PadRstCfg = (PadCfgDwReg[0] & B_PCH_GPIO_RST_CONF) >> N_PCH_GPIO_RST_CONF;
+
+ GpioConfig->PowerConfig = GpioResetConfigFromPadRstCfg (
+ GpioPad,
+ PadRstCfg
+ );
+
+ //
+ // Get how interrupt is triggered (RxEvCfg)
+ //
+ GpioConfig->InterruptConfig = ((PadCfgDwReg[0] & B_PCH_GPIO_RX_LVL_EDG) >> (N_PCH_GPIO_RX_LVL_EDG - (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1))) | (0x1 << N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS);
+
+ //
+ // Get interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
+ //
+ GpioConfig->InterruptConfig |= ((PadCfgDwReg[0] & (B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE)) >> (N_PCH_GPIO_RX_NMI_ROUTE - (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1))) | (0x1 << N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS);
+
+ //
+ // Get GPIO direction (GPIORxDis and GPIOTxDis)
+ //
+ GpioConfig->Direction = ((PadCfgDwReg[0] & (B_PCH_GPIO_RXDIS | B_PCH_GPIO_TXDIS)) >> (N_PCH_GPIO_TXDIS - (N_GPIO_DIRECTION_DIR_BIT_POS + 1))) | (0x1 << N_GPIO_DIRECTION_DIR_BIT_POS);
+
+ //
+ // Get GPIO input inversion (RXINV)
+ // (Only meaningful if input enabled)
+ //
+ if((PadCfgDwReg[0] & B_PCH_GPIO_RXDIS) == 0) {
+ GpioConfig->Direction |= ((PadCfgDwReg[0] & B_PCH_GPIO_RXINV) >> (N_PCH_GPIO_RXINV - (N_GPIO_DIRECTION_INV_BIT_POS + 1))) | (0x1 << N_GPIO_DIRECTION_INV_BIT_POS);
+ }
+
+ //
+ // Get GPIO output state (GPIOTxState)
+ //
+ GpioConfig->OutputState = ((PadCfgDwReg[0] & B_PCH_GPIO_TX_STATE) << (N_PCH_GPIO_TX_STATE + (N_GPIO_OUTPUT_BIT_POS + 1))) | (0x1 << N_GPIO_OUTPUT_BIT_POS);
+
+ //
+ // Configure GPIO RX raw override to '1' (RXRAW1)
+ //
+ GpioConfig->OtherSettings = ((PadCfgDwReg[0] & B_PCH_GPIO_RX_RAW1) >> (N_PCH_GPIO_RX_RAW1 - (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1))) | (0x1 << N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS);
+
+ //
+ // Get GPIO Pad Mode (PMode)
+ //
+ GpioConfig->PadMode = ((PadCfgDwReg[0] & B_PCH_GPIO_PAD_MODE) >> (N_PCH_GPIO_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE_BIT_POS);
+
+ //
+ // Get GPIO termination (Term)
+ //
+ GpioConfig->ElectricalConfig = ((PadCfgDwReg[1] & B_PCH_GPIO_TERM) >> (N_PCH_GPIO_TERM - (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1))) | (0x1 << N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS);
+
+ //
+ // Get GPIO pad tolerance (padtol)
+ //
+ GpioConfig->ElectricalConfig |= ((PadCfgDwReg[1] & B_PCH_GPIO_PADTOL) >> (N_PCH_GPIO_PADTOL - (N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS + 1))) | (0x1 << N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS);
+}
+
+/**
+ This procedure will read multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[out] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadConfig (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_CONFIG *GpioData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadCfgDwReg[2];
+ UINT32 RegVal;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 PadBitPosition;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Read PADCFG DW0 register
+ //
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgDwReg[0]
+ );
+
+ //
+ // Read PADCFG DW1 register
+ //
+ GpioReadPadCfgReg (
+ GpioPad,
+ 1,
+ &PadCfgDwReg[1]
+ );
+
+ GpioConfigFromPadCfgRegValue (
+ GpioPad,
+ PadCfgDwReg,
+ GpioData
+ );
+
+ //
+ // Read HOSTSW_OWN registers
+ //
+ Status = GpioReadReg (
+ GpioHostOwnershipRegister,
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ &RegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Host Software Ownership
+ //
+ GpioData->HostSoftPadOwn = (((RegVal >> PadBitPosition) & 0x1) << (N_GPIO_HOSTSW_OWN_BIT_POS + 1)) | (0x1 << N_GPIO_HOSTSW_OWN_BIT_POS);
+
+ //
+ // Read PADCFGLOCK register
+ //
+ Status = GpioReadReg (
+ GpioPadConfigLockRegister,
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ &RegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Pad Configuration Lock state
+ //
+ GpioData->LockConfig = (((RegVal >> PadBitPosition) & 0x1) << 1) | 0x1;
+
+ //
+ // Read PADCFGLOCKTX register
+ //
+ Status = GpioReadReg (
+ GpioPadLockOutputRegister,
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ &RegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Pad Configuration Lock Tx state
+ //
+ GpioData->LockConfig |= (((RegVal >> PadBitPosition) & 0x1) << 2) | 0x1;
+
+ return Status;
+}
+
+/**
+ This procedure will calculate PADCFG register value based on GpioConfig data
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioConfig GPIO Configuration data
+ @param[out] PadCfgDwReg PADCFG DWx register value
+ @param[out] PadCfgDwRegMask Mask with PADCFG DWx register bits to be modified
+
+ @retval Status
+**/
+EFI_STATUS
+GpioPadCfgRegValueFromGpioConfig (
+ IN GPIO_PAD GpioPad,
+ IN CONST GPIO_CONFIG *GpioConfig,
+ OUT UINT32 *PadCfgDwReg,
+ OUT UINT32 *PadCfgDwRegMask
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadRstCfg;
+
+ //
+ // Configure Reset Type (PadRstCfg)
+ // Reset configuration depends on group type.
+ // This field requires support for new and deprecated settings.
+ //
+ Status = GpioPadRstCfgFromResetConfig (
+ GpioPad,
+ GpioConfig->PowerConfig,
+ &PadRstCfg
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ PadCfgDwRegMask[0] |= ((((GpioConfig->PowerConfig & B_GPIO_RESET_CONFIG_RESET_MASK) >> N_GPIO_RESET_CONFIG_RESET_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RST_CONF);
+ PadCfgDwReg[0] |= PadRstCfg << N_PCH_GPIO_RST_CONF;
+
+ //
+ // Configure how interrupt is triggered (RxEvCfg)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RX_LVL_EDG);
+ PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_PCH_GPIO_RX_LVL_EDG);
+
+ //
+ // Configure interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE));
+ PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_PCH_GPIO_RX_NMI_ROUTE);
+
+ //
+ // Configure GPIO direction (GPIORxDis and GPIOTxDis)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->Direction & B_GPIO_DIRECTION_DIR_MASK) >> N_GPIO_DIRECTION_DIR_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_PCH_GPIO_RXDIS | B_PCH_GPIO_TXDIS));
+ PadCfgDwReg[0] |= (((GpioConfig->Direction & B_GPIO_DIRECTION_DIR_MASK) >> (N_GPIO_DIRECTION_DIR_BIT_POS + 1)) << N_PCH_GPIO_TXDIS);
+
+ //
+ // Configure GPIO input inversion (RXINV)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->Direction & B_GPIO_DIRECTION_INV_MASK) >> N_GPIO_DIRECTION_INV_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RXINV);
+ PadCfgDwReg[0] |= (((GpioConfig->Direction & B_GPIO_DIRECTION_INV_MASK) >> (N_GPIO_DIRECTION_INV_BIT_POS + 1)) << N_PCH_GPIO_RXINV);
+
+ //
+ // Configure GPIO output state (GPIOTxState)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK) >> N_GPIO_OUTPUT_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_TX_STATE);
+ PadCfgDwReg[0] |= (((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK) >> (N_GPIO_OUTPUT_BIT_POS + 1)) << N_PCH_GPIO_TX_STATE);
+
+ //
+ // Configure GPIO RX raw override to '1' (RXRAW1)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->OtherSettings & B_GPIO_OTHER_CONFIG_RXRAW_MASK) >> N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RX_RAW1);
+ PadCfgDwReg[0] |= (((GpioConfig->OtherSettings & B_GPIO_OTHER_CONFIG_RXRAW_MASK) >> (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1)) << N_PCH_GPIO_RX_RAW1);
+
+ //
+ // Configure GPIO Pad Mode (PMode)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK) >> N_GPIO_PAD_MODE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PAD_MODE);
+ PadCfgDwReg[0] |= (((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK) >> (N_GPIO_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE);
+
+ //
+ // Configure GPIO termination (Term)
+ //
+ PadCfgDwRegMask[1] |= ((((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_TERM);
+ PadCfgDwReg[1] |= (((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) << N_PCH_GPIO_TERM);
+
+ //
+ // Configure GPIO pad tolerance (padtol)
+ //
+ PadCfgDwRegMask[1] |= ((((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PADTOL);
+ PadCfgDwReg[1] |= (((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS + 1)) << N_PCH_GPIO_PADTOL);
+
+ return Status;
+}
+
+/**
+ This procedure will configure multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetPadConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_CONFIG *GpioData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadCfgDwReg[2];
+ UINT32 PadCfgDwRegMask[2];
+ UINT32 HostSoftOwnReg;
+ UINT32 HostSoftOwnRegMask;
+ UINT32 GpiGpeEnReg;
+ UINT32 GpiGpeEnRegMask;
+ UINT32 GpiNmiEnReg;
+ UINT32 GpiNmiEnRegMask;
+ GPIO_GROUP Group;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ UINT32 PadBitPosition;
+ UINT32 DwNum;
+
+ ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg));
+ ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask));
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get GPIO PADCFG register value from GPIO config data
+ //
+ GpioPadCfgRegValueFromGpioConfig (
+ GpioPad,
+ GpioData,
+ PadCfgDwReg,
+ PadCfgDwRegMask
+ );
+
+ //
+ // Write PADCFG DW0 register
+ //
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ ~PadCfgDwRegMask[0],
+ PadCfgDwReg[0]
+ );
+
+ //
+ // Write PADCFG DW1 register
+ //
+ GpioWritePadCfgReg (
+ GpioPad,
+ 1,
+ ~PadCfgDwRegMask[1],
+ PadCfgDwReg[1]
+ );
+
+ //
+ // Update value to be programmed in HOSTSW_OWN register
+ //
+ HostSoftOwnRegMask = (GpioData->HostSoftPadOwn & 0x1) << PadBitPosition;
+ HostSoftOwnReg = (GpioData->HostSoftPadOwn >> 0x1) << PadBitPosition;
+
+ //
+ // Write HOSTSW_OWN registers
+ //
+ Status = GpioWriteReg (
+ GpioHostOwnershipRegister,
+ Group,
+ DwNum,
+ ~HostSoftOwnRegMask,
+ HostSoftOwnReg
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Update value to be programmed in GPI_GPE_EN register
+ //
+ GpiGpeEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
+ GpiGpeEnReg = ((GpioData->InterruptConfig & GpioIntSci) >> 3) << PadBitPosition;
+
+ //
+ // Write GPI_GPE_EN registers
+ //
+ Status = GpioWriteReg (
+ GpioGpeEnableRegister,
+ Group,
+ DwNum,
+ ~GpiGpeEnRegMask,
+ GpiGpeEnReg
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Update value to be programmed in GPI_NMI_EN register
+ //
+ GpiNmiEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
+ GpiNmiEnReg = ((GpioData->InterruptConfig & GpioIntNmi) >> 1) << PadBitPosition;
+
+ Status = GpioWriteReg (
+ GpioNmiEnableRegister,
+ Group,
+ DwNum,
+ ~GpiNmiEnRegMask,
+ GpiNmiEnReg
+ );
+ if (Status == EFI_UNSUPPORTED) {
+ if (GpiNmiEnReg == 0) {
+ //
+ // Not all GPIO have NMI capabilities. Since we always try to program this register,
+ // even when not enabling NMI for a pad so do not report such access as an error
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting NMI\n", GroupIndex));
+ ASSERT (FALSE);
+ return Status;
+ }
+ }
+
+ //
+ // Program Pad Configuration Lock
+ //
+ if ((GpioData->LockConfig & GpioPadConfigLock) == GpioPadConfigLock) {
+ GpioWriteLockReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ ~0u,
+ 1 << PadBitPosition
+ );
+ }
+
+ //
+ // Program Pad Configuration Lock Tx
+ //
+ if ((GpioData->LockConfig & GpioOutputStateLock) == GpioOutputStateLock) {
+ GpioWriteLockReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ ~0u,
+ 1 << PadBitPosition
+ );
+ }
+ return Status;
+}
+
+/**
+ This procedure will set GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetOutputValue (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ )
+{
+ if (Value > 1) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_PCH_GPIO_TX_STATE,
+ Value << N_PCH_GPIO_TX_STATE
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] OutputVal GPIO Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetOutputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *OutputVal
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgReg
+ );
+
+ *OutputVal = (PadCfgReg & B_PCH_GPIO_TX_STATE) >> N_PCH_GPIO_TX_STATE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO input level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InputVal GPIO Input value
+ 0: InputLow, 1: InpuHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InputVal
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgReg
+ );
+
+ *InputVal = (PadCfgReg & B_PCH_GPIO_RX_STATE) >> N_PCH_GPIO_RX_STATE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO IOxAPIC interrupt number
+
+ @param[in] GpioPad GPIO pad
+ @param[out] IrqNum IRQ number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadIoApicIrqNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *IrqNum
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 1,
+ &PadCfgReg
+ );
+
+ *IrqNum = (PadCfgReg & B_PCH_GPIO_INTSEL) >> N_PCH_GPIO_INTSEL;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will configure GPIO input inversion
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for GPIO input inversion
+ 0: No input inversion, 1: Invert input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetInputInversion (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ )
+{
+ if (Value > 1) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_PCH_GPIO_RXINV,
+ Value << N_PCH_GPIO_RXINV
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO pad input inversion value
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InvertState GPIO inversion state
+ 0: No input inversion, 1: Inverted input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputInversion (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InvertState
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgReg
+ );
+
+ *InvertState = (PadCfgReg & B_PCH_GPIO_RXINV) >> N_PCH_GPIO_RXINV;
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set GPIO interrupt settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Level/Edge
+ use GPIO_INT_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadInterruptConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_INT_CONFIG Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RxLvlEdgeValue;
+ UINT32 IntRouteValue;
+ UINT32 PadNumber;
+ UINT32 GpeEnable;
+ UINT32 NmiEnable;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EFI_SUCCESS;
+
+ if (((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) != GpioHardwareDefault) {
+ RxLvlEdgeValue = ((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_PCH_GPIO_RX_LVL_EDG;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_PCH_GPIO_RX_LVL_EDG,
+ RxLvlEdgeValue
+ );
+ }
+
+ if (((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) != GpioHardwareDefault) {
+
+ IntRouteValue = ((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_PCH_GPIO_RX_NMI_ROUTE;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~(B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE),
+ IntRouteValue
+ );
+
+ if ((Value & GpioIntSci) == GpioIntSci) {
+ GpeEnable = 0x1;
+ } else {
+ GpeEnable = 0x0;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioWriteReg (
+ GpioGpeEnableRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ ~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
+ GpeEnable << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if ((Value & GpioIntNmi) == GpioIntNmi) {
+ NmiEnable = 0x1;
+ } else {
+ NmiEnable = 0x0;
+ }
+
+ Status = GpioWriteReg (
+ GpioNmiEnableRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ ~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
+ NmiEnable << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+ if (Status == EFI_UNSUPPORTED) {
+ if (NmiEnable == 0) {
+ //
+ // Not all GPIO have NMI capabilities. Since we always try to program this register,
+ // even when not enabling NMI for a pad so do not report such access as an error
+ //
+ return EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting NMI\n", GpioGetGroupIndexFromGpioPad (GpioPad)));
+ }
+ }
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ This procedure will set GPIO electrical settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of termination
+ use GPIO_ELECTRICAL_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadElectricalConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_ELECTRICAL_CONFIG Value
+ )
+{
+ UINT32 TermValue;
+ UINT32 PadTolValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) != GpioHardwareDefault) {
+ TermValue = ((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) << N_PCH_GPIO_TERM;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 1,
+ (UINT32)~B_PCH_GPIO_TERM,
+ TermValue
+ );
+ }
+
+ if (((Value & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS) != GpioHardwareDefault) {
+ PadTolValue = ((Value & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS + 1)) << N_PCH_GPIO_PADTOL;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 1,
+ (UINT32)~B_PCH_GPIO_PADTOL,
+ PadTolValue
+ );
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for Pad Reset Configuration
+ use GPIO_RESET_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadRstCfg;
+
+ Status = EFI_SUCCESS;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (((Value & B_GPIO_RESET_CONFIG_RESET_MASK) >> N_GPIO_RESET_CONFIG_RESET_BIT_POS) != GpioHardwareDefault) {
+
+ //
+ // Reset configuration depends on group type.
+ // This field requires support for new and deprecated settings.
+ //
+ Status = GpioPadRstCfgFromResetConfig (
+ GpioPad,
+ Value,
+ &PadRstCfg
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_PCH_GPIO_RST_CONF,
+ PadRstCfg << N_PCH_GPIO_RST_CONF
+ );
+ }
+ return Status;
+}
+
+/**
+ This procedure will get GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Pad Reset Configuration
+ based on GPIO_RESET_CONFIG
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG *Value
+ )
+{
+ UINT32 PadRstCfg;
+ UINT32 PadCfgDw0Reg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgDw0Reg
+ );
+
+ //
+ // Get Reset Type (PadRstCfg)
+ //
+ PadRstCfg = (PadCfgDw0Reg & B_PCH_GPIO_RST_CONF) >> N_PCH_GPIO_RST_CONF;
+
+ *Value = GpioResetConfigFromPadRstCfg (
+ GpioPad,
+ PadRstCfg
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO Host Software Pad Ownership for certain group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Host Ownership register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] HostSwRegVal Value of Host Software Pad Ownership register
+ Bit position - PadNumber
+ Bit value - 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *HostSwRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioReadReg (
+ GpioHostOwnershipRegister,
+ Group,
+ DwNum,
+ HostSwRegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get GPIO Host Software Pad Ownership for certain group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Host Ownership register number for current group
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] HostSwRegVal Value of Host Software Pad Ownership register
+ Bit position - PadNumber
+ Bit value - 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 HostSwRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioWriteReg (
+ GpioHostOwnershipRegister,
+ Group,
+ DwNum,
+ 0,
+ HostSwRegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadHostSwOwn Value of Host Software Pad Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadHostSwOwn
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadNumber;
+ UINT32 HostSwRegVal;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioReadReg (
+ GpioHostOwnershipRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ &HostSwRegVal
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *PadHostSwOwn = (HostSwRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
+
+ return Status;
+}
+
+/**
+ This procedure will set Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadHostSwOwn Pad Host Software Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadHostSwOwn
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadNumber;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioWriteReg (
+ GpioHostOwnershipRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ ~0u,
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get Gpio Pad Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadOwnVal Value of Pad Ownership
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadOwnership (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_OWN *PadOwnVal
+ )
+{
+ UINT32 Mask;
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 PadOwnRegValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Calculate RegOffset using Pad Ownership offset and GPIO Pad number.
+ // One DWord register contains information for 8 pads.
+ //
+ RegOffset = GpioGroupInfo[GroupIndex].PadOwnOffset + (PadNumber >> 3) * 0x4;
+
+ //
+ // Calculate pad bit position within DWord register
+ //
+ PadNumber %= 8;
+ Mask = (BIT1 | BIT0) << (PadNumber * 4);
+
+ PadOwnRegValue = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
+
+ *PadOwnVal = (GPIO_PAD_OWN) ((PadOwnRegValue & Mask) >> (PadNumber * 4));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will check state of Pad Config Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockRegVal Value of PadCfgLock register
+ Bit position - PadNumber
+ Bit value - 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioReadReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ PadCfgLockRegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will check state of Pad Config Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLock for selected pad
+ 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLock (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLock
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadNumber;
+ UINT32 PadCfgLockRegVal;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioReadReg (
+ GpioPadConfigLockRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ &PadCfgLockRegVal
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *PadCfgLock = (PadCfgLockRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
+
+ return Status;
+}
+
+/**
+ This procedure will check state of Pad Config Tx Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockTxRegVal Value of PadCfgLockTx register
+ Bit position - PadNumber
+ Bit value - 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockTxRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioReadReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ PadCfgLockTxRegVal
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will check state of Pad Config Tx Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLockTx for selected pad
+ 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLockTx (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLockTx
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadNumber;
+ UINT32 PadCfgLockTxRegVal;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioReadReg (
+ GpioPadLockOutputRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ &PadCfgLockTxRegVal
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *PadCfgLockTx = (PadCfgLockTxRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
+
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLock for selected pads within one group.
+ This function should be used only inside SMI.
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlock Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnlock, 1: Unlock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlock
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioWriteLockReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ ~PadsToUnlock,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLock for selected pad.
+ This function should be used only inside SMI.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfg (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioUnlockPadCfgForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLock for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLock Bitmask for pads which are going to be locked
+ Bit position - PadNumber
+ Bit value - 0: DoNotLock, 1: Lock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLock
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioWriteLockReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ ~0u,
+ PadsToLock
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLock for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioLockPadCfg (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioLockPadCfgForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLockTx for selected pads within one group.
+ This function should be used only inside SMI.
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlockTx Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlockTx
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioWriteLockReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ ~PadsToUnlockTx,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLockTx for selected pad.
+ This function should be used only inside SMI.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioUnlockPadCfgTxForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLockTx for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLockTx Bitmask for pads which are going to be locked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLockTx
+ )
+{
+ EFI_STATUS Status;
+
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioWriteLockReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ ~0u,
+ PadsToLockTx
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLockTx for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioLockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ Status = GpioLockPadCfgTxForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+
+/**
+ This procedure will get Group to GPE mapping.
+
+ @param[out] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[out] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[out] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGroupToGpeDwX (
+ IN GPIO_GROUP *GroupToGpeDw0,
+ IN GPIO_GROUP *GroupToGpeDw1,
+ IN GPIO_GROUP *GroupToGpeDw2
+ )
+{
+ UINT32 Data32;
+ UINT32 PchPwrmBase;
+ GPIO_GROUP GpioGroupOffset;
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ Data32 = MmioRead32 ((UINTN) (PchPwrmBase + R_PCH_PWRM_GPIO_CFG));
+
+ *GroupToGpeDw0 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW0) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW0) + GpioGroupOffset;
+ *GroupToGpeDw1 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW1) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW1) + GpioGroupOffset;
+ *GroupToGpeDw2 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW2) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW2) + GpioGroupOffset;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set Group to GPE mapping.
+
+ @param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetGroupToGpeDwX (
+ IN GPIO_GROUP GroupToGpeDw0,
+ IN GPIO_GROUP GroupToGpeDw1,
+ IN GPIO_GROUP GroupToGpeDw2
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT32 PchPwrmBase;
+ GPIO_GROUP GpioGroupLowest;
+ GPIO_GROUP GpioGroupHighest;
+
+ GpioGroupLowest = GpioGetLowestGroup ();
+ GpioGroupHighest = GpioGetHighestGroup ();
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if (((UINT32) GroupToGpeDw0 < GpioGroupLowest) || ((UINT32) GroupToGpeDw0 > GpioGroupHighest) ||
+ ((UINT32) GroupToGpeDw1 < GpioGroupLowest) || ((UINT32) GroupToGpeDw1 > GpioGroupHighest) ||
+ ((UINT32) GroupToGpeDw2 < GpioGroupLowest) || ((UINT32) GroupToGpeDw2 > GpioGroupHighest)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument exceeds GPIO group range\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if each group number is unique
+ //
+ if ((GroupToGpeDw0 == GroupToGpeDw1) ||
+ (GroupToGpeDw0 == GroupToGpeDw2) ||
+ (GroupToGpeDw1 == GroupToGpeDw2)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Values in GPE0_DWx registers are 0 based (GPP_A = 0h)
+ //
+ GroupToGpeDw0 = GpioGetGroupIndexFromGroup (GroupToGpeDw0);
+ GroupToGpeDw1 = GpioGetGroupIndexFromGroup (GroupToGpeDw1);
+ GroupToGpeDw2 = GpioGetGroupIndexFromGroup (GroupToGpeDw2);
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ //
+ // Program GPIO_CFG (PMRMBASE + 120h) register
+ //
+ Data32And = (UINT32) ~(B_PCH_PWRM_GPIO_CFG_GPE0_DW2 | B_PCH_PWRM_GPIO_CFG_GPE0_DW1 | B_PCH_PWRM_GPIO_CFG_GPE0_DW0);
+ Data32Or = (UINT32) ((GroupToGpeDw2 << N_PCH_PWRM_GPIO_CFG_GPE0_DW2) |
+ (GroupToGpeDw1 << N_PCH_PWRM_GPIO_CFG_GPE0_DW1) |
+ (GroupToGpeDw0 << N_PCH_PWRM_GPIO_CFG_GPE0_DW0));
+
+ MmioAndThenOr32 (
+ (PchPwrmBase + R_PCH_PWRM_GPIO_CFG),
+ Data32And,
+ Data32Or
+ );
+
+ Data32And = (UINT32) ~(B_PCH_PCR_GPIO_MISCCFG_GPE0_DW2 | B_PCH_PCR_GPIO_MISCCFG_GPE0_DW1 | B_PCH_PCR_GPIO_MISCCFG_GPE0_DW0);
+ Data32Or = (UINT32) ((GroupToGpeDw2 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW2) |
+ (GroupToGpeDw1 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW1) |
+ (GroupToGpeDw0 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW0));
+ //
+ // Program MISCCFG register for Community 0
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM0, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 1
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM1, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 2
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM2, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 3
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM3, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPE number for provided GpioPad.
+ PCH allows to configure mapping between GPIO groups and related GPE (GpioSetGroupToGpeDwX())
+ what results in the fact that certain Pad can cause different General Purpose Event. Only three
+ GPIO groups can be mapped to cause unique GPE (1-tier), all others groups will be under one common
+ event (GPE_111 for 2-tier).
+
+ 1-tier:
+ Returned GpeNumber is in range <0,95>. GpioGetGpeNumber() can be used
+ to determine what _LXX ACPI method would be called on event on selected GPIO pad
+
+ 2-tier:
+ Returned GpeNumber is 0x6F (111). All GPIO pads which are not mapped to 1-tier GPE
+ will be under one master GPE_111 which is linked to _L6F ACPI method. If it is needed to determine
+ what Pad from 2-tier has caused the event, _L6F method should check GPI_GPE_STS and GPI_GPE_EN
+ registers for all GPIO groups not mapped to 1-tier GPE.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpeNumber GPE number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpeNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *GpeNumber
+ )
+{
+ GPIO_GROUP GroupToGpeDw0;
+ GPIO_GROUP GroupToGpeDw1;
+ GPIO_GROUP GroupToGpeDw2;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get GPIO groups mapping to 1-tier GPE
+ // This mapping is dependent on GPIO IP implementation
+ // and may change between chipset generations
+ //
+ GpioGetGroupToGpeDwX (&GroupToGpeDw0,&GroupToGpeDw1,&GroupToGpeDw2);
+
+ if (Group == GroupToGpeDw0) {
+ *GpeNumber = PadNumber;
+ } else if (Group == GroupToGpeDw1) {
+ *GpeNumber = PadNumber + 32;
+ } else if (Group == GroupToGpeDw2) {
+ *GpeNumber = PadNumber + 64;
+ } else {
+ //
+ // If Group number doesn't match any of above then
+ // it means than certain pad is routed to 2-tier GPE
+ // which all are under GPE_111 (0x6F)
+ //
+ *GpeNumber = PCH_GPIO_2_TIER_MASTER_GPE_NUMBER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to clear SMI STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiSmiSts (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ //
+ // Clear GPI SMI Status bit by writing '1'
+ //
+ Status = GpioWriteReg (
+ GpioSmiStatusRegister,
+ Group,
+ DwNum,
+ 0u,
+ (UINT32) (BIT0 << PadBitPosition)
+ );
+
+ return Status;
+}
+
+/**
+ This procedure is used by PchSmiDispatcher and will clear
+ all GPI SMI Status bits
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearAllGpiSmiSts (
+ VOID
+ )
+{
+ UINT32 DwNum;
+ GPIO_GROUP Group;
+ GPIO_GROUP GroupMin;
+ GPIO_GROUP GroupMax;
+
+ GroupMin = GpioGetLowestGroup ();
+ GroupMax = GpioGetHighestGroup ();
+
+ for (Group = GroupMin; Group <= GroupMax; Group++) {
+ //
+ // Disable all GPI SMI
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) {
+ GpioWriteReg (
+ GpioSmiStatusRegister,
+ Group,
+ DwNum,
+ 0u,
+ 0xFFFFFFFF
+ );
+ }
+ }
+ return EFI_SUCCESS;
+
+}
+
+/**
+ This procedure is used to disable all GPI SMI
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioDisableAllGpiSmi (
+ VOID
+ )
+{
+ UINT32 DwNum;
+ GPIO_GROUP Group;
+ GPIO_GROUP GroupMin;
+ GPIO_GROUP GroupMax;
+
+ GroupMin = GpioGetLowestGroup ();
+ GroupMax = GpioGetHighestGroup ();
+
+ for (Group = GroupMin; Group <= GroupMax; Group++) {
+ //
+ // Disable all GPI SMI
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) {
+ GpioWriteReg (
+ GpioSmiEnableRegister,
+ Group,
+ DwNum,
+ 0u,
+ 0u
+ );
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to register GPI SMI dispatch function.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpiNum GPI number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiSmiNum (
+ IN GPIO_PAD GpioPad,
+ OUT UINTN *GpiNum
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 Index;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ *GpiNum = 0;
+
+ for (Index = 0; Index < GroupIndex; Index++) {
+ *GpiNum += (UINTN) (GpioGroupInfo[Index].PadPerGroup);
+ }
+ *GpiNum += (UINTN) PadNumber;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to check GPIO inputs belongs to 2 tier or 1 tier architecture
+
+ @param[in] GpioPad GPIO pad
+
+ @retval Data 0 means 1-tier, 1 means 2-tier
+**/
+BOOLEAN
+GpioCheckFor2Tier (
+ IN GPIO_PAD GpioPad
+ )
+{
+ UINT32 Data32;
+
+ GpioGetGpeNumber (GpioPad, &Data32);
+ if (Data32 == PCH_GPIO_2_TIER_MASTER_GPE_NUMBER) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ This procedure is used to clear GPE STS for a specified GpioPad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiGpeSts (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check for 2-tier
+ //
+ if (!(GpioCheckFor2Tier (GpioPad))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ //
+ // Clear GPI GPE Status bit by writing '1'
+ //
+ Status = GpioWriteReg (
+ GpioGpeStatusRegister,
+ Group,
+ DwNum,
+ 0u,
+ (UINT32) (BIT0 << PadBitPosition)
+ );
+
+ return Status;
+}
+
+/**
+ This procedure is used to read GPE STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] Data GPE STS data
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiGpeSts (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *Data
+ )
+{
+ EFI_STATUS Status;
+ UINT32 GpeStsRegVal;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check for 2-tier
+ //
+ if (!(GpioCheckFor2Tier (GpioPad))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ //
+ // Read GPI GPE Status bits
+ //
+ Status = GpioReadReg (
+ GpioGpeStatusRegister,
+ Group,
+ DwNum,
+ &GpeStsRegVal
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Data = (GpeStsRegVal >> PadBitPosition) & 0x1;
+
+ return Status;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h
new file mode 100644
index 0000000000..97a5287067
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h
@@ -0,0 +1,327 @@
+/** @file
+ Header file for GPIO Lib implementation.
+
+Copyright (c) 2017, 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 that 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 _GPIO_LIBRARY_H_
+#define _GPIO_LIBRARY_H_
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <GpioPinsSklLp.h>
+#include <GpioPinsSklH.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchSbiAccessLib.h>
+
+typedef struct {
+ GPIO_PAD Pad;
+ GPIO_PAD_MODE Mode;
+} GPIO_PAD_NATIVE_FUNCTION;
+
+
+// BIT15-0 - pad number
+// BIT31-16 - group info
+// BIT23- 16 - group index
+// BIT31- 24 - chipset ID
+#define PAD_INFO_MASK 0x0000FFFF
+#define GROUP_INFO_POSITION 16
+#define GROUP_INFO_MASK 0xFFFF0000
+#define GROUP_INDEX_MASK 0x00FF0000
+#define UNIQUE_ID_MASK 0xFF000000
+#define UNIQUE_ID_POSITION 24
+
+#define GPIO_PAD_DEF(Group,Pad) (UINT32)(((Group) << 16) + (Pad))
+#define GPIO_GROUP_DEF(Index,ChipsetId) ((Index) | ((ChipsetId) << 8))
+#define GPIO_GET_GROUP_INDEX(Group) ((Group) & 0xFF)
+#define GPIO_GET_GROUP_FROM_PAD(Pad) ((Pad) >> 16)
+#define GPIO_GET_GROUP_INDEX_FROM_PAD(Pad) GPIO_GET_GROUP_INDEX (((Pad) >> 16))
+#define GPIO_GET_PAD_NUMBER(Pad) ((Pad) & 0xFFFF)
+#define GPIO_GET_CHIPSET_ID(Pad) ((Pad) >> 24)
+
+#define GPIO_GET_PAD_POSITION(PadNumber) ((PadNumber) % 32)
+#define GPIO_GET_DW_NUM(PadNumber) ((PadNumber) / 32)
+
+//
+// Unique ID used in GpioPad defines
+//
+#define GPIO_SKL_H_CHIPSET_ID 0x1
+#define GPIO_SKL_LP_CHIPSET_ID 0x2
+
+//
+// Below defines are based on GPIO_CONFIG structure fields
+//
+#define B_GPIO_PAD_MODE_MASK 0xF
+#define N_GPIO_PAD_MODE_BIT_POS 0
+#define B_GPIO_HOSTSW_OWN_MASK 0x3
+#define N_GPIO_HOSTSW_OWN_BIT_POS 0
+#define B_GPIO_DIRECTION_MASK 0x1F
+#define B_GPIO_DIRECTION_DIR_MASK 0x7
+#define N_GPIO_DIRECTION_DIR_BIT_POS 0
+#define B_GPIO_DIRECTION_INV_MASK 0x18
+#define N_GPIO_DIRECTION_INV_BIT_POS 3
+#define B_GPIO_OUTPUT_MASK 0x3
+#define N_GPIO_OUTPUT_BIT_POS 0
+#define N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS 0
+#define N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS 5
+#define B_GPIO_RESET_CONFIG_RESET_MASK 0x3F
+#define N_GPIO_RESET_CONFIG_OLD_RESET_TYPE BIT1
+#define B_GPIO_RESET_CONFIG_OLD_RESET_MASK 0xF
+#define N_GPIO_RESET_CONFIG_RESET_BIT_POS 0
+#define B_GPIO_RESET_CONFIG_GPD_RESET_MASK (BIT5 | BIT4)
+#define B_GPIO_RESET_CONFIG_GPP_RESET_MASK (BIT3 | BIT2)
+#define N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS 0
+#define N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS 5
+#define N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS 0
+
+//
+// Structure for storing information about registers offset, community,
+// maximal pad number for available groups
+//
+typedef struct {
+ PCH_SBI_PID Community;
+ UINT32 PadOwnOffset;
+ UINT32 HostOwnOffset;
+ UINT32 GpiIsOffset;
+ UINT32 GpiIeOffset;
+ UINT32 GpiGpeStsOffset;
+ UINT32 GpiGpeEnOffset;
+ UINT32 SmiStsOffset;
+ UINT32 SmiEnOffset;
+ UINT32 NmiStsOffset;
+ UINT32 NmiEnOffset;
+ UINT32 PadCfgLockOffset;
+ UINT32 PadCfgLockTxOffset;
+ UINT32 PadCfgOffset;
+ UINT32 PadPerGroup;
+} GPIO_GROUP_INFO;
+
+//
+// If in GPIO_GROUP_INFO structure certain register doesn't exist
+// it will have value equal to NO_REGISTER_FOR_PROPERTY
+//
+#define NO_REGISTER_FOR_PROPERTY (~0u)
+
+//
+// PADCFG register is split into multiple DW registers
+// PAD_CFG_SIZE holds number of bytes used by all those registers for one pad
+//
+#define PAD_CFG_SIZE 0x08
+
+/**
+ This procedure is used to check if GpioPad is valid for certain chipset
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE This pin is valid on this chipset
+ FALSE Incorrect pin
+**/
+BOOLEAN
+GpioIsCorrectPadForThisChipset (
+ IN GPIO_PAD GpioPad
+ );
+
+
+/**
+ This procedure will retrieve address and length of GPIO info table
+
+ @param[out] GpioGroupInfoTableLength Length of GPIO group table
+
+ @retval Pointer to GPIO group table
+
+**/
+GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINTN *GpioGroupInfoTableLength
+ );
+
+/**
+ This procedure will check if GpioPad is owned by host.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is owned by host
+ @retval FALSE GPIO pad is not owned by host and should not be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadHostOwned (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will check if GpioPad argument is valid.
+ Function will check below conditions:
+ - GpioPad represents a pad for current PCH
+ - GpioPad belongs to valid GpioGroup
+ - GPIO PadNumber is not greater than number of pads for this group
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is valid and can be used with GPIO lib API
+ @retval FALSE GPIO pad is invalid and cannot be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadValid (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[out] PadCfgRegValue Read data
+
+ @retval none
+**/
+VOID
+GpioReadPadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ OUT UINT32 *PadCfgRegValue
+ );
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[in] PadCfgAndMask Mask to be AND'ed with PADCFG reg value
+ @param[in] PadCfgOrMask Mask to be OR'ed with PADCFG reg value
+
+ @retval none
+**/
+VOID
+GpioWritePadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ IN UINT32 PadCfgAndMask,
+ IN UINT32 PadCfgOrMask
+ );
+
+/**
+ This procedure will set GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+SetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadModeValue
+ );
+
+/**
+ This procedure will get GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_MODE *PadModeValue
+ );
+
+/**
+ This function checks if GPIO pin is a GSPI chip select pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsGpioPadAGSpiCsbPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ );
+
+/**
+ This function checks if GPIO pin is a SataDevSlp pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsPadASataDevSlpPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ );
+
+/**
+ This internal procedure will calculate GPIO_RESET_CONFIG value (new type)
+ based on provided PadRstCfg for a specific GPIO Pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] PadRstCfg GPIO PadRstCfg value
+
+ @retval GpioResetConfig GPIO Reset configuration (new type)
+**/
+GPIO_RESET_CONFIG
+GpioResetConfigFromPadRstCfg (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadRstCfg
+ );
+
+/**
+ This internal procedure will calculate PadRstCfg register value based
+ on provided GPIO Reset configuration for a certain pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioResetConfig GPIO Reset configuration
+ @param[out] PadRstCfg GPIO PadRstCfg value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid configuration
+**/
+EFI_STATUS
+GpioPadRstCfgFromResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG GpioResetConfig,
+ OUT UINT32 *PadRstCfg
+ );
+
+/**
+ This procedure will calculate PADCFG register value based on GpioConfig data
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioConfig GPIO Configuration data
+ @param[out] PadCfgDwReg PADCFG DWx register value
+ @param[out] PadCfgDwRegMask Mask with PADCFG DWx register bits to be modified
+
+ @retval Status
+**/
+EFI_STATUS
+GpioPadCfgRegValueFromGpioConfig (
+ IN GPIO_PAD GpioPad,
+ IN CONST GPIO_CONFIG *GpioConfig,
+ OUT UINT32 *PadCfgDwReg,
+ OUT UINT32 *PadCfgDwRegMask
+ );
+#endif // _GPIO_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
new file mode 100644
index 0000000000..e57e3ecbfa
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
@@ -0,0 +1,685 @@
+/** @file
+ This file contains routines for GPIO native and chipset specific usage
+
+Copyright (c) 2017, 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 that 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 "GpioLibrary.h"
+
+//
+// Chipset specific data
+//
+//SerialIo
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpI2cGpio[PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHI2cGpio[PCH_H_SERIALIO_MAX_I2C_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpUartGpio[PCH_SERIALIO_MAX_UART_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHUartGpio[PCH_SERIALIO_MAX_UART_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpSpiGpio[PCH_SERIALIO_MAX_SPI_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHSpiGpio[PCH_SERIALIO_MAX_SPI_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
+
+//SATA
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpSataPortResetToGpioMap[PCH_LP_AHCI_MAX_PORTS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHSataPortResetToGpioMap[PCH_H_AHCI_MAX_PORTS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpSataDevSlpPinToGpioMap[PCH_LP_AHCI_MAX_PORTS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHSataDevSlpPinToGpioMap[PCH_H_AHCI_MAX_PORTS];
+
+//
+// SKL specific
+//
+extern GPIO_GROUP_INFO mPchLpGpioGroupInfo[V_PCH_LP_GPIO_GROUP_MAX];
+extern GPIO_GROUP_INFO mPchHGpioGroupInfo[V_PCH_H_GPIO_GROUP_MAX];
+
+/**
+ This procedure will set GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+SetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadModeValue
+ )
+{
+ UINT32 PadCfgOrMask;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (PadModeValue != (GPIO_PAD_MODE)GpioHardwareDefault) {
+
+ PadCfgOrMask = (((PadModeValue & B_GPIO_PAD_MODE_MASK) >> (N_GPIO_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE);
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_PCH_GPIO_PAD_MODE,
+ PadCfgOrMask
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_MODE *PadModeValue
+ )
+{
+ UINT32 PadCfgRegValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioReadPadCfgReg (
+ GpioPad,
+ 0,
+ &PadCfgRegValue
+ );
+
+ *PadModeValue = (GPIO_PAD_MODE)(((PadCfgRegValue & B_PCH_GPIO_PAD_MODE) >> (N_PCH_GPIO_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE_BIT_POS));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure will retrieve address and length of GPIO info table
+
+ @param[out] GpioGroupInfoTableLength Length of GPIO group table
+
+ @retval Pointer to GPIO group table
+
+**/
+GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINTN *GpioGroupInfoTableLength
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ *GpioGroupInfoTableLength = sizeof (mPchLpGpioGroupInfo) / sizeof (GPIO_GROUP_INFO);
+ return mPchLpGpioGroupInfo;
+ } else {
+ *GpioGroupInfoTableLength = sizeof (mPchHGpioGroupInfo) / sizeof (GPIO_GROUP_INFO);
+ return mPchHGpioGroupInfo;
+ }
+}
+
+
+/**
+ This procedure is used to check if GpioPad is valid for certain chipset
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE This pin is valid on this chipset
+ FALSE Incorrect pin
+**/
+BOOLEAN
+GpioIsCorrectPadForThisChipset (
+ IN GPIO_PAD GpioPad
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if ((PchSeries == PchH) && (GPIO_GET_CHIPSET_ID (GpioPad) == GPIO_SKL_H_CHIPSET_ID)) {
+ return TRUE;
+ } else if ((PchSeries == PchLp) && (GPIO_GET_CHIPSET_ID (GpioPad) == GPIO_SKL_LP_CHIPSET_ID)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ This procedure will get number of pads for certain GPIO group
+
+ @param[in] Group GPIO group number
+
+ @retval Value Pad number for group
+ If illegal group number then return 0
+**/
+UINT32
+GpioGetPadPerGroup (
+ IN GPIO_GROUP Group
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ ASSERT (FALSE);
+ return 0;
+ } else {
+ return GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+}
+
+/**
+ This procedure will get number of groups
+
+ @param[in] none
+
+ @retval Value Group number
+**/
+UINT8
+GpioGetNumberOfGroups (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return V_PCH_LP_GPIO_GROUP_MAX;
+ } else {
+ return V_PCH_H_GPIO_GROUP_MAX;
+ }
+}
+/**
+ This procedure will get lowest group
+
+ @param[in] none
+
+ @retval Value Lowest Group
+**/
+GPIO_GROUP
+GpioGetLowestGroup (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return (UINT32) GPIO_SKL_LP_GROUP_GPP_A;
+ } else {
+ return (UINT32) GPIO_SKL_H_GROUP_GPP_A;
+ }
+}
+/**
+ This procedure will get highest group
+
+ @param[in] none
+
+ @retval Value Highest Group
+**/
+GPIO_GROUP
+GpioGetHighestGroup (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return (UINT32) GPIO_SKL_LP_GROUP_GPD;
+ } else {
+ return (UINT32) GPIO_SKL_H_GROUP_GPD;
+ }
+}
+
+/**
+ This procedure will get group number
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group number
+**/
+GPIO_GROUP
+GpioGetGroupFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return GPIO_GET_GROUP_FROM_PAD (GpioPad);
+}
+
+/**
+ This procedure will get group index (0 based)
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return (UINT32) GPIO_GET_GROUP_INDEX_FROM_PAD (GpioPad);
+}
+
+/**
+ This procedure will get group index (0 based) from group
+
+ @param[in] GpioGroup Gpio Group
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGroup (
+ IN GPIO_GROUP GpioGroup
+ )
+{
+ return (UINT32) GPIO_GET_GROUP_INDEX (GpioGroup);
+}
+
+/**
+ This procedure will get pad number (0 based) from Gpio Pad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Pad Number
+**/
+UINT32
+GpioGetPadNumberFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return (UINT32) GPIO_GET_PAD_NUMBER (GpioPad);
+}
+/**
+ This procedure will return GpioPad from Group and PadNumber
+
+ @param[in] Group GPIO group
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupAndPadNumber (
+ IN GPIO_GROUP Group,
+ IN UINT32 PadNumber
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return GPIO_PAD_DEF (Group,PadNumber);
+ } else {
+ return GPIO_PAD_DEF (Group,PadNumber);
+ }
+}
+
+/**
+ This procedure will return GpioPad from GroupIndex and PadNumber
+
+ @param[in] GroupIndex GPIO GroupIndex
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupIndexAndPadNumber (
+ IN UINT32 GroupIndex,
+ IN UINT32 PadNumber
+ )
+{
+ GPIO_GROUP Group;
+
+ if (GetPchSeries () == PchLp) {
+ Group = GPIO_GROUP_DEF (GroupIndex, GPIO_SKL_LP_CHIPSET_ID);
+ return GPIO_PAD_DEF (Group,PadNumber);
+ } else {
+ Group = GPIO_GROUP_DEF (GroupIndex, GPIO_SKL_H_CHIPSET_ID);
+ return GPIO_PAD_DEF (Group,PadNumber);
+ }
+}
+
+
+/**
+ This function sets SerialIo I2C controller pins into native mode
+
+ @param[in] SerialIoI2cControllerNumber I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoI2cPinsIntoNativeMode (
+ IN UINT32 SerialIoI2cControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION (*I2cGpio) [PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (SerialIoI2cControllerNumber < PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS);
+ I2cGpio = mPchLpI2cGpio;
+ } else {
+ ASSERT (SerialIoI2cControllerNumber < PCH_H_SERIALIO_MAX_I2C_CONTROLLERS);
+ I2cGpio = mPchHI2cGpio;
+ }
+
+ for (Index = 0; Index < PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (I2cGpio[SerialIoI2cControllerNumber][Index].Pad, I2cGpio[SerialIoI2cControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ GpioSetInputInversion (I2cGpio[SerialIoI2cControllerNumber][Index].Pad, 0);
+ }
+ return Status;
+}
+
+/**
+ This function sets SerialIo I2C controller pins tolerance
+
+ @param[in] SerialIoI2CControllerNumber I2C controller
+ @param[in] Pad1v8Tolerance TRUE: Enable 1v8 Pad tolerance
+ FALSE: Disable 1v8 Pad tolerance
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoI2CPinsTolerance (
+ IN UINT32 SerialIoI2cControllerNumber,
+ IN BOOLEAN Pad1v8Tolerance
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_OWN PadOwnership;
+ GPIO_PAD_NATIVE_FUNCTION (*I2cGpio) [PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
+ GPIO_CONFIG GpioData;
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (SerialIoI2cControllerNumber < PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS);
+ I2cGpio = mPchLpI2cGpio;
+ } else {
+ ASSERT (SerialIoI2cControllerNumber < PCH_H_SERIALIO_MAX_I2C_CONTROLLERS);
+ I2cGpio = mPchHI2cGpio;
+ }
+
+ ZeroMem (&GpioData, sizeof (GPIO_CONFIG));
+ if (Pad1v8Tolerance) {
+ GpioData.ElectricalConfig = GpioTolerance1v8;
+ } else {
+ GpioData.ElectricalConfig = GpioNoTolerance1v8;
+ }
+ for (Index = 0; Index < PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER; Index++) {
+ GpioGetPadOwnership (I2cGpio[SerialIoI2cControllerNumber][Index].Pad , &PadOwnership);
+ if (PadOwnership == GpioPadOwnHost) {
+ Status = GpioSetPadConfig (I2cGpio[SerialIoI2cControllerNumber][Index].Pad, &GpioData);
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+
+/**
+ This function sets SerialIo UART controller pins into native mode
+
+ @param[in] SerialIoI2CControllerNumber UART controller
+ @param[in] HardwareFlowControl Hardware Flow control
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoUartPinsIntoNativeMode (
+ IN UINT32 SerialIoUartControllerNumber,
+ IN BOOLEAN HardwareFlowControl
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN PinsUsed;
+ GPIO_PAD_NATIVE_FUNCTION (*UartGpio) [PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ ASSERT (SerialIoUartControllerNumber < PCH_SERIALIO_MAX_UART_CONTROLLERS);
+
+ if (GetPchSeries () == PchLp) {
+ UartGpio = mPchLpUartGpio;
+ } else {
+ UartGpio = mPchHUartGpio;
+ }
+
+ if (HardwareFlowControl) {
+ PinsUsed = PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER;
+ } else {
+ PinsUsed = PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER_NO_FLOW_CTRL;
+ }
+
+ for (Index = 0; Index < PinsUsed; Index++) {
+ Status = SetGpioPadMode (UartGpio[SerialIoUartControllerNumber][Index].Pad, UartGpio[SerialIoUartControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ GpioSetInputInversion (UartGpio[SerialIoUartControllerNumber][Index].Pad, 0);
+ }
+ return Status;
+}
+
+/**
+ This function sets SerialIo SPI controller pins into native mode
+
+ @param[in] SerialIoI2CControllerNumber SPI controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetSerialIoSpiPinsIntoNativeMode (
+ IN UINT32 SerialIoSpiControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION (*SpiGpio) [PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ ASSERT (SerialIoSpiControllerNumber < PCH_SERIALIO_MAX_SPI_CONTROLLERS);
+
+ if (GetPchSeries () == PchLp) {
+ SpiGpio = mPchLpSpiGpio;
+ } else {
+ SpiGpio = mPchHSpiGpio;
+ }
+
+ for (Index = 0; Index < PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (SpiGpio[SerialIoSpiControllerNumber][Index].Pad, SpiGpio[SerialIoSpiControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ GpioSetInputInversion (SpiGpio[SerialIoSpiControllerNumber][Index].Pad, 0);
+ }
+ return Status;
+}
+
+
+/**
+ This function checks if GPIO pin is a GSPI chip select pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsGpioPadAGSpiCsbPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ )
+{
+ UINT32 ControllerMax;
+ UINT32 ControllerIndex;
+ GPIO_PAD_OWN PadOwnership;
+ GPIO_PAD_NATIVE_FUNCTION (*SpiGpio) [PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
+
+ if (GetPchSeries () == PchLp) {
+ SpiGpio = mPchLpSpiGpio;
+ ControllerMax = sizeof (mPchLpSpiGpio) / sizeof (GPIO_PAD_NATIVE_FUNCTION) / PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER;
+ } else {
+ SpiGpio = mPchHSpiGpio;
+ ControllerMax = sizeof (mPchHSpiGpio) / sizeof (GPIO_PAD_NATIVE_FUNCTION) / PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER;
+ }
+
+ for (ControllerIndex = 0; ControllerIndex < ControllerMax; ControllerIndex++) {
+ if ((GpioPad == SpiGpio[ControllerIndex][0].Pad) &&
+ (PadMode == SpiGpio[ControllerIndex][0].Mode)) {
+ GpioGetPadOwnership (SpiGpio[ControllerIndex][0].Pad , &PadOwnership);
+ if (PadOwnership == GpioPadOwnHost) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ This function checks if GPIO pin for SATA reset port is in GPIO MODE
+
+ @param[in] SataPort SATA port number
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsSataResetPortInGpioMode (
+ IN UINTN SataPort
+ )
+{
+ EFI_STATUS Status;
+ UINT32 GpioPin;
+ GPIO_PAD_MODE GpioMode;
+
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (SataPort < PCH_LP_AHCI_MAX_PORTS);
+ GpioPin = mPchLpSataPortResetToGpioMap[SataPort].Pad;
+ } else {
+ ASSERT (SataPort < PCH_H_AHCI_MAX_PORTS);
+ GpioPin = mPchHSataPortResetToGpioMap[SataPort].Pad;
+ }
+
+ Status = GetGpioPadMode (GpioPin, &GpioMode);
+ if ((EFI_ERROR (Status)) || (GpioMode != GpioPadModeGpio)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+/**
+ This function checks if GPIO pin is a SataDevSlp pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsPadASataDevSlpPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ )
+{
+ UINT32 SataDevSlpPinMax;
+ UINT32 SataDevSlpPinIndex;
+ GPIO_PAD_OWN PadOwnership;
+ GPIO_PAD_NATIVE_FUNCTION *SataDevSlpPinToGpioMap;
+
+ if (GetPchSeries () == PchLp) {
+ SataDevSlpPinToGpioMap = mPchLpSataDevSlpPinToGpioMap;
+ SataDevSlpPinMax = sizeof (mPchLpSataDevSlpPinToGpioMap) /sizeof (GPIO_PAD_NATIVE_FUNCTION);
+ } else {
+ SataDevSlpPinToGpioMap = mPchHSataDevSlpPinToGpioMap;
+ SataDevSlpPinMax = sizeof (mPchHSataDevSlpPinToGpioMap) /sizeof (GPIO_PAD_NATIVE_FUNCTION);
+ }
+
+ for (SataDevSlpPinIndex = 0; SataDevSlpPinIndex < SataDevSlpPinMax; SataDevSlpPinIndex++) {
+ if ((GpioPad == SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Pad) &&
+ (PadMode == SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Mode)) {
+ GpioGetPadOwnership (SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Pad , &PadOwnership);
+ if (PadOwnership == GpioPadOwnHost) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ This function checks if SataDevSlp pin is in native mode
+
+ @param[in] SataPort SATA port
+ @param[out] DevSlpPad DevSlpPad
+
+ @retval TRUE DevSlp is in native mode
+ FALSE DevSlp is not in native mode
+**/
+BOOLEAN
+GpioIsSataDevSlpPinEnabled (
+ IN UINTN SataPort,
+ OUT GPIO_PAD *DevSlpPad
+ )
+{
+ GPIO_PAD_MODE DevSlpPadMode;
+ GPIO_PAD DevSlpGpioPad;
+ GPIO_PAD_MODE GpioMode;
+ EFI_STATUS Status;
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (SataPort < PCH_LP_AHCI_MAX_PORTS);
+ DevSlpGpioPad = mPchLpSataDevSlpPinToGpioMap[SataPort].Pad;
+ DevSlpPadMode = mPchLpSataDevSlpPinToGpioMap[SataPort].Mode;
+ } else {
+ ASSERT (SataPort < PCH_H_AHCI_MAX_PORTS);
+ DevSlpGpioPad = mPchHSataDevSlpPinToGpioMap[SataPort].Pad;
+ DevSlpPadMode = mPchHSataDevSlpPinToGpioMap[SataPort].Mode;
+ }
+
+ Status = GetGpioPadMode (DevSlpGpioPad, &GpioMode);
+
+ if (EFI_ERROR (Status) || (GpioMode != DevSlpPadMode)) {
+ *DevSlpPad = 0x0;
+ return FALSE;
+ } else {
+ *DevSlpPad = DevSlpGpioPad;
+ return TRUE;
+ }
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PchSklGpioData.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PchSklGpioData.c
new file mode 100644
index 0000000000..c36792139c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PchSklGpioData.c
@@ -0,0 +1,190 @@
+/** @file
+ This file contains SKL specific GPIO information
+
+Copyright (c) 2017, 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 that 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 "GpioLibrary.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchLpGpioGroupInfo[] = {
+ {PID_GPIOCOM0, R_PCH_LP_PCR_GPIO_GPP_A_PAD_OWN, R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_A_GPI_IS, R_PCH_PCR_GPIO_GPP_A_GPI_IE, R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_A_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_A_SMI_STS, R_PCH_PCR_GPIO_GPP_A_SMI_EN, R_PCH_PCR_GPIO_GPP_A_NMI_STS, R_PCH_PCR_GPIO_GPP_A_NMI_EN, R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET, V_PCH_GPIO_GPP_A_PAD_MAX}, //SKL PCH-LP GPP_A
+ {PID_GPIOCOM0, R_PCH_LP_PCR_GPIO_GPP_B_PAD_OWN, R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_B_GPI_IS, R_PCH_PCR_GPIO_GPP_B_GPI_IE, R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_B_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_B_SMI_STS, R_PCH_PCR_GPIO_GPP_B_SMI_EN, R_PCH_PCR_GPIO_GPP_B_NMI_STS, R_PCH_PCR_GPIO_GPP_B_NMI_EN, R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET, V_PCH_GPIO_GPP_B_PAD_MAX}, //SKL PCH-LP GPP_B
+ {PID_GPIOCOM1, R_PCH_LP_PCR_GPIO_GPP_C_PAD_OWN, R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_C_GPI_IS, R_PCH_PCR_GPIO_GPP_C_GPI_IE, R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_C_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_C_SMI_STS, R_PCH_PCR_GPIO_GPP_C_SMI_EN, R_PCH_PCR_GPIO_GPP_C_NMI_STS, R_PCH_PCR_GPIO_GPP_C_NMI_EN, R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET, V_PCH_GPIO_GPP_C_PAD_MAX}, //SKL PCH-LP GPP_C
+ {PID_GPIOCOM1, R_PCH_LP_PCR_GPIO_GPP_D_PAD_OWN, R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_D_GPI_IS, R_PCH_PCR_GPIO_GPP_D_GPI_IE, R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_D_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_D_SMI_STS, R_PCH_PCR_GPIO_GPP_D_SMI_EN, R_PCH_PCR_GPIO_GPP_D_NMI_STS, R_PCH_PCR_GPIO_GPP_D_NMI_EN, R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET, V_PCH_GPIO_GPP_D_PAD_MAX}, //SKL PCH-LP GPP_D
+ {PID_GPIOCOM1, R_PCH_LP_PCR_GPIO_GPP_E_PAD_OWN, R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_E_GPI_IS, R_PCH_PCR_GPIO_GPP_E_GPI_IE, R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_E_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_E_SMI_STS, R_PCH_PCR_GPIO_GPP_E_SMI_EN, R_PCH_PCR_GPIO_GPP_E_NMI_STS, R_PCH_PCR_GPIO_GPP_E_NMI_EN, R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET, V_PCH_LP_GPIO_GPP_E_PAD_MAX}, //SKL PCH-LP GPP_E
+ {PID_GPIOCOM3, R_PCH_LP_PCR_GPIO_GPP_F_PAD_OWN, R_PCH_LP_PCR_GPIO_GPP_F_HOSTSW_OWN, R_PCH_LP_PCR_GPIO_GPP_F_GPI_IS, R_PCH_LP_PCR_GPIO_GPP_F_GPI_IE, R_PCH_LP_PCR_GPIO_GPP_F_GPI_GPE_STS,R_PCH_LP_PCR_GPIO_GPP_F_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCKTX, R_PCH_LP_PCR_GPIO_GPP_F_PADCFG_OFFSET, V_PCH_GPIO_GPP_F_PAD_MAX}, //SKL PCH-LP GPP_F
+ {PID_GPIOCOM3, R_PCH_LP_PCR_GPIO_GPP_G_PAD_OWN, R_PCH_LP_PCR_GPIO_GPP_G_HOSTSW_OWN, R_PCH_LP_PCR_GPIO_GPP_G_GPI_IS, R_PCH_LP_PCR_GPIO_GPP_G_GPI_IE, R_PCH_LP_PCR_GPIO_GPP_G_GPI_GPE_STS,R_PCH_LP_PCR_GPIO_GPP_G_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCKTX, R_PCH_LP_PCR_GPIO_GPP_G_PADCFG_OFFSET, V_PCH_LP_GPIO_GPP_G_PAD_MAX}, //SKL PCH-LP GPP_G
+ {PID_GPIOCOM2, R_PCH_LP_PCR_GPIO_GPD_PAD_OWN, R_PCH_PCR_GPIO_GPD_HOSTSW_OWN, R_PCH_PCR_GPIO_GPD_GPI_IS, R_PCH_PCR_GPIO_GPD_GPI_IE, R_PCH_PCR_GPIO_GPD_GPI_GPE_STS, R_PCH_PCR_GPIO_GPD_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCK, R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET, V_PCH_GPIO_GPD_PAD_MAX}, //SKL PCH-LP GPD
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchHGpioGroupInfo[] = {
+ {PID_GPIOCOM0, R_PCH_H_PCR_GPIO_GPP_A_PAD_OWN, R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_A_GPI_IS, R_PCH_PCR_GPIO_GPP_A_GPI_IE, R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_A_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_A_SMI_STS, R_PCH_PCR_GPIO_GPP_A_SMI_EN, R_PCH_PCR_GPIO_GPP_A_NMI_STS, R_PCH_PCR_GPIO_GPP_A_NMI_EN, R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET, V_PCH_GPIO_GPP_A_PAD_MAX}, //SKL PCH-H GPP_A
+ {PID_GPIOCOM0, R_PCH_H_PCR_GPIO_GPP_B_PAD_OWN, R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_B_GPI_IS, R_PCH_PCR_GPIO_GPP_B_GPI_IE, R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_B_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_B_SMI_STS, R_PCH_PCR_GPIO_GPP_B_SMI_EN, R_PCH_PCR_GPIO_GPP_B_NMI_STS, R_PCH_PCR_GPIO_GPP_B_NMI_EN, R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET, V_PCH_GPIO_GPP_B_PAD_MAX}, //SKL PCH-H GPP_B
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_C_PAD_OWN, R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_C_GPI_IS, R_PCH_PCR_GPIO_GPP_C_GPI_IE, R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_C_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_C_SMI_STS, R_PCH_PCR_GPIO_GPP_C_SMI_EN, R_PCH_PCR_GPIO_GPP_C_NMI_STS, R_PCH_PCR_GPIO_GPP_C_NMI_EN, R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET, V_PCH_GPIO_GPP_C_PAD_MAX}, //SKL PCH-H GPP_C
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_D_PAD_OWN, R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_D_GPI_IS, R_PCH_PCR_GPIO_GPP_D_GPI_IE, R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_D_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_D_SMI_STS, R_PCH_PCR_GPIO_GPP_D_SMI_EN, R_PCH_PCR_GPIO_GPP_D_NMI_STS, R_PCH_PCR_GPIO_GPP_D_NMI_EN, R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET, V_PCH_GPIO_GPP_D_PAD_MAX}, //SKL PCH-H GPP_D
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_E_PAD_OWN, R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_E_GPI_IS, R_PCH_PCR_GPIO_GPP_E_GPI_IE, R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_E_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_E_SMI_STS, R_PCH_PCR_GPIO_GPP_E_SMI_EN, R_PCH_PCR_GPIO_GPP_E_NMI_STS, R_PCH_PCR_GPIO_GPP_E_NMI_EN, R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_E_PAD_MAX}, //SKL PCH-H GPP_E
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_F_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_F_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_F_GPI_IS, R_PCH_H_PCR_GPIO_GPP_F_GPI_IE, R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_EN, R_PCH_H_PCR_GPIO_GPP_F_SMI_STS,R_PCH_H_PCR_GPIO_GPP_F_SMI_EN, R_PCH_H_PCR_GPIO_GPP_F_NMI_STS,R_PCH_H_PCR_GPIO_GPP_F_NMI_EN, R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_F_PADCFG_OFFSET, V_PCH_GPIO_GPP_F_PAD_MAX}, //SKL PCH-H GPP_F
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_G_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_G_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_G_GPI_IS, R_PCH_H_PCR_GPIO_GPP_G_GPI_IE, R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_EN, R_PCH_H_PCR_GPIO_GPP_G_SMI_STS,R_PCH_H_PCR_GPIO_GPP_G_SMI_EN, R_PCH_H_PCR_GPIO_GPP_G_NMI_STS,R_PCH_H_PCR_GPIO_GPP_G_NMI_EN, R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_G_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_G_PAD_MAX}, //SKL PCH-H GPP_G
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_H_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_H_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_H_GPI_IS, R_PCH_H_PCR_GPIO_GPP_H_GPI_IE, R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_EN, R_PCH_H_PCR_GPIO_GPP_H_SMI_STS,R_PCH_H_PCR_GPIO_GPP_H_SMI_EN, R_PCH_H_PCR_GPIO_GPP_H_NMI_STS,R_PCH_H_PCR_GPIO_GPP_H_NMI_EN, R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_H_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_H_PAD_MAX}, //SKL PCH-H GPP_H
+ {PID_GPIOCOM3, R_PCH_H_PCR_GPIO_GPP_I_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_I_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_I_GPI_IS, R_PCH_H_PCR_GPIO_GPP_I_GPI_IE, R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_EN, R_PCH_H_PCR_GPIO_GPP_I_SMI_STS,R_PCH_H_PCR_GPIO_GPP_I_SMI_EN, R_PCH_H_PCR_GPIO_GPP_I_NMI_STS,R_PCH_H_PCR_GPIO_GPP_I_NMI_EN, R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_I_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_I_PAD_MAX}, //SKL PCH-H GPP_I
+ {PID_GPIOCOM2, R_PCH_H_PCR_GPIO_GPD_PAD_OWN, R_PCH_PCR_GPIO_GPD_HOSTSW_OWN, R_PCH_PCR_GPIO_GPD_GPI_IS, R_PCH_PCR_GPIO_GPD_GPI_IE, R_PCH_PCR_GPIO_GPD_GPI_GPE_STS, R_PCH_PCR_GPIO_GPD_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_H_PCR_GPIO_GPD_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPD_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET, V_PCH_GPIO_GPD_PAD_MAX} //SKL PCH-H GPD
+};
+
+//
+// I2C controller pins
+// I2C[controller number][pin: SDA/SCL]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpI2cGpio [PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER]=
+{
+ {{GPIO_SKL_LP_GPP_C16, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_C17, GpioPadModeNative1}},
+ {{GPIO_SKL_LP_GPP_C18, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_C19, GpioPadModeNative1}},
+ {{GPIO_SKL_LP_GPP_F4, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_F5 , GpioPadModeNative1}},
+ {{GPIO_SKL_LP_GPP_F6, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_F7 , GpioPadModeNative1}},
+ {{GPIO_SKL_LP_GPP_F8, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_F9 , GpioPadModeNative1}},
+ {{GPIO_SKL_LP_GPP_F10, GpioPadModeNative1}, {GPIO_SKL_LP_GPP_F11, GpioPadModeNative1}}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHI2cGpio [PCH_H_SERIALIO_MAX_I2C_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER]=
+{
+ {{GPIO_SKL_H_GPP_C16, GpioPadModeNative1}, {GPIO_SKL_H_GPP_C17, GpioPadModeNative1}}, //I2C0
+ {{GPIO_SKL_H_GPP_C18, GpioPadModeNative1}, {GPIO_SKL_H_GPP_C19, GpioPadModeNative1}}, //I2C1
+ {{GPIO_SKL_H_GPP_D13, GpioPadModeNative3}, {GPIO_SKL_H_GPP_D14, GpioPadModeNative3}}, //I2C2
+ {{GPIO_SKL_H_GPP_D4, GpioPadModeNative2}, {GPIO_SKL_H_GPP_D23, GpioPadModeNative2}} //I2C3
+};
+
+//
+// UART controller pins
+// UART[controller number][pin: RXD/TXD/RTSB/CTSB]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpUartGpio [PCH_SERIALIO_MAX_UART_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER]=
+{
+ { // UART0
+ {GPIO_SKL_LP_GPP_C8, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C9, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C10, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C11, GpioPadModeNative1}
+ },
+ { // UART1
+ {GPIO_SKL_LP_GPP_C12, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C13, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C14, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C15, GpioPadModeNative1}
+ },
+ { // UART2
+ {GPIO_SKL_LP_GPP_C20, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C21, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C22, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_C23, GpioPadModeNative1}
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHUartGpio [PCH_SERIALIO_MAX_UART_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER]=
+{
+ { // UART0
+ {GPIO_SKL_H_GPP_C8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C9, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C10, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C11, GpioPadModeNative1}
+ },
+ { // UART1
+ {GPIO_SKL_H_GPP_C12, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C13, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C14, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C15, GpioPadModeNative1}
+ },
+ { // UART2
+ {GPIO_SKL_H_GPP_C20, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C21, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C22, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_C23, GpioPadModeNative1}
+ }
+};
+
+//
+// SPI controller pins
+// SPI[controller number][pin: CSB/CLK/MISO/MOSI]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSpiGpio [PCH_SERIALIO_MAX_SPI_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER]=
+{
+ { // SPI0
+ {GPIO_SKL_LP_GPP_B15, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B16, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B17, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B18, GpioPadModeNative1}
+ },
+ { // SPI1
+ {GPIO_SKL_LP_GPP_B19, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B20, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B21, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B22, GpioPadModeNative1}
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSpiGpio [PCH_SERIALIO_MAX_SPI_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER]=
+{
+ { // SPI0
+ {GPIO_SKL_H_GPP_B15, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B16, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B17, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B18, GpioPadModeNative1}
+ },
+ { // SPI1
+ {GPIO_SKL_H_GPP_B19, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B20, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B21, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B22, GpioPadModeNative1}
+ }
+};
+
+//
+// SATA reset port to GPIO pin mapping
+// SATAGP_x -> GPIO pin y
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSataPortResetToGpioMap[PCH_LP_AHCI_MAX_PORTS] =
+{
+ {GPIO_SKL_LP_GPP_E0, GpioPadModeNative2},
+ {GPIO_SKL_LP_GPP_E1, GpioPadModeNative2},
+ {GPIO_SKL_LP_GPP_E2, GpioPadModeNative2}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSataPortResetToGpioMap[PCH_H_AHCI_MAX_PORTS] =
+{
+ {GPIO_SKL_H_GPP_E0, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_E1, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_E2, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F0, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F1, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F2, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F3, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F4, GpioPadModeNative2}
+};
+
+//
+// SATADevSlpPin to GPIO pin mapping
+// SATA_DEVSLP_x -> GPIO pin y
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpSataDevSlpPinToGpioMap[PCH_LP_AHCI_MAX_PORTS] =
+{
+ {GPIO_SKL_LP_GPP_E4, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_E5, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_E6, GpioPadModeNative1}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHSataDevSlpPinToGpioMap[PCH_H_AHCI_MAX_PORTS] =
+{
+ {GPIO_SKL_H_GPP_E4, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_E5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_E6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F7, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F9, GpioPadModeNative1}
+};
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
new file mode 100644
index 0000000000..747fa67199
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Component description file for the PeiDxeSmmGpioLib
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmGpioLib
+FILE_GUID = 16EC5CA8-8195-4847-B6CB-662BD7B763F2
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchCycleDecodingLib
+PchSbiAccessLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+GpioLib.c
+GpioLibrary.h
+GpioNativeLib.c
+GpioInit.c
+PchSklGpioData.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
new file mode 100644
index 0000000000..68b0b5dd4b
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
@@ -0,0 +1,1137 @@
+/** @file
+ PCH cycle deocding configuration and query library.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchCycleDecodingLib.h>
+
+/**
+ Set PCH ACPI base address.
+ The Address should not be 0 and should be 256 bytes alignment, and it is IO space, so must not exceed 0xFFFF.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. clear PMC PCI offset 44h [7] to diable ACPI base address first before changing base address.
+ 2. program PMC PCI offset 40h [15:2] to ACPI base address.
+ 3. set PMC PCI offset 44h [7] to enable ACPI base address.
+ 4. program "ACPI Base Address" PCR[DMI] + 27B4h[23:18, 15:2, 0] to [0x3F, PMC PCI Offset 40h bit[15:2], 1].
+ 5. Program "ACPI Base Destination ID"
+ For SPT-LP: Program PCR[DMI] + 27B8h[31:0] to 0x23A0
+ For SPT-H: Program PCR[DMI] + 27B8h[31:0] to 0x23A8
+
+ @param[in] Address Address for ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseSet (
+ IN UINT16 Address
+ )
+{
+ UINTN PmcBase;
+ UINT32 Dmic;
+ UINT32 Data32;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if (((Address & 0x00FF) != 0) ||
+ (Address == 0)) {
+ DEBUG ((DEBUG_ERROR, "PchAcpiBaseSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchAcpiBaseSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Disable ABASE in PMC Device first before changing base address.
+ //
+ MmioAnd8 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ (UINT8) ~B_PCH_PMC_ACPI_CNT_ACPI_EN
+ );
+ //
+ // Program ABASE in PMC Device
+ //
+ MmioAndThenOr16 (
+ PmcBase + R_PCH_PMC_ACPI_BASE,
+ (UINT16) (~B_PCH_PMC_ACPI_BASE_BAR),
+ Address
+ );
+ //
+ // Enable ABASE in PMC Device
+ //
+ MmioOr8 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ B_PCH_PMC_ACPI_CNT_ACPI_EN
+ );
+ //
+ // Program "ACPI Base Address" PCR[DMI] + 27B4h[23:18, 15:2, 0] to [0x3F, PMC PCI Offset 40h bit[15:2], 1]
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_ACPIBA,
+ (0x00FC0001 + Address)
+ );
+ //
+ // Program "ACPI Base Destination ID"
+ // For SPT-LP:
+ // Program PCR[DMI] + 27B8h[31:0] to 0x23A0
+ // For SPT-H:
+ // Program PCR[DMI] + 27B8h[31:0] to 0x23A8
+ //
+ if (PchSeries == PchLp) {
+ Data32 = 0x23A0;
+ } else {
+ Data32 = 0x23A8;
+ }
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_ACPIBDID,
+ Data32
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH ACPI base address.
+
+ @param[out] Address Address of ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseGet (
+ OUT UINT16 *Address
+ )
+{
+ UINTN PmcBase;
+
+ if (Address == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchAcpiBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ *Address = MmioRead16 (PmcBase + R_PCH_PMC_ACPI_BASE) & B_PCH_PMC_ACPI_BASE_BAR;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH PWRM base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. clear PMC PCI offset 44h [8] to diable PWRM base address first before changing PWRM base address.
+ 2. program PMC PCI offset 48h [31:16] to PM base address.
+ 3. set PMC PCI offset 44h [8] to enable PWRM base address.
+ 4. program "PM Base Address Memory Range Base" PCR[DMI] + 27ACh[15:0] to the same value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the PWRMBASE to be 64KB aligned.
+ program "PM Base Address Memory Range Limit" PCR[DMI] + 27ACh[31:16] to the value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the memory allocated to PWRMBASE to be 64KB in size.
+ 5. Program "PM Base Control"
+ For SPT-LP: Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A0]
+ For SPT-H: Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A8]
+
+ @param[in] Address Address for PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseSet (
+ IN UINT32 Address
+ )
+{
+ UINTN PmcBase;
+ UINT32 Dmic;
+ UINT32 Data32;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if (((Address & (~B_PCH_PMC_PWRM_BASE_BAR)) != 0) ||
+ (Address == 0)) {
+ DEBUG ((DEBUG_ERROR, "PchPwrmBaseSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPwrmBaseSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Disable PWRMBASE in PMC Device first before changing PWRM base address.
+ //
+ MmioAnd16 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ (UINT16) ~B_PCH_PMC_ACPI_CNT_PWRM_EN
+ );
+ //
+ // Program PWRMBASE in PMC Device
+ //
+ MmioAndThenOr32 (
+ PmcBase + R_PCH_PMC_PWRM_BASE,
+ (UINT32) (~B_PCH_PMC_PWRM_BASE_BAR),
+ Address
+ );
+ //
+ // Enable PWRMBASE in PMC Device
+ //
+ MmioOr16 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ B_PCH_PMC_ACPI_CNT_PWRM_EN
+ );
+ //
+ // Program "PM Base Address Memory Range Base" PCR[DMI] + 27ACh[15:0] to the same value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the PWRMBASE to be 64KB aligned.
+ // Program "PM Base Address Memory Range Limit" PCR[DMI] + 27ACh[31:16] to the value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the memory allocated to PWRMBASE to be 64KB in size.
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_PMBASEA,
+ ((Address & 0xFFFF0000) | (Address >> 16))
+ );
+ //
+ // Program "PM Base Control"
+ // For SPT-LP:
+ // Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A0]
+ // For SPT-H:
+ // Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A8]
+ //
+ if (PchSeries == PchLp) {
+ Data32 = 0x800023A0;
+ } else {
+ Data32 = 0x800023A8;
+ }
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_PMBASEC,
+ Data32
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH PWRM base address.
+
+ @param[out] Address Address of PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseGet (
+ OUT UINT32 *Address
+ )
+{
+ UINTN PmcBase;
+
+ if (Address == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchPwrmBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ *Address = MmioRead32 (PmcBase + R_PCH_PMC_PWRM_BASE) & B_PCH_PMC_PWRM_BASE_BAR;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH TCO base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. set Smbus PCI offset 54h [8] to enable TCO base address.
+ 2. program Smbus PCI offset 50h [15:5] to TCO base address.
+ 3. set Smbus PCI offset 54h [8] to enable TCO base address.
+ 4. program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1] to [Smbus PCI offset 50h[15:5], 1].
+
+ @param[in] Address Address for TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchTcoBaseSet (
+ IN UINT16 Address
+ )
+{
+ UINTN SmbusBase;
+ UINT32 Dmic;
+
+ if ((Address & ~B_PCH_SMBUS_TCOBASE_BAR) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchTcoBaseSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchTcoBaseSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ SmbusBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+ if (MmioRead16 (SmbusBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Verify TCO base is not locked.
+ //
+ if ((MmioRead8 (SmbusBase + R_PCH_SMBUS_TCOCTL) & B_PCH_SMBUS_TCOCTL_TCO_BASE_LOCK) != 0) {
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Disable TCO in SMBUS Device first before changing base address.
+ //
+ MmioAnd16 (
+ SmbusBase + R_PCH_SMBUS_TCOCTL,
+ (UINT16) ~B_PCH_SMBUS_TCOCTL_TCO_BASE_EN
+ );
+ //
+ // Program TCO in SMBUS Device
+ //
+ MmioAndThenOr16 (
+ SmbusBase + R_PCH_SMBUS_TCOBASE,
+ (UINT16) (~B_PCH_SMBUS_TCOBASE_BAR),
+ Address
+ );
+ //
+ // Enable TCO in SMBUS Device
+ //
+ MmioOr16 (
+ SmbusBase + R_PCH_SMBUS_TCOCTL,
+ B_PCH_SMBUS_TCOCTL_TCO_BASE_EN
+ );
+ //
+ // Program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1] to [SMBUS PCI offset 50h[15:5], 1].
+ //
+ PchPcrWrite16 (
+ PID_DMI, R_PCH_PCR_DMI_TCOBASE,
+ (Address | BIT1)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH TCO base address.
+
+ @param[out] Address Address of TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchTcoBaseGet (
+ OUT UINT16 *Address
+ )
+{
+ if (Address == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchTcoBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Read "TCO Base Address" PCR[DMI] + 2778h[15:5]
+ // Don't read TCO base address from SMBUS PCI register since SMBUS might be disabled.
+ //
+ PchPcrRead16 (
+ PID_DMI, R_PCH_PCR_DMI_TCOBASE,
+ Address
+ );
+ *Address &= B_PCH_PCR_DMI_TCOBASE_TCOBA;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI generic IO range.
+ For generic IO range, the base address must align to 4 and less than 0xFFFF, and the length must be power of 2
+ and less than or equal to 256. Moreover, the address must be length aligned.
+ This function basically checks the address and length, which should not overlap with all other generic ranges.
+ If no more generic range register available, it returns out of resource error.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Some IO ranges below 0x100 have fixed target. The target might be ITSS,RTC,LPC,PMC or terminated inside P2SB
+ but all predefined and can't be changed. IO range below 0x100 will be rejected in this function except below ranges:
+ 0x00-0x1F,
+ 0x44-0x4B,
+ 0x54-0x5F,
+ 0x68-0x6F,
+ 0x80-0x8F,
+ 0xC0-0xFF
+ Steps of programming generic IO range:
+ 1. Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ 2. Program LPC/eSPI Generic IO Range #, PCR[DMI] + 2730h ~ 273Fh to the same value programmed in LPC/eSPI PCI Offset 84h~93h.
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeSet (
+ IN UINT16 Address,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ PCH_LPC_GEN_IO_RANGE_LIST LpcGenIoRangeList;
+ UINTN LpcBase;
+ UINTN Index;
+ UINTN BaseAddr;
+ UINTN MaskLength;
+ UINTN TempMaxAddr;
+ UINT32 Data32;
+ UINTN ArraySize;
+ static struct EXCEPT_RANGE {
+ UINT8 Start;
+ UINT8 Length;
+ } ExceptRanges[] = { {0x00, 0x20}, {0x44, 0x08}, {0x54, 0x0C}, {0x68, 0x08}, {0x80, 0x10}, {0xC0, 0x40} };
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ //
+ // For generic IO range, the base address must align to 4 and less than 0xFFFF,
+ // the length must be power of 2 and less than or equal to 256, and the address must be length aligned.
+ // IO range below 0x100 will be rejected in this function except below ranges:
+ // 0x00-0x1F,
+ // 0x44-0x4B,
+ // 0x54-0x5F,
+ // 0x68-0x6F,
+ // 0x80-0x8F,
+ // 0xC0-0xFF
+ //
+ if (((Length & (Length - 1)) != 0) ||
+ ((Address & (UINT16) ~B_PCH_LPC_GENX_DEC_IOBAR) != 0) ||
+ (Length > 256)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Address < 0x100) {
+ ArraySize = sizeof (ExceptRanges) / sizeof (struct EXCEPT_RANGE);
+ for (Index = 0; Index < ArraySize; Index++) {
+ if ((Address >= ExceptRanges[Index].Start) &&
+ ((Address + Length) <= ((UINTN) ExceptRanges[Index].Start + (UINTN) ExceptRanges[Index].Length))) {
+ break;
+ }
+ }
+ if (Index >= ArraySize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // check if range overlap
+ //
+ Status = PchLpcGenIoRangeGet (&LpcGenIoRangeList);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return Status;
+ }
+
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ BaseAddr = LpcGenIoRangeList.Range[Index].BaseAddr;
+ MaskLength = LpcGenIoRangeList.Range[Index].Length;
+ if (BaseAddr == 0) {
+ continue;
+ }
+ if (((Address >= BaseAddr) && (Address < (BaseAddr + MaskLength))) ||
+ (((Address + Length) > BaseAddr) && ((Address + Length) <= (BaseAddr + MaskLength)))) {
+ if ((Address >= BaseAddr) && (Length <= MaskLength)) {
+ //
+ // return SUCCESS while range is covered.
+ //
+ return EFI_SUCCESS;
+ }
+
+ if ((Address + Length) > (BaseAddr + MaskLength)) {
+ TempMaxAddr = Address + Length;
+ } else {
+ TempMaxAddr = BaseAddr + MaskLength;
+ }
+ if (Address > BaseAddr) {
+ Address = (UINT16) BaseAddr;
+ }
+ Length = TempMaxAddr - Address;
+ break;
+ }
+ }
+ //
+ // If no range overlap
+ //
+ if (Index >= PCH_LPC_GEN_IO_RANGE_MAX) {
+ //
+ // Find a empty register
+ //
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ BaseAddr = LpcGenIoRangeList.Range[Index].BaseAddr;
+ if (BaseAddr == 0) {
+ break;
+ }
+ }
+ if (Index >= PCH_LPC_GEN_IO_RANGE_MAX) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Data32);
+ if ((Data32 & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Program LPC/eSPI generic IO range register accordingly.
+ //
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ Data32 = (UINT32) (((Length - 1) << 16) & B_PCH_LPC_GENX_DEC_IODRA);
+ Data32 |= (UINT32) Address;
+ Data32 |= B_PCH_LPC_GENX_DEC_EN;
+ //
+ // Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ //
+ MmioWrite32 (
+ LpcBase + R_PCH_LPC_GEN1_DEC + Index * 4,
+ Data32
+ );
+ //
+ // Program LPC Generic IO Range #, PCR[DMI] + 2730h ~ 273Fh to the same value programmed in LPC/eSPI PCI Offset 84h~93h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, (UINT16) (R_PCH_PCR_DMI_LPCLGIR1 + Index * 4),
+ Data32
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH LPC/eSPI generic IO range list.
+ This function returns a list of base address, length, and enable for all LPC/eSPI generic IO range regsiters.
+
+ @param[out] LpcGenIoRangeList Return all LPC/eSPI generic IO range register status.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeGet (
+ OUT PCH_LPC_GEN_IO_RANGE_LIST *LpcGenIoRangeList
+ )
+{
+ UINTN Index;
+ UINTN LpcBase;
+ UINT32 Data32;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ if (LpcGenIoRangeList == NULL) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ Data32 = MmioRead32 (LpcBase + R_PCH_LPC_GEN1_DEC + Index * 4);
+ LpcGenIoRangeList->Range[Index].BaseAddr = Data32 & B_PCH_LPC_GENX_DEC_IOBAR;
+ LpcGenIoRangeList->Range[Index].Length = ((Data32 & B_PCH_LPC_GENX_DEC_IODRA) >> 16) + 4;
+ LpcGenIoRangeList->Range[Index].Enable = Data32 & B_PCH_LPC_GENX_DEC_EN;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI memory range decoding.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program LPC/eSPI PCI Offset 98h [0] to [0] to disable memory decoding first before changing base address.
+ 2. Program LPC/eSPI PCI Offset 98h [31:16, 0] to [Address, 1].
+ 3. Program LPC/eSPI Memory Range, PCR[DMI] + 2740h to the same value programmed in LPC/eSPI PCI Offset 98h.
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeSet (
+ IN UINT32 Address
+ )
+{
+ UINTN LpcBase;
+ UINT32 Dmic;
+
+ if ((Address & (~B_PCH_LPC_LGMR_MA)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchLpcMemRangeSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchLpcMemRangeSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ //
+ // Program LPC/eSPI PCI Offset 98h [0] to [0] to disable memory decoding first before changing base address.
+ //
+ MmioAnd32 (
+ LpcBase + R_PCH_LPC_LGMR,
+ (UINT32) ~B_PCH_LPC_LGMR_LMRD_EN
+ );
+ //
+ // Program LPC/eSPI PCI Offset 98h [31:16, 0] to [Address, 1].
+ //
+ MmioWrite32 (
+ LpcBase + R_PCH_LPC_LGMR,
+ (Address | B_PCH_LPC_LGMR_LMRD_EN)
+ );
+ //
+ // Program LPC Memory Range, PCR[DMI] + 2740h to the same value programmed in LPC/eSPI PCI Offset 98h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_LPCGMR,
+ (Address | B_PCH_LPC_LGMR_LMRD_EN)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH LPC/eSPI memory range decoding address.
+
+ @param[out] Address Address of LPC/eSPI memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeGet (
+ OUT UINT32 *Address
+ )
+{
+ UINTN LpcBase;
+
+ if (Address == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchLpcMemRangeGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ *Address = MmioRead32 (LpcBase + R_PCH_LPC_LGMR) & B_PCH_LPC_LGMR_MA;
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH BIOS range deocding.
+ This will check General Control and Status bit 10 (GCS.BBS) to identify SPI or LPC/eSPI and program BDE register accordingly.
+ Please check EDS for detail of BiosDecodeEnable bit definition.
+ bit 15: F8-FF Enable
+ bit 14: F0-F8 Enable
+ bit 13: E8-EF Enable
+ bit 12: E0-E8 Enable
+ bit 11: D8-DF Enable
+ bit 10: D0-D7 Enable
+ bit 9: C8-CF Enable
+ bit 8: C0-C7 Enable
+ bit 7: Legacy F Segment Enable
+ bit 6: Legacy E Segment Enable
+ bit 5: Reserved
+ bit 4: Reserved
+ bit 3: 70-7F Enable
+ bit 2: 60-6F Enable
+ bit 1: 50-5F Enable
+ bit 0: 40-4F Enable
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. if GCS.BBS is 0 (SPI), program SPI offset D8h to BiosDecodeEnable.
+ if GCS.BBS is 1 (LPC/eSPi), program LPC offset D8h to BiosDecodeEnable.
+ 2. program LPC BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC or SPI Offset D8h.
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchBiosDecodeEnableSet (
+ IN UINT16 BiosDecodeEnable
+ )
+{
+ UINTN BaseAddr;
+ UINT32 DmiGcsBbs;
+ UINT32 Dmic;
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchBiosDecodeEnableSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_GCS, &DmiGcsBbs);
+ DmiGcsBbs &= B_PCH_PCR_DMI_BBS;
+ //
+ // Check General Control and Status (GCS) [10]
+ // '0': SPI
+ // '1': LPC/eSPI
+ //
+ if (DmiGcsBbs == 0) {
+ BaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ //
+ // if GCS.BBS is 0 (SPI), program SPI offset D8h to BiosDecodeEnable.
+ //
+ MmioWrite16 (BaseAddr + R_PCH_SPI_BDE, BiosDecodeEnable);
+ } else {
+ BaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ //
+ // if GCS.BBS is 1 (LPC/eSPi), program LPC offset D8h to BiosDecodeEnable.
+ //
+ MmioWrite16 (BaseAddr + R_PCH_LPC_BDE, BiosDecodeEnable);
+ }
+
+ //
+ // program LPC BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC or SPI Offset D8h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_LPCBDE, BiosDecodeEnable);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI IO decode ranges.
+ Program LPC/eSPI I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC/eSPI PCI offset 80h.
+ Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
+ Bit 12: FDD range
+ Bit 9:8: LPT range
+ Bit 6:4: ComB range
+ Bit 2:0: ComA range
+
+ @param[in] LpcIoDecodeRanges LPC/eSPI IO decode ranges bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoDecodeRangesSet (
+ IN UINT16 LpcIoDecodeRanges
+ )
+{
+ UINTN LpcBaseAddr;
+ UINT32 Dmic;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ LpcBaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ //
+ // check if setting is identical
+ //
+ if (LpcIoDecodeRanges == MmioRead16 (LpcBaseAddr + R_PCH_LPC_IOD)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC/eSPI PCI offset 80h.
+ //
+ MmioWrite16 (LpcBaseAddr + R_PCH_LPC_IOD, LpcIoDecodeRanges);
+
+ //
+ // program LPC I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC/eSPI PCI offset 80h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_LPCIOD, LpcIoDecodeRanges);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI IO enable decoding.
+ Setup LPC/eSPI I/O Enables, PCR[DMI] + 2774h[15:0] to the same value program in LPC/eSPI PCI offset 82h.
+ Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+ in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtractive agent for handling.
+ Please check EDS for detail of Lpc/eSPI IO decode ranges bit definition.
+
+ @param[in] LpcIoEnableDecoding LPC/eSPI IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoEnableDecodingSet (
+ IN UINT16 LpcIoEnableDecoding
+ )
+{
+ UINTN LpcBaseAddr;
+ UINT32 Dmic;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ LpcBaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ if (LpcIoEnableDecoding == MmioRead16 (LpcBaseAddr + R_PCH_LPC_IOE)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC/eSPI PCI offset 82h.
+ //
+ MmioWrite16 (LpcBaseAddr + R_PCH_LPC_IOE, LpcIoEnableDecoding);
+
+ //
+ // program LPC I/O Decode Ranges, PCR[DMI] + 2774h[15:0] to the same value programmed in LPC/eSPI PCI offset 82h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_LPCIOE, LpcIoEnableDecoding);
+ return EFI_SUCCESS;
+}
+
+
+//
+// Root Port Destination ID tables
+//
+// PCH-LP RPR destination ID table
+//
+UINT16 mPchLpRprDidTable[] = {
+ 0x2188, // Dest ID of RP1
+ 0x2189, // Dest ID of RP2
+ 0x218A, // Dest ID of RP3
+ 0x218B, // Dest ID of RP4
+ 0x2198, // Dest ID of RP5
+ 0x2199, // Dest ID of RP6
+ 0x219A, // Dest ID of RP7
+ 0x219B, // Dest ID of RP8
+ 0x21A8, // Dest ID of RP9
+ 0x21A9, // Dest ID of RP10
+ 0x21AA, // Dest ID of RP11
+ 0x21AB // Dest ID of RP12
+};
+
+//
+// PCH-H RPR destination ID table
+//
+UINT16 mPchHRprDidTable[] = {
+ 0x2180, // Dest ID of RP1
+ 0x2181, // Dest ID of RP2
+ 0x2182, // Dest ID of RP3
+ 0x2183, // Dest ID of RP4
+ 0x2188, // Dest ID of RP5
+ 0x2189, // Dest ID of RP6
+ 0x218A, // Dest ID of RP7
+ 0x218B, // Dest ID of RP8
+ 0x2198, // Dest ID of RP9
+ 0x2199, // Dest ID of RP10
+ 0x219A, // Dest ID of RP11
+ 0x219B, // Dest ID of RP12
+ 0x21A8, // Dest ID of RP13
+ 0x21A9, // Dest ID of RP14
+ 0x21AA, // Dest ID of RP15
+ 0x21AB, // Dest ID of RP16
+ 0x21B8, // Dest ID of RP17
+ 0x21B9, // Dest ID of RP18
+ 0x21BA, // Dest ID of RP19
+ 0x21BB, // Dest ID of RP20
+ 0x21C0, // Dest ID of RP21 (KBL-PCH-H only)
+ 0x21C1, // Dest ID of RP22 (KBL-PCH-H only)
+ 0x21C2, // Dest ID of RP23 (KBL-PCH-H only)
+ 0x21C3 // Dest ID of RP24 (KBL-PCH-H only)
+};
+
+/**
+ Set PCH IO port 80h cycle decoding to PCIE root port.
+ System BIOS is likely to do this very soon after reset before PCI bus enumeration.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program "RPR Destination ID", PCR[DMI] + 274Ch[31:16] to the Dest ID of RP.
+ 2. Program "Reserved Page Route", PCR[DMI] + 274Ch[11] to '1'. Use byte write on GCS+1 and leave the BILD bit which is RWO.
+
+ @param[in] RpNumber PCIE root port physical number.
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+EFIAPI
+PchIoPort80DecodeSet (
+ IN UINTN RpNumber
+ )
+{
+ UINT32 Dmic;
+ UINT16 *PchRprDidTable;
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchIoPort80DecodeSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ ///
+ /// IO port 80h is typically used by decoder/LED hardware for debug purposes.
+ /// By default PCH will forward IO port 80h cycles to LPC bus. The Reserved Page Route (RPR) bit
+ /// of General Control and Status register, located at PCR[DMI] + 274Ch[11] , allows software to
+ /// re-direct IO port 80h cycles to PCIe bus so that a target (for example, a debug card) on
+ /// PCIe bus can receive and claim these cycles.
+ /// The "RPR Destination ID", PCR[DMI] + 274Ch[31:16] need to be set accordingly to point
+ /// to the root port that decode this range. Reading from Port 80h may not return valid values
+ /// if the POST-card itself do not shadow the writes. Unlike LPC, PCIe does not shadow the Port 80 writes.
+ ///
+
+ if (GetPchSeries () == PchLp) {
+ if (RpNumber >= sizeof (mPchLpRprDidTable) / sizeof (mPchLpRprDidTable[0]) ) {
+ return EFI_UNSUPPORTED;
+ }
+ PchRprDidTable = mPchLpRprDidTable;
+ } else {
+ if (RpNumber >= sizeof (mPchHRprDidTable) / sizeof (mPchHRprDidTable[0]) ) {
+ return EFI_UNSUPPORTED;
+ }
+ PchRprDidTable = mPchHRprDidTable;
+ }
+
+ //
+ // Program "RPR Destination ID", PCR[DMI] + 274Ch[31:16] to the Dest ID of RP.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_GCS + 2, PchRprDidTable[RpNumber]);
+ //
+ // Program "Reserved Page Route", PCR[DMI] + 274Ch[11] to '1'.
+ // Use byte write on GCS+1 and leave the BILD bit which is RWO.
+ //
+ PchPcrAndThenOr8 (PID_DMI, R_PCH_PCR_DMI_GCS + 1, 0xFF, (B_PCH_PCR_DMI_RPR >> 8));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get IO APIC regsiters base address.
+ It returns IO APIC INDEX, DATA, and EOI regsiter address once the parameter is not NULL.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] IoApicIndex Buffer of IO APIC INDEX regsiter address
+ @param[out] IoApicData Buffer of IO APIC DATA regsiter address
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PchIoApicBaseGet (
+ OPTIONAL OUT UINT32 *IoApicIndex,
+ OPTIONAL OUT UINT32 *IoApicData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 RegIoac;
+ UINT32 RangeSelect;
+
+ Status = PchP2sbCfgGet16 (R_PCH_P2SB_IOAC, &RegIoac);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RangeSelect = (RegIoac & B_PCH_P2SB_IOAC_ASEL) << N_PCH_IO_APIC_ASEL;
+
+ if (IoApicIndex != NULL) {
+ *IoApicIndex = R_PCH_IO_APIC_INDEX + RangeSelect;
+ }
+ if (IoApicData != NULL) {
+ *IoApicData = R_PCH_IO_APIC_DATA + RangeSelect;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get HPET base address.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] HpetBase Buffer of HPET base address
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchHpetBaseGet (
+ OUT UINT32 *HpetBase
+ )
+{
+ EFI_STATUS Status;
+ UINT8 RegHptc;
+
+ if (HpetBase == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchHpetBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PchP2sbCfgGet8 (R_PCH_P2SB_HPTC, &RegHptc);
+
+ switch (RegHptc & B_PCH_P2SB_HPTC_AS) {
+ case 0:
+ *HpetBase = V_PCH_HPET_BASE0;
+ break;
+ case 1:
+ *HpetBase = V_PCH_HPET_BASE1;
+ break;
+ case 2:
+ *HpetBase = V_PCH_HPET_BASE2;
+ break;
+ case 3:
+ *HpetBase = V_PCH_HPET_BASE3;
+ break;
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
new file mode 100644
index 0000000000..446703d918
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
@@ -0,0 +1,44 @@
+## @file
+# PCH cycle decoding Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchCycleDecodingLib
+FILE_GUID = 676C749F-9CD1-46B7-BAFD-4B1BC36B4C8E
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchCycleDecodingLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcrLib
+PchP2sbLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchCycleDecodingLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c
new file mode 100644
index 0000000000..277923bdcc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c
@@ -0,0 +1,146 @@
+/** @file
+ PCH Gbe Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchCycleDecodingLib.h>
+
+/**
+ Check whether GbE region is valid
+ Check SPI region directly since GbE might be disabled in SW.
+
+ @retval TRUE Gbe Region is valid
+ @retval FALSE Gbe Region is invalid
+**/
+BOOLEAN
+PchIsGbeRegionValid (
+ VOID
+ )
+{
+ UINT32 SpiBar;
+ SpiBar = MmioRead32 (MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI)
+ + R_PCH_SPI_BAR0) & ~B_PCH_SPI_BAR0_MASK;
+ ASSERT (SpiBar != 0);
+ if (MmioRead32 (SpiBar + R_PCH_SPI_FREG3_GBE) != B_PCH_SPI_FREGX_BASE_MASK) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Returns GbE over PCIe port number based on a soft strap.
+
+ @return Root port number (1-based)
+ @retval 0 GbE over PCIe disabled
+**/
+UINT32
+PchGetGbePortNumber (
+ VOID
+ )
+{
+ UINT32 GbePortSel;
+ UINT32 PcieStrapFuse;
+
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_STRPFUSECFG1_REG_BASE, &PcieStrapFuse);
+ if ((PcieStrapFuse & B_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIE_PEN) == 0) {
+ return 0; // GbE disabled
+ }
+ GbePortSel = (PcieStrapFuse & B_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIEPORTSEL) >> N_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIEPORTSEL;
+ if (GetPchSeries () == PchLp) {
+ switch (GbePortSel) {
+ case 0: return 3;
+ case 1: return 4;
+ case 2: return 5;
+ case 3: return 9;
+ case 4: return 10;
+ }
+ } else {
+ switch (GbePortSel) {
+ case 0: return 4;
+ case 1: return 5;
+ case 2: return 9;
+ case 3: return 12;
+ case 4: return 13;
+ }
+ }
+ DEBUG ((DEBUG_ERROR, "Invalid GbE port\n"));
+ ASSERT (FALSE);
+ return 0;
+}
+
+/**
+ Check whether LAN controller is enabled in the platform.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+PchIsGbePresent (
+ VOID
+ )
+{
+ UINT32 PwrmBase;
+ UINT32 FuseDis2State;
+ //
+ // Check PMC strap/fuse
+ //
+ PchPwrmBaseGet (&PwrmBase);
+ FuseDis2State = MmioRead32 (PwrmBase + R_PCH_PWRM_FUSE_DIS_RD_2);
+ if (FuseDis2State & B_PCH_PWRM_FUSE_DIS_RD_2_GBE_FUSE_SS_DIS) {
+ return FALSE;
+ }
+ //
+ // Check FIA strap/fuse
+ //
+ if (PchGetGbePortNumber () == 0) {
+ return FALSE;
+ }
+ //
+ // Check GbE NVM
+ //
+ if (PchIsGbeRegionValid () == FALSE) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Check whether LAN controller is enabled in the platform.
+
+ @deprecated Use PchIsGbePresent instead.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+PchIsGbeAvailable (
+ VOID
+ )
+{
+ return PchIsGbePresent ();
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf
new file mode 100644
index 0000000000..b05d82fce1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf
@@ -0,0 +1,44 @@
+## @file
+# PCH Gbe Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchGbeLib
+FILE_GUID = FC022ED0-6EB3-43E1-A740-0BA27CBBD010
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchGbeLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcrLib
+PchCycleDecodingLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchGbeLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c
new file mode 100644
index 0000000000..d3e6094954
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PchHsioLib.c
@@ -0,0 +1,928 @@
+/** @file
+ PCH HSIO Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchHsioLib.h>
+
+/**
+ The function returns the Port Id and lane owner for the specified lane
+
+ @param[in] PhyMode Phymode that needs to be checked
+ @param[out] PortId Common Lane End Point ID
+ @param[out] LaneOwner Lane Owner
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid lane number
+**/
+EFI_STATUS
+EFIAPI
+PchGetLaneInfo (
+ IN UINT32 LaneNum,
+ OUT UINT8 *PortId,
+ OUT UINT8 *LaneOwner
+ )
+{
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGeneration;
+ UINT32 Los1;
+ UINT32 Los2;
+ UINT32 Los3;
+ UINT32 Los4;
+
+ Los1 = 0;
+ Los2 = 0;
+ Los3 = 0;
+ Los4 = 0;
+
+ PchSeries = GetPchSeries ();
+ PchGeneration = GetPchGeneration ();
+
+ if (((LaneNum > 15) && (PchSeries == PchLp)) ||
+ ((LaneNum > 29) && (PchSeries == PchH) && (PchGeneration == SklPch)) ||
+ (LaneNum > 33) ) {
+ return EFI_INVALID_PARAMETER;
+ } else if (LaneNum < 8) {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS1_REG_BASE, &Los1);
+ } else if (LaneNum < 16) {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS2_REG_BASE, &Los2);
+ } else if (LaneNum < 24) {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS3_REG_BASE, &Los3);
+ } else {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS4_REG_BASE, &Los4);
+ }
+
+ if (PchSeries == PchLp) {
+ switch (LaneNum) {
+ case 0:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L0O));
+ *PortId = PID_MODPHY0;
+ break;
+ case 1:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L1O) >>4);
+ *PortId = PID_MODPHY0;
+ break;
+ case 2:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L2O) >>8);
+ *PortId = PID_MODPHY0;
+ break;
+ case 3:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L3O) >>12);
+ *PortId = PID_MODPHY0;
+ break;
+ case 4:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L4O) >>16);
+ *PortId = PID_MODPHY0;
+ break;
+ case 5:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L5O) >>20);
+ *PortId = PID_MODPHY0;
+ break;
+ case 6:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L6O) >>24);
+ *PortId = PID_MODPHY1;
+ break;
+ case 7:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L7O) >>28);
+ *PortId = PID_MODPHY1;
+ break;
+ case 8:
+ *LaneOwner = (UINT8) (Los2 & B_PCH_PCR_FIA_L8O);
+ *PortId = PID_MODPHY1;
+ break;
+ case 9:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L9O) >>4);
+ *PortId = PID_MODPHY1;
+ break;
+ case 10:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L10O) >>8);
+ *PortId = PID_MODPHY2;
+ break;
+ case 11:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L11O) >>12);
+ *PortId = PID_MODPHY2;
+ break;
+ case 12:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L12O) >>16);
+ *PortId = PID_MODPHY2;
+ break;
+ case 13:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L13O) >>20);
+ *PortId = PID_MODPHY2;
+ break;
+ case 14:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L14O) >>24);
+ *PortId = PID_MODPHY2;
+ break;
+ case 15:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L15O) >>28);
+ *PortId = PID_MODPHY2;
+ break;
+ }
+ } else {
+ switch (LaneNum) {
+ case 0:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L0O));
+ *PortId = PID_MODPHY0;
+ break;
+ case 1:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L1O) >>4);
+ *PortId = PID_MODPHY0;
+ break;
+ case 2:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L2O) >>8);
+ *PortId = PID_MODPHY0;
+ break;
+ case 3:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L3O) >>12);
+ *PortId = PID_MODPHY0;
+ break;
+ case 4:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L4O) >>16);
+ *PortId = PID_MODPHY0;
+ break;
+ case 5:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L5O) >>20);
+ *PortId = PID_MODPHY0;
+ break;
+ case 6:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L6O) >>24);
+ *PortId = PID_MODPHY1;
+ break;
+ case 7:
+ *LaneOwner = (UINT8) ((Los1 & B_PCH_PCR_FIA_L7O) >>28);
+ *PortId = PID_MODPHY1;
+ break;
+ case 8:
+ *LaneOwner = (UINT8) (Los2 & B_PCH_PCR_FIA_L8O);
+ *PortId = PID_MODPHY1;
+ break;
+ case 9:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L9O) >>4);
+ *PortId = PID_MODPHY1;
+ break;
+ case 10:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L10O) >>8);
+ *PortId = PID_MODPHY1;
+ break;
+ case 11:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L11O) >>12);
+ *PortId = PID_MODPHY1;
+ break;
+ case 12:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L12O) >>16);
+ *PortId = PID_MODPHY1;
+ break;
+ case 13:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L13O) >>20);
+ *PortId = PID_MODPHY1;
+ break;
+ case 14:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L14O) >>24);
+ *PortId = PID_MODPHY2;
+ break;
+ case 15:
+ *LaneOwner = (UINT8) ((Los2 & B_PCH_PCR_FIA_L15O) >>28);
+ *PortId = PID_MODPHY2;
+ break;
+ case 16:
+ *LaneOwner = (UINT8) (Los3 & B_PCH_PCR_FIA_L16O);
+ *PortId = PID_MODPHY2;
+ break;
+ case 17:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L17O) >>4);
+ *PortId = PID_MODPHY2;
+ break;
+ case 18:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L18O) >>8);
+ *PortId = PID_MODPHY2;
+ break;
+ case 19:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L19O) >>12);
+ *PortId = PID_MODPHY2;
+ break;
+ case 20:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L20O) >>16);
+ *PortId = PID_MODPHY2;
+ break;
+ case 21:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L21O) >>20);
+ *PortId = PID_MODPHY2;
+ break;
+ case 22:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L22O) >>24);
+ *PortId = PID_MODPHY3;
+ break;
+ case 23:
+ *LaneOwner = (UINT8) ((Los3 & B_PCH_PCR_FIA_L23O) >>28);
+ *PortId = PID_MODPHY3;
+ break;
+ case 24:
+ *LaneOwner = (UINT8) (Los4 & B_PCH_PCR_FIA_L24O);
+ *PortId = PID_MODPHY3;
+ break;
+ case 25:
+ *LaneOwner = (UINT8) ((Los4 & B_PCH_PCR_FIA_L25O) >>4);
+ *PortId = PID_MODPHY3;
+ break;
+ case 26:
+ *LaneOwner = (UINT8) ((Los4 & B_PCH_PCR_FIA_L26O) >>8);
+ *PortId = PID_MODPHY3;
+ break;
+ case 27:
+ *LaneOwner = (UINT8) ((Los4 & B_PCH_PCR_FIA_L27O) >>12);
+ *PortId = PID_MODPHY3;
+ break;
+ case 28:
+ *LaneOwner = (UINT8) ((Los4 & B_PCH_PCR_FIA_L28O) >>16);
+ *PortId = PID_MODPHY3;
+ break;
+ case 29:
+ *LaneOwner = (UINT8) ((Los4 & B_PCH_PCR_FIA_L29O) >>20);
+ *PortId = PID_MODPHY3;
+ break;
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ //
+ // Lanes 30-33 don't have ownership registers and are always configured to PCIE
+ //
+ *LaneOwner = V_PCH_PCR_FIA_LANE_OWN_PCIEDMI;
+ *PortId = PID_MODPHY4;
+ break;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Determine the lane number of a specified port
+
+ @param[out] LaneNum GBE Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetGbeLaneNum (
+ UINT8 *LaneNum
+ )
+{
+ PCH_SERIES PchSeries;
+ UINT32 Los1;
+ UINT32 Los2;
+ UINT32 Los3;
+
+ PchSeries = GetPchSeries ();
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS2_REG_BASE, &Los2);
+
+ if (PchSeries == PchLp) {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS1_REG_BASE, &Los1);
+ if (((Los1 & B_PCH_PCR_FIA_L6O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 6;
+ return EFI_SUCCESS;
+ } else if (((Los1 & B_PCH_PCR_FIA_L7O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 7;
+ return EFI_SUCCESS;
+ } else if ((Los2 & B_PCH_PCR_FIA_L8O) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 8;
+ return EFI_SUCCESS;
+ } else if (((Los2 & B_PCH_PCR_FIA_L12O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 12;
+ return EFI_SUCCESS;
+ } else if (((Los2 & B_PCH_PCR_FIA_L13O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 13;
+ return EFI_SUCCESS;
+ }
+ } else {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS3_REG_BASE, &Los3);
+ if (((Los2 & B_PCH_PCR_FIA_L9O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 9;
+ return EFI_SUCCESS;
+ } else if (((Los2 & B_PCH_PCR_FIA_L10O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 10;
+ return EFI_SUCCESS;
+ } else if (((Los3 & B_PCH_PCR_FIA_L18O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 18;
+ return EFI_SUCCESS;
+ } else if (((Los3 & B_PCH_PCR_FIA_L21O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 21;
+ return EFI_SUCCESS;
+ } else if (((Los3 & B_PCH_PCR_FIA_L22O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_GBE) {
+ *LaneNum = 22;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] Usb3LaneIndex USB3 Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetUsb3LaneNum (
+ UINT32 Usb3LaneIndex,
+ UINT8 *LaneNum
+ )
+{
+ PCH_SERIES PchSeries;
+ UINT32 Los1;
+ UINT32 Los2;
+ UINT32 Los3;
+ UINT32 Los4;
+
+ PchSeries = GetPchSeries ();
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS1_REG_BASE, &Los1);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS2_REG_BASE, &Los2);
+
+ if (PchSeries == PchLp) {
+ switch (Usb3LaneIndex) {
+ case 0:
+ if ((Los1 & B_PCH_PCR_FIA_L0O) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 0;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los1 & B_PCH_PCR_FIA_L1O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 1;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if (((Los1 & B_PCH_PCR_FIA_L2O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 2;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 3:
+ if (((Los1 & B_PCH_PCR_FIA_L3O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 3;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 4:
+ if (((Los1 & B_PCH_PCR_FIA_L4O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 4;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 5:
+ if (((Los1 & B_PCH_PCR_FIA_L5O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 5;
+ return EFI_SUCCESS;
+ }
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported USB3 Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ } else {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS3_REG_BASE, &Los3);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS4_REG_BASE, &Los4);
+ switch (Usb3LaneIndex) {
+ case 0:
+ if ((Los1 & B_PCH_PCR_FIA_L0O) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 0;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los1 & B_PCH_PCR_FIA_L1O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 1;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if (((Los1 & B_PCH_PCR_FIA_L2O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 2;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 3:
+ if (((Los1 & B_PCH_PCR_FIA_L3O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 3;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 4:
+ if (((Los1 & B_PCH_PCR_FIA_L4O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 4;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 5:
+ if (((Los1 & B_PCH_PCR_FIA_L5O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 5;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 6:
+ if (((Los1 & B_PCH_PCR_FIA_L6O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 6;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 7:
+ if (((Los1 & B_PCH_PCR_FIA_L7O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 7;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 8:
+ if ((Los2 & B_PCH_PCR_FIA_L8O) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 8;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 9:
+ if (((Los2 & B_PCH_PCR_FIA_L9O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_USB3) {
+ *LaneNum = 9;
+ return EFI_SUCCESS;
+ }
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported USB3 Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] SataLaneIndex Sata Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetSataLaneNum (
+ UINT32 SataLaneIndex,
+ UINT8 *LaneNum
+ )
+{
+ PCH_SERIES PchSeries;
+ UINT32 Los1;
+ UINT32 Los2;
+ UINT32 Los3;
+ UINT32 Los4;
+
+ PchSeries = GetPchSeries ();
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS1_REG_BASE, &Los1);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS2_REG_BASE, &Los2);
+
+ if (PchSeries == PchLp) {
+ switch (SataLaneIndex) {
+ case 0:
+ if (((Los2 & B_PCH_PCR_FIA_L10O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 10;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los2 & B_PCH_PCR_FIA_L11O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 11;
+ return EFI_SUCCESS;
+ } else if (((Los2 & B_PCH_PCR_FIA_L14O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 14;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if (((Los2 & B_PCH_PCR_FIA_L15O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 15;
+ return EFI_SUCCESS;
+ }
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported SATA Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ } else {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS3_REG_BASE, &Los3);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS4_REG_BASE, &Los4);
+ switch (SataLaneIndex) {
+ case 0:
+ if (((Los3 & B_PCH_PCR_FIA_L18O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 18;
+ return EFI_SUCCESS;
+ } else if (((Los3 & B_PCH_PCR_FIA_L22O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 22;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los3 & B_PCH_PCR_FIA_L19O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 19;
+ return EFI_SUCCESS;
+ } else if (((Los3 & B_PCH_PCR_FIA_L23O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 23;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if ((Los4 & B_PCH_PCR_FIA_L24O) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 24;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 3:
+ if (((Los4 & B_PCH_PCR_FIA_L25O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 25;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 4:
+ if (((Los4 & B_PCH_PCR_FIA_L26O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 26;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 5:
+ if (((Los4 & B_PCH_PCR_FIA_L27O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 27;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 6:
+ if (((Los4 & B_PCH_PCR_FIA_L28O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 28;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 7:
+ if (((Los4 & B_PCH_PCR_FIA_L29O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_SATA) {
+ *LaneNum = 29;
+ return EFI_SUCCESS;
+ }
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported SATA Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Determine the lane number of a specified port
+
+ @param[in] PcieLaneIndex PCIE Root Port Lane Index
+ @param[out] LaneNum Lane Number
+
+ @retval EFI_SUCCESS Lane number valid.
+ @retval EFI_UNSUPPORTED Incorrect input device port
+**/
+EFI_STATUS
+PchGetPcieLaneNum (
+ UINT32 PcieLaneIndex,
+ UINT8 *LaneNum
+ )
+{
+ PCH_SERIES PchSeries;
+ UINT32 Los1;
+ UINT32 Los2;
+ UINT32 Los3;
+ UINT32 Los4;
+
+ PchSeries = GetPchSeries ();
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS1_REG_BASE, &Los1);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS2_REG_BASE, &Los2);
+
+ if (PchSeries == PchLp) {
+ switch (PcieLaneIndex) {
+ case 0:
+ if (((Los1 & B_PCH_PCR_FIA_L4O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 4;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los1 & B_PCH_PCR_FIA_L5O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 5;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if (((Los1 & B_PCH_PCR_FIA_L6O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 6;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 3:
+ if (((Los1 & B_PCH_PCR_FIA_L7O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 7;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 4:
+ if ((Los2 & B_PCH_PCR_FIA_L8O) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 8;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 5:
+ if (((Los2 & B_PCH_PCR_FIA_L9O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 9;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 6:
+ if (((Los2 & B_PCH_PCR_FIA_L10O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 10;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 7:
+ if (((Los2 & B_PCH_PCR_FIA_L11O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 11;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 8:
+ if (((Los2 & B_PCH_PCR_FIA_L12O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 12;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 9:
+ if (((Los2 & B_PCH_PCR_FIA_L13O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 13;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 10:
+ if (((Los2 & B_PCH_PCR_FIA_L14O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 14;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 11:
+ if (((Los2 & B_PCH_PCR_FIA_L15O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 15;
+ return EFI_SUCCESS;
+ }
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCIE Root Port Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ } else {
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS3_REG_BASE, &Los3);
+ PchPcrRead32 (PID_FIA, R_PCH_PCR_FIA_LOS4_REG_BASE, &Los4);
+ switch (PcieLaneIndex) {
+ case 0:
+ if (((Los1 & B_PCH_PCR_FIA_L6O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 6;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 1:
+ if (((Los1 & B_PCH_PCR_FIA_L7O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 7;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 2:
+ if ((Los2 & B_PCH_PCR_FIA_L8O) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 8;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 3:
+ if (((Los2 & B_PCH_PCR_FIA_L9O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 9;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 4:
+ if (((Los2 & B_PCH_PCR_FIA_L10O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 10;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 5:
+ if (((Los2 & B_PCH_PCR_FIA_L11O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 11;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 6:
+ if (((Los2 & B_PCH_PCR_FIA_L12O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 12;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 7:
+ if (((Los2 & B_PCH_PCR_FIA_L13O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 13;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 8:
+ if (((Los3 & B_PCH_PCR_FIA_L18O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 18;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 9:
+ if (((Los3 & B_PCH_PCR_FIA_L19O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 19;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 10:
+ if (((Los3 & B_PCH_PCR_FIA_L20O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 20;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 11:
+ if (((Los3 & B_PCH_PCR_FIA_L21O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 21;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 12:
+ if (((Los3 & B_PCH_PCR_FIA_L22O) >> 24) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 22;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 13:
+ if (((Los3 & B_PCH_PCR_FIA_L23O) >> 28) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 23;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 14:
+ if ((Los4 & B_PCH_PCR_FIA_L24O) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 24;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 15:
+ if (((Los4 & B_PCH_PCR_FIA_L25O) >> 4) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 25;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 16:
+ if (((Los4 & B_PCH_PCR_FIA_L26O) >> 8) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 26;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 17:
+ if (((Los4 & B_PCH_PCR_FIA_L27O) >> 12) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 27;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 18:
+ if (((Los4 & B_PCH_PCR_FIA_L28O) >> 16) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 28;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 19:
+ if (((Los4 & B_PCH_PCR_FIA_L29O) >> 20) == V_PCH_PCR_FIA_LANE_OWN_PCIEDMI) {
+ *LaneNum = 29;
+ return EFI_SUCCESS;
+ }
+ break;
+ case 20:
+ if (GetPchGeneration () == KblPch) { // there's no Los register for 4 last PCIe rootports on KBL
+ *LaneNum = 30;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ case 21:
+ if (GetPchGeneration () == KblPch) { // there's no Los register for 4 last PCIe rootports on KBL
+ *LaneNum = 31;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ case 22:
+ if (GetPchGeneration () == KblPch) { // there's no Los register for 4 last PCIe rootports on KBL
+ *LaneNum = 32;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ case 23:
+ if (GetPchGeneration () == KblPch) { // there's no Los register for 4 last PCIe rootports on KBL
+ *LaneNum = 33;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCIE Root Port Lane Index"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ break;
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Get HSIO lane representation needed to perform any operation on the lane.
+
+ @param[in] LaneIndex Number of the HSIO lane
+ @param[out] HsioLane HSIO lane representation
+**/
+VOID
+HsioGetLane (
+ IN UINT8 LaneIndex,
+ OUT HSIO_LANE *HsioLane
+ )
+{
+ // SPT-LP
+ // iolane 0 - 5 : 0xEA - 000, 200, 400, 600, 800, a00
+ // iolane 6 - 9 : 0xE9 - 000, 200, 400, 600
+ // iolane 10 - 15 : 0xA9 - 000, 200, 400, 600, 800, a00
+ // SPT-H
+ // iolane 0 - 5 : 0xEA - 000, 200, 400, 600, 800, a00
+ // iolane 6 - 13 : 0xE9 - 000, 200, 400, 600, 800, a00, c00, e00
+ // iolane 14 - 21 : 0xA9 - 000, 200, 400, 600, 800, a00, c00, e00
+ // iolane 22 - 29 : 0xA8 - 000, 200, 400, 600, 800, a00, c00, e00
+ // KBL-H: as for SKL-H plus the following lanes
+ // iolane 30 - 33 : 0xB0 - 000, 200, 400, 600
+
+ static UINT8 IoLanesLp[] = { 0, 6, 10, 16 };
+ static UINT8 IoLanesH[] = { 0, 6, 14, 22, 30, 34 };
+ static UINT8 Pids[] = { PID_MODPHY0, PID_MODPHY1, PID_MODPHY2, PID_MODPHY3, PID_MODPHY4 };
+
+ UINT8* IoLanes;
+ UINT8 PidMax;
+ UINT32 Index;
+
+ ASSERT (HsioLane != NULL);
+
+ if (GetPchSeries () == PchLp) {
+ IoLanes = IoLanesLp;
+ PidMax = 3;
+ } else {
+ IoLanes = IoLanesH;
+ if (GetPchGeneration () == KblPch) {
+ PidMax = 5;
+ } else {
+ PidMax = 4;
+ }
+ }
+ ASSERT (LaneIndex < IoLanes[PidMax]);
+
+ for (Index = 0; Index < PidMax; ++Index) {
+ if (LaneIndex < IoLanes[Index + 1]) {
+ HsioLane->Index = LaneIndex;
+ HsioLane->Pid = Pids[Index];
+ HsioLane->Base = (LaneIndex - IoLanes[Index]) * 0x200;
+ return;
+ }
+ }
+ ASSERT (FALSE);
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf
new file mode 100644
index 0000000000..f233f3e673
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchHsioLib/PeiDxeSmmPchHsioLib.inf
@@ -0,0 +1,44 @@
+## @file
+# PCH HSIO Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchHsioLib
+FILE_GUID = 6B2D3D0D-9A04-4E7C-AE84-1C2EF2E00E2E
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchHsioLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcrLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchHsioLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c
new file mode 100644
index 0000000000..3f72e006c8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c
@@ -0,0 +1,514 @@
+/** @file
+ Pch information library.
+
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchAccess.h>
+
+#define PCH_DO_STRINGIFY(x) #x
+#define PCH_STRINGIFY(x) PCH_DO_STRINGIFY(x)
+
+//
+// This module variables are used for cache the static result.
+// @note: please pay attention to the PEI phase, the module variables on ROM
+// and can't be modified.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_STEPPING mPchStepping = PchSteppingMax;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mIsPchSupported = 0xFF;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SERIES mPchSeries = PchUnknownSeries;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_GENERATION mPchGeneration = PchUnknownGeneration;
+
+/**
+ Return Pch stepping type
+
+ @retval PCH_STEPPING Pch stepping type
+**/
+PCH_STEPPING
+EFIAPI
+PchStepping (
+ VOID
+ )
+{
+ UINT8 RevId;
+ UINT16 LpcDeviceId;
+ UINTN LpcBaseAddress;
+#ifndef MDEPKG_NDEBUG
+ static CHAR8 *UnsupportedPchMsg = "Unsupported PCH. Supported stepping starting from";
+#endif
+
+ if (mPchStepping != PchSteppingMax) {
+ return mPchStepping;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ RevId = MmioRead8 (LpcBaseAddress + PCI_REVISION_ID_OFFSET);
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ if (IS_SKL_PCH_H_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+ case V_PCH_LPC_RID_10:
+ mPchStepping = PchHB0;
+ return PchHB0;
+
+ case V_PCH_LPC_RID_20:
+ mPchStepping = PchHC0;
+ return PchHC0;
+
+ case V_PCH_LPC_RID_30:
+ mPchStepping = PchHD0;
+ return PchHD0;
+
+ case V_PCH_LPC_RID_31:
+ mPchStepping = PchHD1;
+ return PchHD1;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "%a %a\n", UnsupportedPchMsg, PCH_STRINGIFY (SKL_PCH_H_MIN_SUPPORTED_STEPPING)));
+ return PchSteppingMax;
+ }
+ }
+
+ if (IS_KBL_PCH_H_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+ case V_PCH_LPC_RID_0:
+ mPchStepping = KblPchHA0;
+ return KblPchHA0;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "%a %a\n", UnsupportedPchMsg, PCH_STRINGIFY (KBL_PCH_H_MIN_SUPPORTED_STEPPING)));
+ return PchSteppingMax;
+ }
+ }
+
+ if (IS_PCH_LP_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+ case V_PCH_LPC_RID_10:
+ mPchStepping = PchLpB0;
+ return PchLpB0;
+
+ case V_PCH_LPC_RID_11:
+ mPchStepping = PchLpB1;
+ return PchLpB1;
+
+ case V_PCH_LPC_RID_20:
+ mPchStepping = PchLpC0;
+ return PchLpC0;
+
+ case V_PCH_LPC_RID_21:
+ mPchStepping = PchLpC1;
+ return PchLpC1;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "%a %a\n", UnsupportedPchMsg, PCH_STRINGIFY (PCH_LP_MIN_SUPPORTED_STEPPING)));
+ return PchSteppingMax;
+ }
+ }
+ return PchSteppingMax;
+}
+
+/**
+ Determine if PCH is supported
+
+ @retval TRUE PCH is supported
+ @retval FALSE PCH is not supported
+**/
+BOOLEAN
+IsPchSupported (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINT16 LpcVendorId;
+ UINTN LpcBaseAddress;
+
+ if (mIsPchSupported != 0xFF) {
+ return (BOOLEAN) mIsPchSupported;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+ LpcVendorId = MmioRead16 (LpcBaseAddress + PCI_VENDOR_ID_OFFSET);
+
+ ///
+ /// Verify that this is a supported chipset
+ ///
+ if ((LpcVendorId == V_PCH_LPC_VENDOR_ID) &&
+ (IS_PCH_LPC_DEVICE_ID (LpcDeviceId))) {
+ mIsPchSupported = TRUE;
+ return TRUE;
+ } else {
+ DEBUG ((DEBUG_ERROR, "PCH code doesn't support the LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ mIsPchSupported = FALSE;
+ return FALSE;
+ }
+}
+
+/**
+ Return Pch Series
+
+ @retval PCH_SERIES Pch Series
+**/
+PCH_SERIES
+EFIAPI
+GetPchSeries (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINT32 PchSeries;
+
+ if (mPchSeries != PchUnknownSeries) {
+ return mPchSeries;
+ }
+
+ LpcDeviceId = GetLpcDid ();
+
+ if (IS_PCH_H_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchSeries = PchH;
+ } else if (IS_PCH_LP_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchSeries = PchLp;
+ } else {
+ PchSeries = PchUnknownSeries;
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ ASSERT (FALSE);
+ }
+ mPchSeries = PchSeries;
+
+ return PchSeries;
+}
+
+/**
+ Return Pch Generation
+
+ @retval PCH_GENERATION Pch Generation
+**/
+PCH_GENERATION
+EFIAPI
+GetPchGeneration (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ PCH_GENERATION PchGen;
+
+ if (mPchGeneration != PchUnknownGeneration) {
+ return mPchGeneration;
+ }
+
+ LpcDeviceId = GetLpcDid ();
+
+ if (IS_SKL_PCH_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchGen = SklPch;
+ } else if (IS_KBL_PCH_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchGen = KblPch;
+ } else {
+ PchGen = PchUnknownGeneration;
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ ASSERT (FALSE);
+ }
+ mPchGeneration = PchGen;
+
+ return PchGen;
+}
+
+/**
+ Get PCH SKU type
+
+ @retval PCH_SKU_TYPE Type of PCH SKU
+**/
+PCH_SKU_TYPE
+GetPchSkuType (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+
+ LpcDeviceId = GetLpcDid ();
+
+ if (IS_PCH_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) {
+ return PchMobileSku;
+ } else if (IS_PCH_LPC_DEVICE_ID_DESKTOP (LpcDeviceId)) {
+ return PchDesktopSku;
+ } else if (IS_PCH_LPC_DEVICE_ID_SERVER (LpcDeviceId)) {
+ return PchServerSku;
+ } else {
+ return PchUnknownSku;
+ }
+}
+
+/**
+ Get Pch Maximum Pcie Root Port Number
+
+ @retval Pch Maximum Pcie Root Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPciePortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_PCIE_MAX_ROOT_PORTS;
+
+ case PchH:
+ switch (GetPchGeneration ()) {
+ case SklPch:
+ return SKL_PCH_H_PCIE_MAX_ROOT_PORTS;
+ case KblPch:
+ return KBL_PCH_H_PCIE_MAX_ROOT_PORTS;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Sata Port Number
+
+ @retval Pch Maximum Sata Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxSataPortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_AHCI_MAX_PORTS;
+
+ case PchH:
+ return PCH_H_AHCI_MAX_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Usb Maximum Physical Port Number
+
+ @retval Pch Usb Maximum Physical Port Number
+**/
+UINT8
+EFIAPI
+GetPchUsbMaxPhysicalPortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB2_PHYSICAL_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB2_PHYSICAL_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Usb2 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb2 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb2PortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB2_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB2_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Usb3 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb3 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb3PortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB3_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB3_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Lpc Did
+
+ @retval UINT16 Lpc Did
+**/
+UINT16
+EFIAPI
+GetLpcDid (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINTN LpcBaseAddress;
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ return LpcDeviceId;
+}
+
+/**
+ Get RST mode supported by the silicon
+
+ @retval RST_MODE RST mode supported by silicon
+**/
+RST_MODE
+EFIAPI
+GetSupportedRstMode (
+ VOID
+ )
+{
+ if (IsPchRaidSupported ()) {
+ return RstPremium;
+ } else if (IsOptaneModeSupported ()) {
+ return RstOptane;
+ } else {
+ return RstUnsupported;
+ }
+}
+
+/**
+ Check if current SKU supports Optane mode
+
+ @retval TRUE This SKU supports Optane mode
+ @retval FALSE This SKU doesn't support Optane mode
+**/
+BOOLEAN
+EFIAPI
+IsOptaneModeSupported (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ BOOLEAN OptaneSupported;
+
+ LpcDeviceId = GetLpcDid ();
+
+ switch (LpcDeviceId) {
+ case V_KBL_PCH_H_LPC_DEVICE_ID_DT_B250:
+ case V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q250:
+ OptaneSupported = TRUE;
+ break;
+ default:
+ OptaneSupported = FALSE;
+ break;
+ }
+
+ return OptaneSupported;
+}
+
+/**
+ Check if current SKU supports RAID feature
+
+ @retval TRUE This SKU supports RAID
+ @retval FALSE This SKU doesn't support RAID
+**/
+BOOLEAN
+EFIAPI
+IsPchRaidSupported (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ BOOLEAN RaidSupported;
+
+ LpcDeviceId = GetLpcDid ();
+
+
+ switch (LpcDeviceId) {
+ case V_PCH_LP_LPC_DEVICE_ID_MB_1: // SPT-LP Base-U (SPT-LP Mobile)
+ case V_PCH_LP_LPC_DEVICE_ID_MB_5: // KBL-LP Base-U (KBL-LP Mobile)
+ case V_PCH_LP_LPC_DEVICE_ID_MB_10: // KBL-LP Mobile (U) iHDCP 2.2 Base
+ case V_SKL_PCH_H_LPC_DEVICE_ID_DT_1: // H110 (SPT-H Desktop)
+ case V_SKL_PCH_H_LPC_DEVICE_ID_DT_6: // B150 (SPT-H Desktop)
+ case V_SKL_PCH_H_LPC_DEVICE_ID_DT_5: // Q150 (SPT-H Desktop)
+ case V_KBL_PCH_H_LPC_DEVICE_ID_DT_B250: // B250 (KBL-H Desktop)
+ case V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q250: // Q250 (KBL-H Desktop)
+ case V_SKL_PCH_H_LPC_DEVICE_ID_SVR_1: // C232 (SPT-H Server)
+ RaidSupported = FALSE;
+ break;
+ default:
+ RaidSupported = TRUE;
+ break;
+ }
+
+ return RaidSupported;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c
new file mode 100644
index 0000000000..6fb06eac2f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c
@@ -0,0 +1,334 @@
+/** @file
+ Pch information string library.
+
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchAccess.h>
+
+/**
+ Structure for PCH stepping string mapping
+**/
+struct PCH_STEPPING_STRING {
+ PCH_STEPPING Stepping;
+ CHAR8 *String;
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+struct PCH_STEPPING_STRING mSteppingStrs[] = {
+ {PchHB0, "B0"},
+ {PchHC0, "C0"},
+ {PchHD0, "D0"},
+ {PchHD1, "D1"},
+ {PchLpB0, "B0"},
+ {PchLpB1, "B1"},
+ {PchLpC0, "C0"},
+ {PchLpC1, "C1"},
+ {KblPchHA0, "A0"},
+ {PchSteppingMax, NULL}
+};
+
+/**
+ Structure for PCH series string mapping
+**/
+typedef struct {
+ PCH_SERIES Series;
+ CHAR8 *String;
+} PCH_SERIES_STRING ;
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+PCH_SERIES_STRING mSklPchSeriesStrs[] = {
+ {PchH, "SKL PCH-H"},
+ {PchLp, "SKL PCH-LP"},
+ {PchUnknownSeries, NULL}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+PCH_SERIES_STRING mKblPchSeriesStrs[] = {
+ {PchH, "KBL PCH-H"},
+ {PchUnknownSeries, NULL}
+};
+
+/**
+ Structure for PCH sku string mapping
+**/
+struct PCH_SKU_STRING {
+ UINT16 Id;
+ CHAR8 *String;
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+struct PCH_SKU_STRING mSkuStrs[] = {
+ //
+ // SKL PCH H Desktop LPC Device IDs
+ //
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU, "Super SKU"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_ES_SUPER_SKU, "ES Super SKU"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_0, "Super SKU (locked)"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_1, "H110"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_2, "H170"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_3, "Z170"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_4, "Q170"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_5, "Q150"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_DT_6, "B150"},
+ //
+ // SKL PCH H Server/WS LPC Device IDs
+ //
+ {V_SKL_PCH_H_LPC_DEVICE_ID_SVR_0, "C236"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_SVR_1, "C232"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_SVR_2, "CM236"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_A14B, "Super SKU (Unlocked)"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_ES_SUPER_SKU, "ES Super SKU (Unlocked)"},
+ //
+ // SKL PCH H Mobile LPC Device IDs
+ //
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_0, "QM170"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_1, "HM170"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_3, "QMS180"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_4, "HM175"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_5, "QM175"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_6, "CM238"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_SUPER_SKU, "Super SKU"},
+ {V_SKL_PCH_H_LPC_DEVICE_ID_MB_8, "QMS185"},
+ //
+ // SKL PCH LP Mobile LPC Device IDs
+ //
+ {V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU, "Super SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_0, "Super SKU (locked)"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_1, "(U) Base SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_2, "(Y) Premium SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_3, "(U) Premium SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU_1, "Super SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_4, "Super SKU (locked)"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_5, "(U) Base SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_6, "(Y) Premium SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_7, "(U) Premium SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_8, "(Y) iHDCP 2.2 Premium"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_9, "(U) iHDCP 2.2 Premium"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_10, "(U) iHDCP 2.2 Base"},
+ //
+ // KBL PCH H Desktop LPC Device IDs
+ //
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU, "Super SKU"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_H270, "H270"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z270, "Z270"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q270, "Q270"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_Q250, "Q250"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_B250, "B250"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_H215, "H215"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_DT_Z370, "Z370"},
+
+ //
+ // KBL PCH H Server/WS LPC Device IDs
+ //
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_SUPER_SKU, "Super SKU (Unlocked)"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_0, "X290"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_1, "C6xx"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_2, "ES Super SKU Server (Interposer)"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_3, "Super SKU Server"},
+ {V_KBL_PCH_H_LPC_DEVICE_ID_SVR_4, "C422B"},
+ {0xFFFF, NULL}
+};
+
+/**
+ Get PCH stepping ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchStep Pch stepping
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The stepping is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSteppingStr (
+ IN PCH_STEPPING PchStep,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; mSteppingStrs[Index].Stepping != PchSteppingMax; Index++) {
+ if (PchStep == mSteppingStrs[Index].Stepping) {
+ StrLength = (UINT32) AsciiStrLen (mSteppingStrs[Index].String);
+ Str = mSteppingStrs[Index].String;
+ break;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Stepping
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ AsciiStrCpyS (Buffer, *BufferSize, Str);
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH series ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchSeries Pch series
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSeriesStr (
+ IN PCH_SERIES PchSeries,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+ PCH_GENERATION PchGen;
+ PCH_SERIES_STRING *SeriesStrs;
+ UINT16 LpcDeviceId;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PchGen = GetPchGeneration ();
+
+ if (PchGen == SklPch) {
+ //
+ // Check if Client/Server ES Super SKU
+ //
+
+ LpcDeviceId = GetLpcDid ();
+
+ if ((LpcDeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_DT_ES_SUPER_SKU) ||
+ (LpcDeviceId == V_KBL_PCH_H_LPC_DEVICE_ID_SVR_ES_SUPER_SKU)) {
+ SeriesStrs = mKblPchSeriesStrs;
+ } else {
+ SeriesStrs = mSklPchSeriesStrs;
+ }
+ } else if (PchGen == KblPch){
+ SeriesStrs = mKblPchSeriesStrs;
+ } else {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; SeriesStrs[Index].Series != PchUnknownSeries; Index++) {
+ if (PchSeries == SeriesStrs[Index].Series) {
+ StrLength = (UINT32) AsciiStrLen (SeriesStrs[Index].String);
+ Str = SeriesStrs[Index].String;
+ break;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Series
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ AsciiStrCpyS (Buffer, *BufferSize, Str);
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH Sku ASCII string
+ The return string is zero terminated.
+
+ @param [in] LpcDid LPC device id
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSkuStr (
+ IN UINT16 LpcDid,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; mSkuStrs[Index].Id != 0xFFFF; Index++) {
+ if (LpcDid == mSkuStrs[Index].Id) {
+ StrLength = (UINT32) AsciiStrLen (mSkuStrs[Index].String);
+ Str = mSkuStrs[Index].String;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Sku
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ AsciiStrCpyS (Buffer, *BufferSize, Str);
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf
new file mode 100644
index 0000000000..35566d8243
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf
@@ -0,0 +1,43 @@
+## @file
+# PCH information library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchInfoLib
+FILE_GUID = D43F3086-1D7E-4FF5-AE6A-3B0E15B11329
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchInfoLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchInfoLib.c
+PchInfoStrLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c
new file mode 100644
index 0000000000..dba89d3edc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c
@@ -0,0 +1,338 @@
+/** @file
+ PCH P2sb access lib.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+
+/**
+ Get P2SB pci configuration register. (This is internal function)
+ It returns register at Offset of P2SB controller and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchP2sbCfgGet (
+ IN UINTN Offset,
+ IN UINTN Size,
+ OUT UINT32 *OutData
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN DevicePresent;
+
+ if ((Offset > 255) ||
+ ((Offset & (Size - 1)) != 0)) {
+ DEBUG ((DEBUG_ERROR, "PchP2sbCfgGet error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, 0);
+ }
+ ASSERT (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+
+ switch (Size) {
+ case 4:
+ *(UINT32*) OutData = MmioRead32 (P2sbBase + Offset);
+ break;
+ case 2:
+ *(UINT16*) OutData = MmioRead16 (P2sbBase + Offset);
+ break;
+ case 1:
+ *(UINT8*) OutData = MmioRead8 (P2sbBase + Offset);
+ break;
+ default:
+ break;
+ }
+
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, BIT0);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet32 (
+ IN UINTN Offset,
+ OUT UINT32 *OutData
+ )
+{
+ return PchP2sbCfgGet (Offset, 4, (UINT32*) OutData);
+}
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 2bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet16 (
+ IN UINTN Offset,
+ OUT UINT16 *OutData
+ )
+{
+ return PchP2sbCfgGet (Offset, 2, (UINT32*) OutData);
+}
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 1byte.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet8 (
+ IN UINTN Offset,
+ OUT UINT8 *OutData
+ )
+{
+ return PchP2sbCfgGet (Offset, 1, (UINT32*) OutData);
+}
+
+/**
+ Set P2SB pci configuration register. (This is internal function)
+ It programs register at Offset of P2SB controller and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchP2sbCfgSet (
+ IN UINTN Offset,
+ IN UINTN Size,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN DevicePresent;
+ UINT32 Data32;
+
+ if ((Offset > 255) ||
+ ((Offset & (Size - 1)) != 0)) {
+ DEBUG ((DEBUG_ERROR, "PchP2sbCfgSet error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data32 = 0;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, 0);
+ }
+ ASSERT (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+
+ switch (Size) {
+ case 4:
+ Data32 = MmioRead32 (P2sbBase + Offset);
+ Data32 &= AndData;
+ Data32 |= OrData;
+ MmioWrite32 (P2sbBase + Offset, (UINT32) Data32);
+ break;
+ case 2:
+ Data32 = MmioRead16 (P2sbBase + Offset);
+ Data32 &= AndData;
+ Data32 |= OrData;
+ MmioWrite16 (P2sbBase + Offset, (UINT16) Data32);
+ break;
+ case 1:
+ Data32 = MmioRead8 (P2sbBase + Offset);
+ Data32 &= AndData;
+ Data32 |= OrData;
+ MmioWrite8 (P2sbBase + Offset, (UINT8) Data32);
+ break;
+ default:
+ break;
+ }
+
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, BIT0);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet32 (
+ IN UINTN Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PchP2sbCfgSet (Offset, 4, AndData, OrData);
+}
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 2bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet16 (
+ IN UINTN Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PchP2sbCfgSet (Offset, 2, AndData, OrData);
+}
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 1bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet8 (
+ IN UINTN Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PchP2sbCfgSet (Offset, 1, AndData, OrData);
+}
+
+/**
+ Hide P2SB device.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+PchHideP2sb (
+ IN UINTN P2sbBase
+ )
+{
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, BIT0);
+ return EFI_SUCCESS;
+}
+
+/**
+ Reveal P2SB device.
+ Also return the original P2SB status which is for Hidding P2SB or not after.
+ If OrgStatus is not NULL, then TRUE means P2SB is unhidden,
+ and FALSE means P2SB is hidden originally.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+ @param[out] OrgStatus Original P2SB hidding/unhidden status
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+PchRevealP2sb (
+ IN UINTN P2sbBase,
+ OUT BOOLEAN *OrgStatus
+ )
+{
+ BOOLEAN DevicePresent;
+
+ DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+ if (OrgStatus != NULL) {
+ *OrgStatus = DevicePresent;
+ }
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, 0);
+ }
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf
new file mode 100644
index 0000000000..115175f8a2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf
@@ -0,0 +1,42 @@
+## @file
+# PCH P2sb access Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchP2sbLib
+FILE_GUID = FB044F6F-5F9F-48AB-AE12-1C0B829C8AD7
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchP2sbLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchP2sbLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c
new file mode 100644
index 0000000000..6b8a51d8d2
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c
@@ -0,0 +1,268 @@
+/** @file
+ PCH PCIE root port library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchPcieRpLib.h>
+
+//
+// For SKL PCH-LP, it supports three express port controllers:
+// Controller 1:
+// Port 1-4, Device 28, function 0-3
+// Controller 2:
+// Port 5-8, Device 28, function 4-7
+// Controller 3:
+// port 9-12, Device 29, function 0-3
+// For SKL PCH-H, it supports five express port controllers:
+// Controller 1:
+// Port 1-4, Device 28, function 0-3
+// Controller 2:
+// Port 5-8, Device 28, function 4-7
+// Controller 3:
+// port 9-12, Device 29, function 0-3
+// Controller 4:
+// Port 13-16, Device 29, function 4-7
+// Controller 5:
+// port 17-20, Device 27, function 0-3
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_PCIE_CONTROLLER_INFO mPchPcieControllerInfo[] = {
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1, PID_SPA, 0 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1, PID_SPB, 4 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2, PID_SPC, 8 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2, PID_SPD, 12 }, // SKL-H and KBL-H only
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3, PID_SPE, 16 }, // SKL-H and KBL-H only
+ { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3, PID_SPF, 20 } // KBL-H only
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 mPchPcieControllerInfoSize = sizeof (mPchPcieControllerInfo) / sizeof (mPchPcieControllerInfo[0]);
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchLpRstPcieStorageSupportedPort[] = {
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4
+ RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, // RP5..RP8
+ RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3 // RP9..RP12
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSklPchHRstPcieStorageSupportedPort[] = {
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP5..RP8
+ RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, // RP9..RP12
+ RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, // RP13..RP16
+ RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3 // RP17..RP20
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mKblPchHRstPcieStorageSupportedPort[] = {
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP5..RP8
+ RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, // RP9..RP12
+ RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP13..RP16
+ RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, // RP17..RP20
+ RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2 // RP21..RP24
+};
+
+/**
+ Get Pch Pcie Root Port Device and Function Number by Root Port physical Number
+
+ @param[in] RpNumber Root port physical number. (0-based)
+ @param[out] RpDev Return corresponding root port device number.
+ @param[out] RpFun Return corresponding root port function number.
+
+ @retval EFI_SUCCESS Root port device and function is retrieved
+ @retval EFI_INVALID_PARAMETER RpNumber is invalid
+**/
+EFI_STATUS
+EFIAPI
+GetPchPcieRpDevFun (
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ )
+{
+ UINTN Index;
+ UINTN FuncIndex;
+ UINT32 PciePcd;
+
+ //
+ // if SKL PCH-LP, RpNumber must be < 12.
+ // if SKL PCH-H , RpNumber must be < 20.
+ // if KBL PCH-H , RpNumber must be < 24.
+ //
+ if (RpNumber >= GetPchMaxPciePortNum ()) {
+ DEBUG ((DEBUG_ERROR, "GetPchPcieRpDevFun invalid RpNumber %x", RpNumber));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Index = RpNumber / PCH_PCIE_CONTROLLER_PORTS;
+ FuncIndex = RpNumber - mPchPcieControllerInfo[Index].RpNumBase;
+ *RpDev = mPchPcieControllerInfo[Index].DevNum;
+ PchPcrRead32 (mPchPcieControllerInfo[Index].Pid, R_PCH_PCR_SPX_PCD, &PciePcd);
+ *RpFun = (PciePcd >> (FuncIndex * S_PCH_PCR_SPX_PCD_RP_FIELD)) & B_PCH_PCR_SPX_PCD_RP1FN;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Root Port physical Number by Pch Pcie Root Port Device and Function Number
+
+ @param[in] RpDev Root port device number.
+ @param[in] RpFun Root port function number.
+ @param[out] RpNumber Return corresponding physical Root Port index (0-based)
+
+ @retval EFI_SUCCESS Physical root port is retrieved
+ @retval EFI_INVALID_PARAMETER RpDev and/or RpFun are invalid
+ @retval EFI_UNSUPPORTED Root port device and function is not assigned to any physical root port
+**/
+EFI_STATUS
+EFIAPI
+GetPchPcieRpNumber (
+ IN UINTN RpDev,
+ IN UINTN RpFun,
+ OUT UINTN *RpNumber
+ )
+{
+ UINTN Index;
+ UINTN FuncIndex;
+ UINT32 PciePcd;
+ UINT8 MaxPorts;
+
+ MaxPorts = GetPchMaxPciePortNum ();
+ if ( !((RpDev == PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1) && (RpFun < 8) && (RpFun < MaxPorts)) &&
+ !((RpDev == PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2) && (RpFun < 8) && (RpFun + 8 < MaxPorts)) &&
+ !((RpDev == PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3) && (RpFun < 8) && (RpFun + 16 < MaxPorts)) ) {
+ DEBUG ((DEBUG_ERROR, "GetPchPcieRpNumber invalid RpDev %x RpFun %x", RpDev, RpFun));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Index = 0; Index < mPchPcieControllerInfoSize; Index++) {
+ if (mPchPcieControllerInfo[Index].DevNum == RpDev) {
+ PchPcrRead32 (mPchPcieControllerInfo[Index].Pid, R_PCH_PCR_SPX_PCD, &PciePcd);
+ for (FuncIndex = 0; FuncIndex < 4; FuncIndex ++) {
+ if (RpFun == ((PciePcd >> (FuncIndex * S_PCH_PCR_SPX_PCD_RP_FIELD)) & B_PCH_PCR_SPX_PCD_RP1FN)) {
+ break;
+ }
+ }
+ if (FuncIndex < 4) {
+ *RpNumber = mPchPcieControllerInfo[Index].RpNumBase + FuncIndex;
+ break;
+ }
+ }
+ }
+ if (Index >= mPchPcieControllerInfoSize) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Gets base address of PCIe root port.
+
+ @param RpIndex Root Port Index (0 based)
+ @return PCIe port base address.
+**/
+UINTN
+PchPcieBase (
+ IN UINT32 RpIndex
+ )
+{
+ UINTN RpDevice;
+ UINTN RpFunction;
+ GetPchPcieRpDevFun (RpIndex, &RpDevice, &RpFunction);
+ return MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDevice, (UINT32) RpFunction);
+}
+
+/**
+ Determines whether L0s is supported on current stepping.
+
+ @return TRUE if L0s is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieL0sSupported (
+ VOID
+ )
+{
+ if (GetPchGeneration () == SklPch) {
+ if (GetPchSeries () == PchLp) {
+ if (PchStepping () < PchLpC0) {
+ return FALSE;
+ }
+ } else {
+ if (PchStepping () < PchHD0) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Some early SKL PCH steppings require Native ASPM to be disabled due to hardware issues:
+ - RxL0s exit causes recovery
+ - Disabling PCIe L0s capability disables L1
+ Use this function to determine affected steppings.
+
+ @return TRUE if Native ASPM is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieNativeAspmSupported (
+ VOID
+ )
+{
+ return PchIsPcieL0sSupported ();
+}
+
+/**
+ Check the RST PCIe Storage Cycle Router number according to the root port number and PCH type
+
+ @param[in] RootPortNum Root Port Number
+
+ @retval UINT32 The RST PCIe Storage Cycle Router Number
+**/
+UINT32
+RstGetCycleRouterNumber (
+ IN UINT32 RootPortNum
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if (PchSeries == PchLp) {
+ if (RootPortNum < PCH_LP_PCIE_MAX_ROOT_PORTS) {
+ return mPchLpRstPcieStorageSupportedPort[RootPortNum];
+ }
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ if (RootPortNum < KBL_PCH_H_PCIE_MAX_ROOT_PORTS) {
+ return mKblPchHRstPcieStorageSupportedPort[RootPortNum];
+ }
+ } else {
+ if (RootPortNum < SKL_PCH_H_PCIE_MAX_ROOT_PORTS) {
+ return mSklPchHRstPcieStorageSupportedPort[RootPortNum];
+ }
+ }
+ }
+ return RST_PCIE_STORAGE_CR_INVALID;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf
new file mode 100644
index 0000000000..79ddb969ae
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf
@@ -0,0 +1,44 @@
+## @file
+# PCH PCIE root port Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchPcieRpLib
+FILE_GUID = B4129C2C-E0C5-4E04-A82A-C61D4F0B2C75
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPcieRpLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcrLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchPcieRpLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
new file mode 100644
index 0000000000..e2585c36e0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
@@ -0,0 +1,458 @@
+/** @file
+ PCH PCR library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+
+/**
+ Read PCR register. (This is internal function)
+ It returns PCR register and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchPcrRead (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINTN Size,
+ OUT UINT32 *OutData
+ )
+{
+ if ((Offset & (Size - 1)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPcrRead error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // @todo SKL PCH: check PID that not expected to use this routine, such as CAM_FLIS, CSME0
+ //
+
+ switch (Size) {
+ case 4:
+ *(UINT32*) OutData = MmioRead32 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ case 2:
+ *(UINT16*) OutData = MmioRead16 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ case 1:
+ *(UINT8*) OutData = MmioRead8 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ default:
+ break;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT32 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 4, (UINT32*) OutData);
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT16 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 2, (UINT32*) OutData);
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT8 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 1, (UINT32*) OutData);
+}
+
+BOOLEAN
+PchPcrWriteMmioCheck (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ //
+ // 1. USB2 AFE register must use SBI method
+ //
+
+ //
+ // 2. GPIO unlock register field must use SBI method
+ //
+ if (Pid == PID_GPIOCOM0) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCKTX)))) {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM1) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCKTX)))) {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM2) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPD_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPD_PADCFGLOCKTX)))) {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM3) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCKTX)))) {
+ return FALSE;
+ }
+ }
+ //
+ // 3. CIO2 FLIS regsiter must use SBI method
+ //
+
+ //
+ // 4. CSME0 based PCR should use the SBI method due to the FID requirement
+ //
+ if (Pid == PID_CSME0) {
+ return FALSE;
+ }
+ DEBUG_CODE_END ();
+ return TRUE;
+
+}
+
+/**
+ Write PCR register. (This is internal function)
+ It programs PCR register and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchPcrWrite (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINTN Size,
+ IN UINT32 InData
+ )
+{
+ if ((Offset & (Size - 1)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPcrWrite error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ DEBUG_CODE_BEGIN ();
+ if (!PchPcrWriteMmioCheck (Pid, Offset)) {
+ DEBUG ((DEBUG_ERROR, "PchPcrWrite error. Pid: %x Offset: %x should access through SBI interface", Pid, Offset));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ DEBUG_CODE_END ();
+
+ //
+ // Write the PCR register with provided data
+ // Then read back PCR register to prevent from back to back write.
+ //
+ switch (Size) {
+ case 4:
+ MmioWrite32 (PCH_PCR_ADDRESS (Pid, Offset), (UINT32) InData);
+ break;
+ case 2:
+ MmioWrite16 (PCH_PCR_ADDRESS (Pid, Offset), (UINT16) InData);
+ break;
+ case 1:
+ MmioWrite8 (PCH_PCR_ADDRESS (Pid, Offset), (UINT8) InData);
+ break;
+ default:
+ break;
+ }
+ MmioRead32 (PCH_PCR_ADDRESS (PID_LPC, R_PCH_PCR_LPC_GCFD));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 4, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 2, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 1, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+
+ Data32 = 0x00;
+ Status = PchPcrRead (Pid, Offset, 4, &Data32);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data32 &= AndData;
+ Data32 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 4, Data32);
+ return Status;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Data16;
+
+ Data16 = 0x00;
+ Status = PchPcrRead (Pid, Offset, 2, (UINT32*) &Data16);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data16 &= AndData;
+ Data16 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 2, Data16);
+ return Status;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data8;
+
+ Status = PchPcrRead (Pid, Offset, 1, (UINT32*) &Data8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data8 &= AndData;
+ Data8 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 1, Data8);
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
new file mode 100644
index 0000000000..fdc523143f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
@@ -0,0 +1,43 @@
+## @file
+# PCH PCR Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchPcrLib
+FILE_GUID = 117C8D19-445B-46BF-B624-109F63709375
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPcrLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchPcrLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c
new file mode 100644
index 0000000000..1985d5d133
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c
@@ -0,0 +1,136 @@
+/** @file
+ PCH PMC Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPmcLib.h>
+
+/**
+ Query PCH to determine the Pm Status
+ NOTE:
+ It's matter when did platform code use this library, since some status could be cleared by write one clear.
+ Therefore this funciton is not always return the same result in one boot.
+ It's suggested that platform code read this status in the beginning of post.
+ For the ColdBoot case, this function only returns one case of the cold boot. Some cold boot case might
+ depends on the power cycle scenario and should check with different condtion.
+
+ @param[in] PmStatus - The Pch Pm Status to be probed
+
+ @retval Return TRUE if Status querried is Valid or FALSE if otherwise
+**/
+BOOLEAN
+GetPchPmStatus (
+ PCH_PM_STATUS PmStatus
+ )
+{
+ UINTN PmcRegBase;
+ UINT32 PchPwrmBase;
+ UINT32 PmConA;
+ UINT32 PmConB;
+ UINT32 GblRst0;
+
+ PmcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ PmConA = MmioRead32 (PmcRegBase + R_PCH_PMC_GEN_PMCON_A);
+ PmConB = MmioRead32 (PmcRegBase + R_PCH_PMC_GEN_PMCON_B);
+
+ GblRst0 = MmioRead32 (PchPwrmBase + R_PCH_PWRM_124);
+
+ switch (PmStatus) {
+ case WarmBoot:
+ if (PmConA & B_PCH_PMC_GEN_PMCON_A_MEM_SR) {
+ return TRUE;
+ }
+ break;
+
+ case PwrFlr:
+ if (PmConB & B_PCH_PMC_GEN_PMCON_B_PWR_FLR) {
+ return TRUE;
+ }
+ break;
+
+ case PwrFlrSys:
+ if (GblRst0 & BIT12) {
+ return TRUE;
+ }
+ break;
+
+ case PwrFlrPch:
+ if (GblRst0 & BIT11) {
+ return TRUE;
+ }
+ break;
+
+ case ColdBoot:
+ ///
+ /// Check following conditions for cold boot.
+ ///
+ if ((GblRst0 & BIT11) && // PCHPWR_FLR
+ (GblRst0 & BIT12) && // SYSPWR_FLR
+ (!(PmConA & B_PCH_PMC_GEN_PMCON_A_MEM_SR))) {
+ return TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+/**
+ Funtion to check if Battery lost or CMOS cleared.
+
+ @reval TRUE Battery is always present.
+ @reval FALSE CMOS is cleared.
+**/
+BOOLEAN
+EFIAPI
+PchIsRtcBatteryGood (
+ VOID
+ )
+{
+ UINTN Data;
+ UINTN PmcBaseAddress;
+
+ //
+ // Check if the CMOS battery is present
+ // Checks RTC_PWR_STS bit in the GEN_PMCON_3 register
+ //
+ PmcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ Data = MmioRead32 (PmcBaseAddress + R_PCH_PMC_GEN_PMCON_B);
+
+ if ((Data & B_PCH_PMC_GEN_PMCON_B_RTC_PWR_STS) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf
new file mode 100644
index 0000000000..bd3a33ff70
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf
@@ -0,0 +1,43 @@
+## @file
+# PEI/DXE/SMM PCH PMC Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchPmcLib
+FILE_GUID = 9D60C364-5086-41E3-BC9D-C62AB7233DBF
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPmcLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchPmcLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PchPsfLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PchPsfLib.c
new file mode 100644
index 0000000000..08a28f7e6d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PchPsfLib.c
@@ -0,0 +1,448 @@
+/** @file
+ This file contains PSF routines
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchPsfLib.h>
+#include <Library/PchInfoLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPchLpSerialIoPsfRegs[PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C0_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C1_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C2_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C3_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C4_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_I2C5_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_SPI0_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_SPI1_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_UART0_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_UART1_REG_BASE,
+ R_PCH_LP_PCR_PSF3_T0_SHDW_UART2_REG_BASE
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPchHSerialIoPsfRegs[PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ R_PCH_H_PCR_PSF3_T0_SHDW_I2C0_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_I2C1_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_I2C2_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_I2C3_REG_BASE,
+ 0,
+ 0,
+ R_PCH_H_PCR_PSF3_T0_SHDW_SPI0_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_SPI1_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_UART0_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_UART1_REG_BASE,
+ R_PCH_H_PCR_PSF3_T0_SHDW_UART2_REG_BASE
+};
+
+/**
+ This procedure will enable SerialIO device BAR1 at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfEnableSerialIoDeviceBar1 (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ )
+{
+ UINT32 *SerialIoPsfReg;
+
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPsfReg = mPchLpSerialIoPsfRegs;
+ } else {
+ SerialIoPsfReg = mPchHSerialIoPsfRegs;
+ if ((SerialIoDevice == PchSerialIoIndexI2C4) ||
+ (SerialIoDevice == PchSerialIoIndexI2C5)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ //
+ // Set AGNT_T0_SHDW_PCIEN[19:18] = 00b
+ // SerialIo device BAR is 64bit wide so to enable BAR1
+ // at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be enabled
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ (UINT16)SerialIoPsfReg[SerialIoDevice] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32)~(B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS),
+ 0
+ );
+}
+
+/**
+ This procedure will disable SerialIO device BAR1 at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfDisableSerialIoDeviceBar1 (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ )
+{
+ UINT32 *SerialIoPsfReg;
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPsfReg = mPchLpSerialIoPsfRegs;
+ } else {
+ SerialIoPsfReg = mPchHSerialIoPsfRegs;
+ if ((SerialIoDevice == PchSerialIoIndexI2C4) ||
+ (SerialIoDevice == PchSerialIoIndexI2C5)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ //
+ // Set AGNT_T0_SHDW_PCIEN[19:18] = 11b
+ // SerialIo device BAR is 64bit wide so to disable BAR1
+ // at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be disabled
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ (UINT16)SerialIoPsfReg[SerialIoDevice] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ (B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS)
+ );
+}
+
+/**
+ This procedure will disable SerailIO device at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfDisableSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ )
+{
+ UINT32 *SerialIoPsfReg;
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPsfReg = mPchLpSerialIoPsfRegs;
+ } else {
+ SerialIoPsfReg = mPchHSerialIoPsfRegs;
+ if ((SerialIoDevice == PchSerialIoIndexI2C4) ||
+ (SerialIoDevice == PchSerialIoIndexI2C5)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ (UINT16)SerialIoPsfReg[SerialIoDevice] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ 0xFFFFFFFF,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ This procedure will hide SerialIo device PciCfgSpace at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfHideSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ )
+{
+ UINT32 *SerialIoPsfReg;
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPsfReg = mPchLpSerialIoPsfRegs;
+ } else {
+ SerialIoPsfReg = mPchHSerialIoPsfRegs;
+ if ((SerialIoDevice == PchSerialIoIndexI2C4) ||
+ (SerialIoDevice == PchSerialIoIndexI2C5)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ (UINT16)SerialIoPsfReg[SerialIoDevice] + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ This procedure will reveal SerialIo device PciCfgSpace at PSF level
+
+ @param[in] SerialIoDevice SERIAL IO device (I2C0-5, SPI0-1, UART0-2)
+
+ @retval None
+**/
+VOID
+PsfRevealSerialIoDevice (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice
+ )
+{
+ UINT32 *SerialIoPsfReg;
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPsfReg = mPchLpSerialIoPsfRegs;
+ } else {
+ SerialIoPsfReg = mPchHSerialIoPsfRegs;
+ if ((SerialIoDevice == PchSerialIoIndexI2C4) ||
+ (SerialIoDevice == PchSerialIoIndexI2C5)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ (UINT16)SerialIoPsfReg[SerialIoDevice] + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS),
+ 0
+ );
+}
+
+/**
+ This procedure will set BARx value for TraceHub ACPI device at PSF level
+
+ @param[in] BarNum BAR Number (0:BAR0, 1:BAR1)
+ @param[in] BarValue 32bit BAR value
+
+ @retval None
+**/
+VOID
+PsfSetTraceHubAcpiDeviceBarValue (
+ IN UINT8 BarNum,
+ IN UINT32 BarValue
+ )
+{
+ UINT16 RegOffset;
+
+ if (BarNum > 1) {
+ ASSERT (FALSE);
+ }
+
+ RegOffset = R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_ACPI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_BAR0 + BarNum * 0x4;
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ RegOffset,
+ 0x0,
+ BarValue
+ );
+}
+
+/**
+ This procedure will enable MSE for TraceHub ACPI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfEnableTraceHubAcpiDeviceMemorySpace (
+ VOID
+ )
+{
+ PchPcrAndThenOr8 (
+ PID_PSF3, R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_ACPI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ 0xFF,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_MEMEN
+ );
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpHeciPsfRegBase[] =
+{
+ R_PCH_LP_PCR_PSF1_T0_SHDW_HECI1_REG_BASE,
+ R_PCH_LP_PCR_PSF1_T0_SHDW_HECI2_REG_BASE,
+ R_PCH_LP_PCR_PSF1_T0_SHDW_HECI3_REG_BASE
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchHHeciPsfRegBase[] =
+{
+ R_PCH_H_PCR_PSF1_T0_SHDW_HECI1_REG_BASE,
+ R_PCH_H_PCR_PSF1_T0_SHDW_HECI2_REG_BASE,
+ R_PCH_H_PCR_PSF1_T0_SHDW_HECI3_REG_BASE
+};
+
+/**
+ Enable HECI device at PSF level
+
+ @param[in] HeciDevice HECIx Device (HECI1-3)
+
+ @retval None
+**/
+VOID
+PsfEnableHeciDevice (
+ IN UINT8 HeciDevice
+ )
+{
+ UINT16 *DevPsfBase;
+
+ if ((HeciDevice < 1) || (HeciDevice > 3)) {
+ ASSERT (FALSE);
+ }
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = mPchLpHeciPsfRegBase;
+ } else {
+ DevPsfBase = mPchHHeciPsfRegBase;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase[HeciDevice - 1] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS),
+ 0
+ );
+}
+
+/**
+ Disable HECI device at PSF level
+
+ @param[in] HeciDevice HECIx Device (HECI1-3)
+
+ @retval None
+**/
+VOID
+PsfDisableHeciDevice (
+ IN UINT8 HeciDevice
+ )
+{
+ UINT16 *DevPsfBase;
+
+ if ((HeciDevice < 1) || (HeciDevice > 3)) {
+ ASSERT (FALSE);
+ }
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = mPchLpHeciPsfRegBase;
+ } else {
+ DevPsfBase = mPchHHeciPsfRegBase;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase[HeciDevice - 1] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Enable IDER device at PSF level
+
+ @retval None
+**/
+VOID
+PsfEnableIderDevice (
+ VOID
+ )
+{
+ UINT16 DevPsfBase;
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = R_PCH_LP_PCR_PSF1_T0_SHDW_IDER_REG_BASE;
+ } else {
+ DevPsfBase = R_PCH_H_PCR_PSF1_T0_SHDW_IDER_REG_BASE;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS),
+ 0
+ );
+}
+
+/**
+ Disable IDER device at PSF level
+
+ @retval None
+**/
+VOID
+PsfDisableIderDevice (
+ VOID
+ )
+{
+ UINT16 DevPsfBase;
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = R_PCH_LP_PCR_PSF1_T0_SHDW_IDER_REG_BASE;
+ } else {
+ DevPsfBase = R_PCH_H_PCR_PSF1_T0_SHDW_IDER_REG_BASE;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Enable SOL device at PSF level
+
+ @retval None
+**/
+VOID
+PsfEnableSolDevice (
+ VOID
+ )
+{
+ UINT16 DevPsfBase;
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = R_PCH_LP_PCR_PSF1_T0_SHDW_KT_REG_BASE;
+ } else {
+ DevPsfBase = R_PCH_H_PCR_PSF1_T0_SHDW_KT_REG_BASE;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS),
+ 0
+ );
+}
+
+/**
+ Disable SOL device at PSF level
+
+ @retval None
+**/
+VOID
+PsfDisableSolDevice (
+ VOID
+ )
+{
+ UINT16 DevPsfBase;
+
+ if (GetPchSeries () == PchLp) {
+ DevPsfBase = R_PCH_LP_PCR_PSF1_T0_SHDW_KT_REG_BASE;
+ } else {
+ DevPsfBase = R_PCH_H_PCR_PSF1_T0_SHDW_KT_REG_BASE;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, DevPsfBase + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PeiDxeSmmPchPsfLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PeiDxeSmmPchPsfLib.inf
new file mode 100644
index 0000000000..941f5a72dd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPsfLib/PeiDxeSmmPchPsfLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Component description file for the PeiDxeSmmPchPsfLib
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchPsfLib
+FILE_GUID = 36FE3C65-8367-46B9-9388-819C4933B899
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPsfLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PchInfoLib
+ PchPcrLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ PchPsfLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c
new file mode 100644
index 0000000000..9434b7f236
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c
@@ -0,0 +1,385 @@
+/** @file
+ PCH SBI access library.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchSbiAccessLib.h>
+
+/**
+ Execute PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+**/
+EFI_STATUS
+EFIAPI
+PchSbiExecution (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ )
+{
+ //
+ // Check address valid
+ //
+ if (((UINT32) Offset & 0x3) != 0) {
+ //
+ // Warning message for the address not DWORD alignment.
+ //
+ DEBUG ((DEBUG_INFO, "PchSbiExecution: Be careful that the address is not DWORD alignment.\n"));
+ }
+
+ return PchSbiExecutionEx ( Pid,
+ Offset,
+ Opcode,
+ Posted,
+ 0x000F,
+ 0x0000,
+ 0x0000,
+ Data32,
+ Response
+ );
+}
+
+/**
+ Full function for executing PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in] Fbe First byte enable
+ @param[in] Bar Bar
+ @param[in] Fid Function ID
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+**/
+EFI_STATUS
+EFIAPI
+PchSbiExecutionEx (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN UINT16 Fbe,
+ IN UINT16 Bar,
+ IN UINT16 Fid,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ )
+{
+ EFI_STATUS Status;
+ UINTN P2sbBase;
+ BOOLEAN P2sbOrgStatus;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ //
+ // Check opcode valid
+ //
+ switch (Opcode) {
+ case PciConfigRead:
+ case PciConfigWrite:
+ case PrivateControlRead:
+ case PrivateControlWrite:
+ case GpioLockUnlock:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ P2sbOrgStatus = FALSE;
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ PchRevealP2sb (P2sbBase, &P2sbOrgStatus);
+ ///
+ /// BWG Section 2.2.1
+ /// 1. Poll P2SB PCI offset D8h[0] = 0b
+ /// Make sure the previous opeartion is completed.
+ ///
+ Timeout = 0xFFFFFFF;
+ while (Timeout > 0) {
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ Timeout--;
+ }
+ if (Timeout == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto ExitPchSbiExecutionEx;
+ }
+ //
+ // Initial Response status
+ //
+ *Response = SBI_INVALID_RESPONSE;
+ Status = EFI_SUCCESS;
+ SbiStat = 0;
+ ///
+ /// 2. Write P2SB PCI offset D0h[31:0] with Address and Destination Port ID
+ ///
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIADDR, (UINT32) ((Pid << 24) | (UINT16) Offset));
+ ///
+ /// 3. Write P2SB PCI offset DCh[31:0] with extended address, which is expected to be 0 in SKL PCH.
+ ///
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR, (UINT32) RShiftU64 (Offset, 16));
+ ///
+ /// 5. Set P2SB PCI offset D8h[15:8] = 00000110b for read
+ /// Set P2SB PCI offset D8h[15:8] = 00000111b for write
+ //
+ // Set SBISTAT[15:8] to the opcode passed in
+ // Set SBISTAT[7] to the posted passed in
+ //
+ MmioAndThenOr16 (
+ (P2sbBase + R_PCH_P2SB_SBISTAT),
+ (UINT16) ~(B_PCH_P2SB_SBISTAT_OPCODE | B_PCH_P2SB_SBISTAT_POSTED),
+ (UINT16) ((Opcode << 8) | (Posted << 7))
+ );
+ ///
+ /// 6. Write P2SB PCI offset DAh[15:0] = F000h
+ ///
+ //
+ // Set RID[15:0] = Fbe << 12 | Bar << 8 | Fid
+ //
+ MmioWrite16 (
+ (P2sbBase + R_PCH_P2SB_SBIRID),
+ (((Fbe & 0x000F) << 12) | ((Bar & 0x0007) << 8) | (Fid & 0x00FF))
+ );
+
+ switch (Opcode) {
+ case PciConfigWrite:
+ case PrivateControlWrite:
+ case GpioLockUnlock:
+ ///
+ /// 4. Write P2SB PCI offset D4h[31:0] with the intended data accordingly
+ ///
+ MmioWrite32 ((P2sbBase + R_PCH_P2SB_SBIDATA), *Data32);
+ break;
+ default:
+ ///
+ /// 4. Write P2SB PCI offset D4h[31:0] with dummy data such as 0,
+ /// because all D0-DFh register range must be touched in SKL PCH
+ /// for a successful SBI transaction.
+ ///
+ MmioWrite32 ((P2sbBase + R_PCH_P2SB_SBIDATA), 0);
+ break;
+ }
+ ///
+ /// 7. Set P2SB PCI offset D8h[0] = 1b, Poll P2SB PCI offset D8h[0] = 0b
+ ///
+ //
+ // Set SBISTAT[0] = 1b, trigger the SBI operation
+ //
+ MmioOr16 (P2sbBase + R_PCH_P2SB_SBISTAT, (UINT16) B_PCH_P2SB_SBISTAT_INITRDY);
+ //
+ // Poll SBISTAT[0] = 0b, Polling for Busy bit
+ //
+ Timeout = 0xFFFFFFF;
+ while (Timeout > 0) {
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ Timeout--;
+ }
+ if (Timeout == 0) {
+ //
+ // If timeout, it's fatal error.
+ //
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ ///
+ /// 8. Check if P2SB PCI offset D8h[2:1] = 00b for successful transaction
+ ///
+ *Response = (UINT8) ((SbiStat & B_PCH_P2SB_SBISTAT_RESPONSE) >> N_PCH_P2SB_SBISTAT_RESPONSE);
+ if (*Response == SBI_SUCCESSFUL) {
+ switch (Opcode) {
+ case PciConfigRead:
+ case PrivateControlRead:
+ ///
+ /// 9. Read P2SB PCI offset D4h[31:0] for SBI data
+ ///
+ *Data32 = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIDATA);
+ break;
+ default:
+ break;
+ }
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+ExitPchSbiExecutionEx:
+ if (!P2sbOrgStatus) {
+ PchHideP2sb (P2sbBase);
+ }
+ return Status;
+}
+
+/**
+ This function saves all PCH SBI registers.
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in, out] PchSbiRegister Structure for saving the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterSave (
+ IN OUT PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ )
+{
+ UINTN P2sbBase;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ if (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Make sure it's not busy.
+ // Poll SBISTAT[0] = 0b
+ //
+ Timeout = 0xFFFFFFF;
+ while ((Timeout--) > 0) {
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ }
+ if (Timeout == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Save original SBI registers
+ //
+ PchSbiRegister->SbiAddr = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIADDR);
+ PchSbiRegister->SbiExtAddr = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR);
+ PchSbiRegister->SbiData = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIDATA);
+ PchSbiRegister->SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ PchSbiRegister->SbiRid = MmioRead16 (P2sbBase + R_PCH_P2SB_SBIRID);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function restores all PCH SBI registers
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in] PchSbiRegister Structure for restoring the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterRestore (
+ IN PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ )
+{
+ UINTN P2sbBase;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ if (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Make sure it's not busy.
+ // Poll SBISTAT[0] = 0b
+ //
+ Timeout = 0xFFFFFFF;
+ while ((Timeout--) > 0) {
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ }
+ if (Timeout == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Restore original SBI registers
+ //
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIADDR , PchSbiRegister->SbiAddr);
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR, PchSbiRegister->SbiExtAddr);
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIDATA , PchSbiRegister->SbiData);
+ MmioWrite16 (P2sbBase + R_PCH_P2SB_SBISTAT , PchSbiRegister->SbiStat);
+ MmioWrite16 (P2sbBase + R_PCH_P2SB_SBIRID , PchSbiRegister->SbiRid);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
new file mode 100644
index 0000000000..38ca8dce0e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
@@ -0,0 +1,43 @@
+## @file
+# PCH SBI access library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchSbiAccessLib
+FILE_GUID = 96ECB0FB-A975-4DC8-B88A-D90C3378CE87
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchSbiAccessLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchP2sbLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchSbiAccessLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c
new file mode 100644
index 0000000000..7d24ed1269
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c
@@ -0,0 +1,527 @@
+/** @file
+ PCH Serial IO Lib implementation.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/PchPsfLib.h>
+#include <Include/PcieRegs.h>
+
+typedef struct {
+ UINT32 Bar0;
+ UINT32 Bar1;
+} SERIAL_IO_CONTROLLER_DESCRIPTOR;
+
+typedef struct {
+ UINT8 DevNum;
+ UINT8 FuncNum;
+} SERIAL_IO_BDF_NUMBERS;
+
+typedef struct {
+ UINT16 PciDevIdPchLp;
+ UINT16 PciDevIdSklPchH;
+ UINT16 PciDevIdKblPchH;
+ CHAR8 AcpiHid[SERIALIO_HID_LENGTH];
+} SERIAL_IO_ID;
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_ID mSerialIoId [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ {V_PCH_LP_SERIAL_IO_I2C0_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C0_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C0_DEVICE_ID, "INT3442"},
+ {V_PCH_LP_SERIAL_IO_I2C1_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C1_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C1_DEVICE_ID, "INT3443"},
+ {V_PCH_LP_SERIAL_IO_I2C2_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C2_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C2_DEVICE_ID, "INT3444"},
+ {V_PCH_LP_SERIAL_IO_I2C3_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_I2C3_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_I2C3_DEVICE_ID, "INT3445"},
+ {V_PCH_LP_SERIAL_IO_I2C4_DEVICE_ID, 0 , 0 , "INT3446"},
+ {V_PCH_LP_SERIAL_IO_I2C5_DEVICE_ID, 0 , 0 , "INT3447"},
+ {V_PCH_LP_SERIAL_IO_SPI0_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_SPI0_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_SPI0_DEVICE_ID, "INT3440"},
+ {V_PCH_LP_SERIAL_IO_SPI1_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_SPI1_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_SPI1_DEVICE_ID, "INT3441"},
+ {V_PCH_LP_SERIAL_IO_UART0_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_UART0_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_UART0_DEVICE_ID, "INT3448"},
+ {V_PCH_LP_SERIAL_IO_UART1_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_UART1_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_UART1_DEVICE_ID, "INT3449"},
+ {V_PCH_LP_SERIAL_IO_UART2_DEVICE_ID, V_SKL_PCH_H_SERIAL_IO_UART2_DEVICE_ID, V_KBL_PCH_H_SERIAL_IO_UART2_DEVICE_ID, "INT344A"}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_BDF_NUMBERS mSerialIoBdf [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C0},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C1},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C2, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C2},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C3, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C3},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C4, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C4},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C5, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C5},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI0},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI1},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART0, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART0},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART1, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART1},
+ {PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART2, PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART2}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_CONTROLLER_DESCRIPTOR mSerialIoAcpiAddress [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x0000, PCH_SERIAL_IO_BASE_ADDRESS + 0x1000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x2000, PCH_SERIAL_IO_BASE_ADDRESS + 0x3000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x4000, PCH_SERIAL_IO_BASE_ADDRESS + 0x5000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x6000, PCH_SERIAL_IO_BASE_ADDRESS + 0x7000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x8000, PCH_SERIAL_IO_BASE_ADDRESS + 0x9000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xA000, PCH_SERIAL_IO_BASE_ADDRESS + 0xB000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xC000, PCH_SERIAL_IO_BASE_ADDRESS + 0xD000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xE000, PCH_SERIAL_IO_BASE_ADDRESS + 0xF000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x10000, PCH_SERIAL_IO_BASE_ADDRESS + 0x11000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x12000, PCH_SERIAL_IO_BASE_ADDRESS + 0x13000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x14000, PCH_SERIAL_IO_BASE_ADDRESS + 0x15000}
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoPciCfgCtrAddr [PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL1,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL2,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL3,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL4,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL5,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL6,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL13,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL14,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL9,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL10,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL11
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchHSerialIoPciCfgCtrAddr[PCH_SERIALIO_MAX_CONTROLLERS] =
+{
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL1,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL2,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL3,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL4,
+ 0,
+ 0,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL13,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL14,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL9,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL10,
+ R_PCH_PCR_SERIAL_IO_PCICFGCTRL11
+};
+
+
+/**
+ Returns index of the last i2c controller
+
+ @param[in] Number Number of SerialIo controller
+
+ @retval Index of I2C controller
+**/
+PCH_SERIAL_IO_CONTROLLER
+GetMaxI2cNumber (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchH) {
+ return PchSerialIoIndexI2C3;
+ } else {
+ return PchSerialIoIndexI2C5;
+ }
+}
+
+/**
+ Returns string with AcpiHid assigned to selected SerialIo controller
+
+ @param[in] Number Number of SerialIo controller
+
+ @retval pointer to 8-byte string
+**/
+CHAR8*
+GetSerialIoAcpiHID (
+ IN PCH_SERIAL_IO_CONTROLLER Number
+ )
+{
+ return mSerialIoId[Number].AcpiHid;
+}
+
+/**
+ Checks if Device with given PciDeviceId is one of SerialIo controllers
+ If yes, its number is returned through Number parameter, otherwise Number is not updated
+
+ @param[in] PciDevId Device ID
+ @param[out] Number Number of SerialIo controller
+
+ @retval TRUE Yes it is a SerialIo controller
+ @retval FALSE No it isn't a SerialIo controller
+**/
+BOOLEAN
+IsSerialIoPciDevId (
+ IN UINT16 PciDevId,
+ OUT PCH_SERIAL_IO_CONTROLLER *Number
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER Controller;
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGen;
+
+ PchSeries = GetPchSeries ();
+ PchGen = GetPchGeneration ();
+ for (Controller = 0; Controller < PCH_SERIALIO_MAX_CONTROLLERS; Controller++) {
+ if (((PchSeries == PchLp) && (PciDevId == mSerialIoId[Controller].PciDevIdPchLp)) ||
+ ((PchSeries == PchH) && (PchGen == SklPch) && (PciDevId == mSerialIoId[Controller].PciDevIdSklPchH)) ||
+ ((PchSeries == PchH) && (PchGen == KblPch) && (PciDevId == mSerialIoId[Controller].PciDevIdKblPchH))) {
+ *Number = Controller;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Checks if Device with given AcpiHid string is one of SerialIo controllers
+ If yes, its number is returned through Number parameter, otherwise Number is not updated
+
+ @param[in] AcpiHid String
+ @param[out] Number Number of SerialIo controller
+
+ @retval TRUE yes it is a SerialIo controller
+ @retval FALSE no it isn't a SerialIo controller
+**/
+BOOLEAN
+IsSerialIoAcpiHid (
+ IN CHAR8 *AcpiHid,
+ OUT PCH_SERIAL_IO_CONTROLLER *Number
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER Controller;
+ for (Controller = 0; Controller < PCH_SERIALIO_MAX_CONTROLLERS; Controller++) {
+ if (!AsciiStrCmp ((const CHAR8 *) AcpiHid, mSerialIoId[Controller].AcpiHid)) {
+ *Number = Controller;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Finds PCI Device Number of SerialIo devices.
+
+ @param[in] SerialIoNumber 0=I2C0, ..., 11=UART2
+
+ @retval SerialIo device number
+**/
+UINT8
+GetSerialIoDeviceNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ )
+{
+ return mSerialIoBdf[SerialIoNumber].DevNum;
+}
+
+/**
+ Finds PCI Function Number of SerialIo devices.
+
+ @param[in] SerialIoNumber 0=I2C0, ..., 11=UART2
+
+ @retval SerialIo funciton number
+**/
+UINT8
+GetSerialIoFunctionNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ )
+{
+ return mSerialIoBdf[SerialIoNumber].FuncNum;
+}
+
+/**
+ Finds BAR values of SerialIo devices.
+ SerialIo devices can be configured to not appear on PCI so traditional method of reading BAR might not work.
+ If the SerialIo device is in PCI mode, a request for BAR1 will return its PCI CFG space instead
+
+ @param[in] SerialIoDevice 0=I2C0, ..., 11=UART2
+ @param[in] BarNumber 0=BAR0, 1=BAR1
+
+ @retval SerialIo Bar value
+**/
+UINTN
+FindSerialIoBar (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice,
+ IN UINT8 BarNumber
+ )
+{
+ UINT64 Bar;
+ UINTN PcieBase;
+ UINT32 VenId;
+
+ PcieBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, GetSerialIoDeviceNumber (SerialIoDevice), GetSerialIoFunctionNumber (SerialIoDevice));
+ VenId = MmioRead32 (PcieBase + PCI_VENDOR_ID_OFFSET) & 0xFFFF;
+ if (VenId == V_PCH_INTEL_VENDOR_ID) {
+ if (BarNumber == 1) {
+ return PcieBase;
+ }
+ Bar = MmioRead32 (PcieBase + PCI_BASE_ADDRESSREG_OFFSET);
+ //
+ // For 64-Bit Memory Space BARs ((BAR[x] & 0xFFFFFFF0) + ((BAR[x+1] & 0xFFFFFFFF) << 32)
+ //
+ if ((Bar & B_PCI_BAR_MEMORY_TYPE_MASK) == B_PCI_BAR_MEMORY_TYPE_64) {
+ Bar = (Bar & 0xFFFFF000) + LShiftU64 (MmioRead32 (PcieBase + PCI_BASE_ADDRESSREG_OFFSET + 4) & 0xFFFFFFFF, 32);
+ return (UINTN) Bar;
+ }
+ return (UINTN) (Bar & 0xFFFFF000);
+ }
+ //
+ //PCI mode failed? Try hardcoded addresses from ACPI
+ //
+ if (BarNumber == 0) {
+ Bar = mSerialIoAcpiAddress[SerialIoDevice].Bar0;
+ } else {
+ Bar = mSerialIoAcpiAddress[SerialIoDevice].Bar1;
+ }
+ return (UINTN) Bar;
+}
+
+/**
+ Configures Serial IO Controller
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+**/
+VOID
+ConfigureSerialIoController (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode
+ )
+{
+ UINTN PciCfgBase;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT16 *SerialIoPciCfgCtrAddr;
+
+ if (Controller >= PchSerialIoIndexMax) {
+ return;
+ }
+
+ if (DeviceMode == PchSerialIoSkipInit) {
+ return;
+ }
+
+ PciCfgBase = MmPciBase (0, GetSerialIoDeviceNumber (Controller), GetSerialIoFunctionNumber (Controller));
+ //
+ // Do not modify a device that has already been disabled/hidden
+ //
+ if (MmioRead16 (PciCfgBase + PCI_VENDOR_ID_OFFSET) != V_PCH_INTEL_VENDOR_ID) {
+ return;
+ }
+
+ ///
+ /// Step 0. set Bit 16,17,18.
+ ///
+ MmioOr32 (PciCfgBase + R_PCH_SERIAL_IO_D0I3MAXDEVPG, BIT18 | BIT17 | BIT16);
+
+ //
+ // special case for I2C4 and I2C5 on SPT-H
+ //
+ if (GetPchSeries () == PchH && (Controller == PchSerialIoIndexI2C4 || Controller == PchSerialIoIndexI2C5)) {
+ return;
+ }
+
+ if (GetPchSeries () == PchLp) {
+ SerialIoPciCfgCtrAddr = mPchLpSerialIoPciCfgCtrAddr;
+ } else {
+ SerialIoPciCfgCtrAddr = mPchHSerialIoPciCfgCtrAddr;
+ }
+
+ switch (DeviceMode) {
+ case PchSerialIoDisabled:
+ ///
+ /// Step 1. Put device in D3
+ /// Step 2. Function Disable in PSF
+ ///
+ MmioOr32 (PciCfgBase + R_PCH_SERIAL_IO_PME_CTRL_STS, BIT1 | BIT0);
+ PsfDisableSerialIoDevice (Controller);
+ break;
+
+ case PchSerialIoAcpi:
+ case PchSerialIoAcpiHidden:
+ case PchSerialIoLegacyUart:
+ ///
+ /// reenable BAR1 in case it was disabled earlier
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller],(UINT32) ~(B_PCH_PCR_SERIAL_IO_PCICFGCTRL_BAR1_DIS),0x0);
+ PsfEnableSerialIoDeviceBar1 (Controller);
+ ///
+ /// Step 1. Assign BAR0
+ /// Step 2. Assign BAR1
+ ///
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_LOW, mSerialIoAcpiAddress[Controller].Bar0);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_HIGH, 0x0);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR1_LOW, mSerialIoAcpiAddress[Controller].Bar1);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR1_HIGH, 0x0);
+ ///
+ /// Step 3. Set Memory space Enable
+ ///
+ MmioOr32 (PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ ///
+ /// Step 4. Disable device's PciCfg and enable ACPI interrupts
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller], 0xFFFFFFFF, (B_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_CFG_DIS | B_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_INTR_EN));
+ ///
+ /// Step 5. Disable device's PciCfg in PSF
+ ///
+ PsfHideSerialIoDevice (Controller);
+ ///
+ /// get controller out of reset
+ ///
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA);
+ break;
+ case PchSerialIoPci:
+ ///
+ /// reenable PciCfg in case it was disabled earlier
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller], (UINT32) ~(B_PCH_PCR_SERIAL_IO_PCICFGCTRL_PCI_CFG_DIS | B_PCH_PCR_SERIAL_IO_PCICFGCTRL_ACPI_INTR_EN),0x0);
+ PsfRevealSerialIoDevice (Controller);
+ ///
+ /// Disable Bar1
+ /// Disable Bar1 in PSF
+ ///
+ PchPcrAndThenOr32 (PID_SERIALIO, SerialIoPciCfgCtrAddr[Controller], 0xFFFFFFFF, B_PCH_PCR_SERIAL_IO_PCICFGCTRL_BAR1_DIS);
+ PsfDisableSerialIoDeviceBar1 (Controller);
+ //
+ // Assign BAR0 and Set Memory space Enable
+ //
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_LOW, mSerialIoAcpiAddress[Controller].Bar0);
+ MmioWrite32 (PciCfgBase + R_PCH_SERIAL_IO_BAR0_HIGH, 0x0);
+ MmioOr32 (PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ ///
+ /// get controller out of reset
+ ///
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA);
+ break;
+ default:
+ return;
+ }
+
+ ///
+ /// Step X. Program clock dividers for UARTs
+ /// Step Y. Enable Byte addressing for UARTs in legacy mode
+ ///
+ if (Controller >= PchSerialIoIndexUart0 && Controller <= PchSerialIoIndexUart2) {
+ MmioWrite32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_CLK,
+ (B_PCH_SERIAL_IO_PPR_CLK_UPDATE | (V_PCH_SERIAL_IO_PPR_CLK_N_DIV << 16) |
+ (V_PCH_SERIAL_IO_PPR_CLK_M_DIV << 1) | B_PCH_SERIAL_IO_PPR_CLK_EN )
+ );
+
+ Data32And = (UINT32) (~(B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART0_BYTE_ADDR_EN << (Controller - PchSerialIoIndexUart0)));
+ Data32Or = 0x0;
+ if (DeviceMode == PchSerialIoLegacyUart) {
+ Data32Or = (B_PCH_PCR_SERIAL_IO_GPPRVRW7_UART0_BYTE_ADDR_EN << (Controller - PchSerialIoIndexUart0));
+ }
+ PchPcrAndThenOr32 (PID_SERIALIO, R_PCH_PCR_SERIAL_IO_GPPRVRW7,Data32And,Data32Or);
+ //
+ // Dummy read after setting any of GPPRVRW7.
+ // Required for UART 16550 8-bit Legacy mode to become active
+ //
+ MmioRead32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_PPR_CLK);
+ }
+ ///
+ /// Step Z. Program I2C SDA hold registers
+ ///
+ if (Controller >= PchSerialIoIndexI2C0 && Controller <= GetMaxI2cNumber ()) {
+ if (DeviceMode != PchSerialIoDisabled) {
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_I2C_SDA_HOLD, V_PCH_SERIAL_IO_I2C_SDA_HOLD_VALUE);
+ }
+ }
+
+}
+
+/**
+ Initializes GPIO pins used by SerialIo I2C devices
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+ @param[in] I2cVoltage Voltage selector
+**/
+VOID
+SerialIoI2cGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN UINT32 I2cVoltage
+ )
+{
+ if ((DeviceMode == PchSerialIoDisabled) || (DeviceMode == PchSerialIoSkipInit)) {
+ return;
+ }
+ GpioSetSerialIoI2cPinsIntoNativeMode (Controller);
+ if (I2cVoltage == PchSerialIoIs18V) {
+ GpioSetSerialIoI2CPinsTolerance (Controller, TRUE);
+ }
+}
+
+/**
+ Initializes GPIO pins used by SerialIo SPI devices
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+ @param[in] SpiCsPolarity Polarity selector
+**/
+VOID
+SerialIoSpiGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN UINT32 SpiCsPolarity
+ )
+{
+ if ((DeviceMode == PchSerialIoDisabled) || (DeviceMode == PchSerialIoSkipInit)) {
+ return;
+ }
+
+ //
+ // set Invert Frame Signal before enabling pins to ensure correct initial ChipSelect polarity
+ //
+ if (SpiCsPolarity == PchSerialIoCsActiveLow) {
+ MmioAnd32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SSCR1, (UINT32) ~(B_PCH_SERIAL_IO_SSCR1_IFS));
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SPI_CS_CONTROL, B_PCH_SERIAL_IO_SPI_CS_CONTROL_STATE);
+ } else {
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SSCR1, B_PCH_SERIAL_IO_SSCR1_IFS);
+ MmioAnd32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SPI_CS_CONTROL, (UINT32) ~B_PCH_SERIAL_IO_SPI_CS_CONTROL_STATE);
+ }
+
+ MmioOr32 (mSerialIoAcpiAddress[Controller].Bar0 + R_PCH_SERIAL_IO_SPI_CS_CONTROL, B_PCH_SERIAL_IO_SPI_CS_CONTROL_MODE);
+ GpioSetSerialIoSpiPinsIntoNativeMode (Controller-PchSerialIoIndexSpi0);
+}
+
+/**
+ Initializes GPIO pins used by SerialIo devices
+
+ @param[in] Controller Serial Io controller selector
+ @param[in] DeviceMode Device mode selector
+ @param[in] HardwareFlowControl Hardware flow control selector
+**/
+VOID
+SerialIoUartGpioInit (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode,
+ IN BOOLEAN HardwareFlowControl
+ )
+{
+
+ if ((DeviceMode == PchSerialIoDisabled) || (DeviceMode == PchSerialIoSkipInit)) {
+ return;
+ }
+ GpioSetSerialIoUartPinsIntoNativeMode (Controller-PchSerialIoIndexUart0, HardwareFlowControl);
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf
new file mode 100644
index 0000000000..28ee07ee15
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf
@@ -0,0 +1,45 @@
+## @file
+# Component description file for PEI/DXE/SMM PCH Serial IO Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchSerialIoLib
+FILE_GUID = 613A22A2-5736-40f8-909B-DF10EA389C72
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchSerialIoLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+GpioLib
+PchPcrLib
+PchPsfLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiDxeSmmPchSerialIoLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf
new file mode 100644
index 0000000000..723ad14ced
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/PeiDxeSmmPchWdtCommonLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the PchWdtCommonLib
+#
+# Copyright (c) 2017, 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 = PeiDxeSmmPchWdtCommonLib
+ FILE_GUID = 171F78D2-0A52-4692-8830-AB693791EA23
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchWdtCommonLib
+
+[Sources]
+ WdtCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PchCycleDecodingLib
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c
new file mode 100644
index 0000000000..00a2fef78d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchWdtCommonLib/WdtCommon.c
@@ -0,0 +1,225 @@
+/** @file
+ Library that contains common parts of WdtPei and WdtDxe. Not a standalone module.
+
+Copyright (c) 2017, 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 that 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 <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/MmPciLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mAllowExpectedReset = 0;
+
+/**
+ Reads LPC bridge to get Watchdog Timer address
+
+
+ @retval UINT32 Watchdog's address
+**/
+UINT32
+WdtGetAddress (
+ VOID
+ )
+{
+ UINT32 Address;
+ UINT16 ABase;
+
+ PchAcpiBaseGet (&ABase);
+ Address = ABase + R_PCH_OC_WDT_CTL;
+
+ return Address;
+}
+
+/**
+ Reloads WDT with new timeout value and starts it. Also sets Unexpected Reset bit, which
+ causes the next reset to be treated as watchdog expiration - unless AllowKnownReset()
+ function was called too.
+
+ @param[in] TimeoutValue Time in seconds before WDT times out. Supported range = 1 - 1024.
+
+ @retval EFI_SUCCESS if everything's OK
+ @retval EFI_INVALID_PARAMETER if TimeoutValue parameter is wrong
+**/
+EFI_STATUS
+EFIAPI
+WdtReloadAndStart (
+ IN UINT32 TimeoutValue
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "\n(Wdt) ReloadAndStartTimer(%d)\n", TimeoutValue));
+
+ if ((TimeoutValue > B_PCH_OC_WDT_CTL_TOV_MASK) || (TimeoutValue == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Readback = IoRead32 (WdtGetAddress ());
+ Readback |= (B_PCH_OC_WDT_CTL_EN | B_PCH_OC_WDT_CTL_FORCE_ALL | B_PCH_OC_WDT_CTL_ICCSURV);
+ if (mAllowExpectedReset == 0) {
+ Readback |= B_PCH_OC_WDT_CTL_UNXP_RESET_STS;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ ///
+ /// In Debug mode, WDT will not be turned on. This is to prevent platform reboots triggered
+ /// by WDT expiration, which can be expected when processor is halted for debugging
+ ///
+ Readback &= ~(B_PCH_OC_WDT_CTL_EN | B_PCH_OC_WDT_CTL_FORCE_ALL | B_PCH_OC_WDT_CTL_UNXP_RESET_STS);
+ DEBUG ((DEBUG_INFO, "(Wdt) Wdt disabled in Debug BIOS\n"));
+ DEBUG_CODE_END ();
+
+ Readback &= ~(B_PCH_OC_WDT_CTL_TOV_MASK);
+ Readback |= ((TimeoutValue - 1) & B_PCH_OC_WDT_CTL_TOV_MASK);
+ IoWrite32 (WdtGetAddress (), Readback);
+ Readback |= B_PCH_OC_WDT_CTL_RLD;
+ IoWrite32 (WdtGetAddress (), Readback);
+ return EFI_SUCCESS;
+}
+
+/**
+ Disables WDT timer.
+
+
+**/
+VOID
+EFIAPI
+WdtDisable (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "(Wdt) DisableTimer\n"));
+
+ Readback = IoRead32 (WdtGetAddress ());
+ Readback &= ~(B_PCH_OC_WDT_CTL_EN | B_PCH_OC_WDT_CTL_FORCE_ALL | B_PCH_OC_WDT_CTL_UNXP_RESET_STS);
+ IoWrite32 (WdtGetAddress (), Readback);
+}
+
+/**
+ Returns WDT failure status.
+
+
+ @retval V_PCH_OC_WDT_CTL_STATUS_FAILURE If there was WDT expiration or unexpected reset
+ @retval V_PCH_OC_WDT_CTL_STATUS_OK Otherwise
+**/
+UINT8
+EFIAPI
+WdtCheckStatus (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "(Wdt) CheckTimerStatus\n"));
+
+ Readback = IoRead32 (WdtGetAddress ());
+
+ DEBUG ((DEBUG_INFO, "(Wdt) Readback = (%x)\n", Readback));
+
+ if (Readback & B_PCH_OC_WDT_CTL_FAILURE_STS) {
+ DEBUG ((DEBUG_INFO, "(Wdt) Status = FAILURE\n"));
+ return V_PCH_OC_WDT_CTL_STATUS_FAILURE;
+ } else {
+ return V_PCH_OC_WDT_CTL_STATUS_OK;
+ }
+}
+
+/**
+ Normally, each reboot performed while watchdog runs is considered a failure.
+ This function allows platform to perform expected reboots with WDT running,
+ without being interpreted as failures.
+ In DXE phase, it is enough to call this function any time before reset.
+ In PEI phase, between calling this function and performing reset, ReloadAndStart()
+ must not be called.
+
+
+**/
+VOID
+EFIAPI
+WdtAllowKnownReset (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "(Wdt) AllowKnownReset\n"));
+
+ mAllowExpectedReset = 1;
+
+ Readback = IoRead32 (WdtGetAddress ());
+ Readback &= ~(B_PCH_OC_WDT_CTL_UNXP_RESET_STS | B_PCH_OC_WDT_CTL_FORCE_ALL);
+ IoWrite32 (WdtGetAddress (), Readback);
+}
+
+/**
+ Returns information if WDT coverage for the duration of BIOS execution
+ was requested by an OS application
+
+
+ @retval TRUE if WDT was requested
+ @retval FALSE if WDT was not requested
+**/
+UINT8
+EFIAPI
+IsWdtRequired (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "(Wdt) IsWdtRequired"));
+
+ Readback = IoRead32 (WdtGetAddress ());
+
+
+ if ((Readback & B_PCH_OC_WDT_CTL_AFTER_POST) != 0) {
+ DEBUG ((DEBUG_INFO, " - yes\n"));
+ return TRUE;
+ } else {
+ DEBUG ((DEBUG_INFO, " - no\n"));
+ return FALSE;
+ }
+
+}
+
+/**
+ Returns WDT enabled/disabled status.
+
+
+ @retval TRUE if WDT is enabled
+ @retval FALSE if WDT is disabled
+**/
+UINT8
+EFIAPI
+IsWdtEnabled (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ DEBUG ((DEBUG_INFO, "(Wdt) IsWdtEnabled"));
+
+ Readback = IoRead32 (WdtGetAddress ());
+
+
+ if ((Readback & B_PCH_OC_WDT_CTL_EN) != 0) {
+ DEBUG ((DEBUG_INFO, " - yes\n"));
+ return TRUE;
+ } else {
+ DEBUG ((DEBUG_INFO, " - no\n"));
+ return FALSE;
+ }
+
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c
new file mode 100644
index 0000000000..0996b02ea6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.c
@@ -0,0 +1,138 @@
+/** @file
+ The PEI Library Implements OcWdt Support.
+
+Copyright (c) 2017, 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 that 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 <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/Wdt.h>
+#include <Library/PchWdtCommonLib.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/IoLib.h>
+
+static WDT_PPI mWdtPpi = {
+ WdtReloadAndStart,
+ WdtCheckStatus,
+ WdtDisable,
+ WdtAllowKnownReset,
+ IsWdtRequired,
+ IsWdtEnabled
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mInstallWdtPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gWdtPpiGuid,
+ &mWdtPpi
+};
+
+/**
+ Reads PCH registers to check if platform wakes from S3/S4
+
+ @retval TRUE if platfrom wakes from S3/S4
+ @retval FALSE otherwise
+**/
+BOOLEAN
+IsWakeFromS3S4 (
+ VOID
+ )
+{
+ UINT16 ABase;
+ UINT16 SleepType;
+
+ PchAcpiBaseGet (&ABase);
+
+ if (IoRead16 (ABase + R_PCH_ACPI_PM1_STS) & B_PCH_ACPI_PM1_STS_WAK) {
+ SleepType = IoRead16 (ABase + R_PCH_ACPI_PM1_CNT) & B_PCH_ACPI_PM1_CNT_SLP_TYP;
+ if ((SleepType == V_PCH_ACPI_PM1_CNT_S3) || (SleepType == V_PCH_ACPI_PM1_CNT_S4)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Check for unexpected reset.
+ If there was an unexpected reset, enforces WDT expiration.
+**/
+VOID
+OcWdtResetCheck (
+ VOID
+ )
+{
+ UINT32 Readback;
+
+ Readback = IoRead32 (WdtGetAddress ());
+
+ DEBUG ((DEBUG_ERROR, "(WDT) OcWdtResetCheck\n"));
+
+ ///
+ /// If there was a WDT expiration, set Failure Status and clear timeout status bits
+ /// Timeout status bits are cleared by writing '1'
+ ///
+ if (Readback & (B_PCH_OC_WDT_CTL_ICCSURV_STS | B_PCH_OC_WDT_CTL_NO_ICCSURV_STS)) {
+ DEBUG ((DEBUG_ERROR, "(WDT) Expiration detected.\n", Readback));
+ Readback |= B_PCH_OC_WDT_CTL_FAILURE_STS;
+ Readback |= (B_PCH_OC_WDT_CTL_ICCSURV_STS | B_PCH_OC_WDT_CTL_NO_ICCSURV_STS);
+ Readback &= ~(B_PCH_OC_WDT_CTL_UNXP_RESET_STS);
+ } else {
+ ///
+ /// If there was unexpected reset but no WDT expiration and no resume from S3/S4,
+ /// clear unexpected reset status and enforce expiration. This is to inform Firmware
+ /// which has no access to unexpected reset status bit, that something went wrong.
+ ///
+ if ((Readback & B_PCH_OC_WDT_CTL_UNXP_RESET_STS) && !IsWakeFromS3S4 ()) {
+#ifndef MDEPKG_NDEBUG
+ DEBUG ((DEBUG_ERROR, "(WDT) Unexpected reset detected and ignored.\n"));
+ Readback &= ~(B_PCH_OC_WDT_CTL_FAILURE_STS | B_PCH_OC_WDT_CTL_UNXP_RESET_STS);
+ Readback |= (B_PCH_OC_WDT_CTL_ICCSURV_STS | B_PCH_OC_WDT_CTL_NO_ICCSURV_STS);
+#else
+ DEBUG ((DEBUG_ERROR, "(WDT) Unexpected reset detected. Enforcing Wdt expiration.\n"));
+ WdtReloadAndStart (1);
+ ///
+ /// wait for reboot caused by WDT expiration
+ ///
+ CpuDeadLoop ();
+#endif
+ } else {
+ ///
+ /// No WDT expiration and no unexpected reset - clear Failure status
+ ///
+ DEBUG ((DEBUG_INFO, "(WDT) Status OK.\n", Readback));
+ Readback &= ~(B_PCH_OC_WDT_CTL_FAILURE_STS);
+ Readback |= (B_PCH_OC_WDT_CTL_ICCSURV_STS | B_PCH_OC_WDT_CTL_NO_ICCSURV_STS);
+ }
+ }
+
+ IoWrite32 (WdtGetAddress (), Readback);
+}
+
+/**
+ This function install WDT PPI
+
+ @retval EFI_STATUS Results of the installation of the WDT PPI
+**/
+EFI_STATUS
+EFIAPI
+OcWdtInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesInstallPpi (&mInstallWdtPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf
new file mode 100644
index 0000000000..a2b8f71784
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLib/PeiOcWdtLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Component Description File for OcWdt Support.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiOcWdtLib
+FILE_GUID = D5207C23-3632-4078-A671-3B5C364B2BDB
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = OcWdtLib
+
+
+[LibraryClasses]
+IoLib
+DebugLib
+PeiServicesLib
+PchWdtCommonLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiOcWdtLib.c
+
+
+[Ppis]
+gWdtPpiGuid ## PRODUCES
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.c
new file mode 100644
index 0000000000..fdde6803c3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.c
@@ -0,0 +1,41 @@
+/** @file
+ The Null PEI Library Implements OcWdt Support.
+
+Copyright (c) 2017, 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 that 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 <Ppi/Wdt.h>
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Check for unexpected reset.
+ If there was an unexpected reset, enforces WDT expiration.
+**/
+VOID
+OcWdtResetCheck (
+ VOID
+ )
+{
+}
+
+/**
+ This function install WDT PPI
+
+ @retval EFI_STATUS Results of the installation of the WDT PPI
+**/
+EFI_STATUS
+EFIAPI
+OcWdtInit (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.inf
new file mode 100644
index 0000000000..93c951d49c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiOcWdtLibNull/PeiOcWdtLibNull.inf
@@ -0,0 +1,32 @@
+## @file
+# Component Description File for OcWdt Support.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiOcWdtLib
+FILE_GUID = DB65B36B-E276-4A2b-AB20-61764889E483
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = OcWdtLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiOcWdtLibNull.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPrintPolicy.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPrintPolicy.c
new file mode 100644
index 0000000000..650d414247
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPreMemPrintPolicy.c
@@ -0,0 +1,311 @@
+/** @file
+ Print whole PCH_PREMEM_POLICY_PPI
+
+Copyright (c) 2017, 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 that 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 "PeiPchPolicyLibrary.h"
+
+/**
+ Print PCH_GENERAL_PREMEM_CONFIG and serial out.
+
+ @param[in] PchGeneralPreMemConfig Pointer to a PCH_GENERAL_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintGeneralPreMemConfig (
+ IN CONST PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH General PreMem Config -----------\n"));
+ DEBUG ((DEBUG_INFO, " AcpiBase= %x\n", PchGeneralPreMemConfig->AcpiBase));
+ DEBUG ((DEBUG_INFO, " Port80Route= %x\n", PchGeneralPreMemConfig->Port80Route));
+}
+
+/**
+ Print PCH_DCI_PREMEM_CONFIG and serial out.
+
+ @param[in] DciPreMemConfig Pointer to a PCH_DCI_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintDciPreMemConfig (
+ IN CONST PCH_DCI_PREMEM_CONFIG *DciPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH DCI PreMem Config ---------------\n"));
+ DEBUG ((DEBUG_INFO, "DciEn= %x\n", DciPreMemConfig->DciEn));
+}
+
+/**
+ Print PCH_WDT_PREMEM_CONFIG and serial out.
+
+ @param[in] WdtPreMemConfig Pointer to a PCH_WDT_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintWdtPreMemConfig (
+ IN CONST PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH WDT PreMem Config ---------------\n"));
+ DEBUG ((DEBUG_INFO, "DisableAndLock= %x\n", WdtPreMemConfig->DisableAndLock));
+}
+
+/**
+ Print PCH_TRACE_HUB_CONFIG and serial out.
+
+ @param[in] TraceHubConfig Pointer to a PCH_TRACE_HUB_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintTraceHubPreMemConfig (
+ IN CONST PCH_TRACE_HUB_PREMEM_CONFIG *TraceHubPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH TraceHub PreMem Config ----------\n"));
+ DEBUG ((DEBUG_INFO, "EnableMode= %x\n", TraceHubPreMemConfig->EnableMode));
+ DEBUG ((DEBUG_INFO, "MemReg0Size= %x\n", TraceHubPreMemConfig->MemReg0Size));
+ DEBUG ((DEBUG_INFO, "MemReg1Size= %x\n", TraceHubPreMemConfig->MemReg1Size));
+}
+
+/**
+ Print PCH_HPET_PREMEM_CONFIG and serial out.
+
+ @param[in] HpetPreMemConfig Pointer to a PCH_HPET_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHpetPreMemConfig (
+ IN CONST PCH_HPET_PREMEM_CONFIG *HpetPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH HPET PreMem Config --------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable %x\n", HpetPreMemConfig->Enable));
+ DEBUG ((DEBUG_INFO, " BdfValid %x\n", HpetPreMemConfig->BdfValid));
+ DEBUG ((DEBUG_INFO, " BusNumber %x\n", HpetPreMemConfig->BusNumber));
+ DEBUG ((DEBUG_INFO, " DeviceNumber %x\n", HpetPreMemConfig->DeviceNumber));
+ DEBUG ((DEBUG_INFO, " FunctionNumber %x\n", HpetPreMemConfig->FunctionNumber));
+ DEBUG ((DEBUG_INFO, " Base %x\n", HpetPreMemConfig->Base));
+}
+
+/**
+ Print PCH_SMBUS_CONFIG and serial out.
+
+ @param[in] SmbusConfig Pointer to a PCH_SMBUS_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSmbusPreMemConfig (
+ IN CONST PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH SMBUS PreMem Config -------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable= %x\n", SmbusPreMemConfig->Enable));
+ DEBUG ((DEBUG_INFO, " ArpEnable= %x\n", SmbusPreMemConfig->ArpEnable));
+ DEBUG ((DEBUG_INFO, " DynamicPowerGating= %x\n", SmbusPreMemConfig->DynamicPowerGating));
+ DEBUG ((DEBUG_INFO, " SpdWriteDisable= %x\n", SmbusPreMemConfig->SpdWriteDisable));
+ DEBUG ((DEBUG_INFO, " SmbusIoBase= %x\n", SmbusPreMemConfig->SmbusIoBase));
+ DEBUG ((DEBUG_INFO, " NumRsvdSmbusAddresses= %x\n", SmbusPreMemConfig->NumRsvdSmbusAddresses));
+ DEBUG ((DEBUG_INFO, " RsvdSmbusAddressTable= {"));
+ for (Index = 0; Index < SmbusPreMemConfig->NumRsvdSmbusAddresses; ++Index) {
+ DEBUG ((DEBUG_INFO, " %02xh", SmbusPreMemConfig->RsvdSmbusAddressTable[Index]));
+ }
+ DEBUG ((DEBUG_INFO, " }\n"));
+}
+
+/**
+ Print PCH_LPC_PREMEM_CONFIG and serial out.
+
+ @param[in] LpcPreMemConfig Pointer to a PCH_LPC_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintLpcPreMemConfig (
+ IN CONST PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH LPC PreMem Config ---------------\n"));
+ DEBUG ((DEBUG_INFO, "EnhancePort8xhDecoding= %x\n", LpcPreMemConfig->EnhancePort8xhDecoding));
+}
+
+/**
+ Print PCH_HSIO_PCIE_PREMEM_CONFIG and serial out.
+
+ @param[in] HsioPciePreMemConfig Pointer to a PCH_HSIO_PCIE_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHsioPciePreMemConfig (
+ IN CONST PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ HSIO PCIE PreMem Config -------------\n"));
+ DEBUG ((DEBUG_INFO, " PciePllSsc = %x\n", HsioPciePreMemConfig->PciePllSsc));
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioRxSetCtleEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioRxSetCtleEnable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioRxSetCtle= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioRxSetCtle));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen1DownscaleAmpEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen1DownscaleAmp= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DownscaleAmpEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DownscaleAmp= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen3DownscaleAmpEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen3DownscaleAmp= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen3DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen1DeEmphEnable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen1DeEmph= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen1DeEmph));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DeEmph3p5Enable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5Enable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DeEmph3p5= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph3p5));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DeEmph6p0Enable= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0Enable));
+ DEBUG ((DEBUG_INFO, " Rp[%d] HsioTxGen2DeEmph6p0= %x\n", Index, HsioPciePreMemConfig->Lane[Index].HsioTxGen2DeEmph6p0));
+ }
+}
+
+/**
+ Print PCH_HSIO_SATA_PREMEM_CONFIG and serial out.
+
+ @param[in] HsioSataPreMemConfig Pointer to a PCH_HSIO_SATA_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHsioSataPreMemConfig (
+ IN CONST PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ HSIO SATA PreMem Config -------------\n"));
+ for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMagEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMagEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMag= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen1EqBoostMag));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMagEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMagEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMag= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen2EqBoostMag));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMagEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMagEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMag= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioRxGen3EqBoostMag));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmpEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmp= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmpEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmp= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmpEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmp= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmphEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmph= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen1DeEmph));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmphEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmph= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen2DeEmph));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmphEnable= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmph= %x\n", Index, HsioSataPreMemConfig->PortLane[Index].HsioTxGen3DeEmph));
+ }
+}
+
+/**
+ Print PCH_HSIO_PREMEM_CONFIG and serial out.
+
+ @param[in] HsioPreMemConfig Pointer to a PCH_HSIO_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHsioPreMemConfig (
+ IN CONST PCH_HSIO_PREMEM_CONFIG *HsioPreMemConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ HSIO PreMem Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " ChipsetInitMessage : 0x%x\n", HsioPreMemConfig->ChipsetInitMessage));
+ DEBUG ((DEBUG_INFO, " BypassPhySyncReset : 0x%x\n", HsioPreMemConfig->BypassPhySyncReset));
+}
+
+/**
+ Print PCH_PCIE_RP_PREMEM_CONFIG and serial out.
+
+ @param[in] PcieRpPreMemConfig Pointer to a PCH_PCIE_RP_PREMEM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintPcieRpPreMemConfig (
+ IN CONST PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig
+ )
+{
+ UINT32 Index;
+ DEBUG ((DEBUG_INFO, "------------------ PCH PCIe RP PreMem Config -----------\n"));
+
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " Port[%d] RpEnabled= %x\n", Index, (PcieRpPreMemConfig->RpEnabledMask & (UINT32) (1 << Index)) != 0 ));
+ }
+}
+
+
+/**
+ Print whole PCH_POLICY_PPI and serial out.
+
+ @param[in] SiPreMemPolicyPpi The RC PREMEM Policy PPI instance
+
+**/
+VOID
+PchPreMemPrintPolicyPpi (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ EFI_STATUS Status;
+ PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig;
+ PCH_DCI_PREMEM_CONFIG *DciPreMemConfig;
+ PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig;
+ PCH_TRACE_HUB_PREMEM_CONFIG *TraceHubPreMemConfig;
+ PCH_HPET_PREMEM_CONFIG *HpetPreMemConfig;
+ PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig;
+ PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig;
+ PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig;
+ PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig;
+ PCH_HSIO_PREMEM_CONFIG *HsioPreMemConfig;
+ PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPchGeneralPreMemConfigGuid, (VOID *) &PchGeneralPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gDciPreMemConfigGuid, (VOID *) &DciPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gWatchDogPreMemConfigGuid, (VOID *) &WdtPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gTraceHubPreMemConfigGuid, (VOID *) &TraceHubPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHpetPreMemConfigGuid, (VOID *) &HpetPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gSmbusPreMemConfigGuid, (VOID *) &SmbusPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gLpcPreMemConfigGuid, (VOID *) &LpcPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHsioPciePreMemConfigGuid, (VOID *) &HsioPciePreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHsioSataPreMemConfigGuid, (VOID *) &HsioSataPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gHsioPreMemConfigGuid, (VOID *) &HsioPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPcieRpPreMemConfigGuid, (VOID *) &PcieRpPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Print PreMemPolicy Start ------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision= %x\n", SiPreMemPolicyPpi->TableHeader.Header.Revision));
+
+ PchPrintGeneralPreMemConfig (PchGeneralPreMemConfig);
+ PchPrintDciPreMemConfig (DciPreMemConfig);
+ PchPrintWdtPreMemConfig (WdtPreMemConfig);
+ PchPrintTraceHubPreMemConfig (TraceHubPreMemConfig);
+ PchPrintHpetPreMemConfig (HpetPreMemConfig);
+ PchPrintSmbusPreMemConfig (SmbusPreMemConfig);
+ PchPrintLpcPreMemConfig (LpcPreMemConfig);
+ PchPrintHsioPciePreMemConfig (HsioPciePreMemConfig);
+ PchPrintHsioSataPreMemConfig (HsioSataPreMemConfig);
+ PchPrintHsioPreMemConfig (HsioPreMemConfig);
+ PchPrintPcieRpPreMemConfig (PcieRpPreMemConfig);
+
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Print PreMemPolicy End --------------------------\n"));
+ DEBUG_CODE_END ();
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy.c
new file mode 100644
index 0000000000..13a8f9fbd6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchPrintPolicy.c
@@ -0,0 +1,783 @@
+/** @file
+ Print whole PCH_POLICY_PPI
+
+Copyright (c) 2017, 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 that 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 "PeiPchPolicyLibrary.h"
+
+/**
+ Print PCH_USB_CONFIG and serial out.
+
+ @param[in] UsbConfig Pointer to a PCH_USB_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintUsbConfig (
+ IN CONST PCH_USB_CONFIG *UsbConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH USB Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " DisableComplianceMode = %x\n", UsbConfig->DisableComplianceMode));
+ DEBUG ((DEBUG_INFO, " DelayPdoProgramming = %x\n", UsbConfig->DelayPdoProgramming));
+
+ for (Index = 0; Index < GetPchUsbMaxPhysicalPortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Enabled = %x\n", Index, UsbConfig->PortUsb20[Index].Enable));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].OverCurrentPin = OC%x\n", Index, UsbConfig->PortUsb20[Index].OverCurrentPin));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Petxiset = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Petxiset));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Txiset = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Txiset));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Predeemp = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Predeemp));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Pehalfbit = %x\n", Index, UsbConfig->PortUsb20[Index].Afe.Pehalfbit));
+ }
+
+ for (Index = 0; Index < GetPchXhciMaxUsb3PortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d] Enabled = %x\n", Index, UsbConfig->PortUsb30[Index].Enable));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].OverCurrentPin = OC%x\n", Index, UsbConfig->PortUsb30[Index].OverCurrentPin));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmph = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDeEmph));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmphEnable = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmp = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmpEnable = %x\n", Index, UsbConfig->PortUsb30[Index].HsioTxDownscaleAmpEnable));
+ }
+
+ DEBUG ((DEBUG_INFO, " XdciConfig.Enable = %x\n", UsbConfig->XdciConfig.Enable));
+
+ for (Index = 0; Index < PCH_XHCI_MAX_SSIC_PORT_COUNT; Index++) {
+ DEBUG ((DEBUG_INFO, " SsicPort[%d].Enable = %x\n", Index, UsbConfig->SsicConfig.SsicPort[Index].Enable));
+ }
+
+}
+
+/**
+ Print PCH_PCIE_CONFIG and serial out.
+
+ @param[in] PcieConfig Pointer to a PCH_PCIE_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintPcieConfig (
+ IN CONST PCH_PCIE_CONFIG *PcieConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH PCIE Config ------------------\n"));
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HotPlug= %x\n", Index, PcieConfig->RootPort[Index].HotPlug));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PmSci= %x\n", Index, PcieConfig->RootPort[Index].PmSci));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ExtSync= %x\n", Index, PcieConfig->RootPort[Index].ExtSync));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqSupported= %x\n", Index, PcieConfig->RootPort[Index].ClkReqSupported));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqNumber= %x\n", Index, PcieConfig->RootPort[Index].ClkReqNumber));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqDetect= %x\n", Index, PcieConfig->RootPort[Index].ClkReqDetect));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] UnsupportedRequestReport= %x\n", Index, PcieConfig->RootPort[Index].UnsupportedRequestReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] FatalErrorReport= %x\n", Index, PcieConfig->RootPort[Index].FatalErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NoFatalErrorReport= %x\n", Index, PcieConfig->RootPort[Index].NoFatalErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] CorrectableErrorReport= %x\n", Index, PcieConfig->RootPort[Index].CorrectableErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnFatalError= %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnFatalError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnNonFatalError= %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnNonFatalError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnCorrectableError= %x\n", Index, PcieConfig->RootPort[Index].SystemErrorOnCorrectableError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] MaxPayload= %x\n", Index, PcieConfig->RootPort[Index].MaxPayload));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] AcsEnabled= %x\n", Index, PcieConfig->RootPort[Index].AcsEnabled));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] AdvancedErrorReporting= %x\n", Index, PcieConfig->RootPort[Index].AdvancedErrorReporting));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] TransmitterHalfSwing= %x\n", Index, PcieConfig->RootPort[Index].TransmitterHalfSwing));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PcieSpeed= %x\n", Index, PcieConfig->RootPort[Index].PcieSpeed));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Gen3EqPh3Method= %x\n", Index, PcieConfig->RootPort[Index].Gen3EqPh3Method));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PhysicalSlotNumber= %x\n", Index, PcieConfig->RootPort[Index].PhysicalSlotNumber));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] CompletionTimeout= %x\n", Index, PcieConfig->RootPort[Index].CompletionTimeout));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Aspm= %x\n", Index, PcieConfig->RootPort[Index].Aspm));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] L1Substates= %x\n", Index, PcieConfig->RootPort[Index].L1Substates));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrEnable= %x\n", Index, PcieConfig->RootPort[Index].LtrEnable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrConfigLock= %x\n", Index, PcieConfig->RootPort[Index].LtrConfigLock));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxSnoopLatency= %x\n", Index, PcieConfig->RootPort[Index].LtrMaxSnoopLatency));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxNoSnoopLatency= %x\n", Index, PcieConfig->RootPort[Index].LtrMaxNoSnoopLatency));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMode= %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideMode));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMultiplier= %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideMultiplier));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideValue= %x\n", Index, PcieConfig->RootPort[Index].SnoopLatencyOverrideValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMode= %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideMode));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMultiplier= %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideMultiplier));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideValue= %x\n", Index, PcieConfig->RootPort[Index].NonSnoopLatencyOverrideValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ForceLtrOverride= %x\n", Index, PcieConfig->RootPort[Index].ForceLtrOverride));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] DetectTimeoutMs= %x\n", Index, PcieConfig->RootPort[Index].DetectTimeoutMs));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitScale= %x\n", Index, PcieConfig->RootPort[Index].SlotPowerLimitScale));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitValue= %x\n", Index, PcieConfig->RootPort[Index].SlotPowerLimitValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Uptp= %x\n", Index, PcieConfig->RootPort[Index].Uptp));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Dptp= %x\n", Index, PcieConfig->RootPort[Index].Dptp));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] EnableCpm= %x\n", Index, PcieConfig->RootPort[Index].EnableCpm));
+
+ }
+ for (Index = 0; Index < PCH_PCIE_SWEQ_COEFFS_MAX; Index++) {
+ DEBUG ((DEBUG_INFO, " SwEqCoeffCm[%d] = %x\n", Index, PcieConfig->SwEqCoeffList[Index].Cm));
+ DEBUG ((DEBUG_INFO, " SwEqCoeffCp[%d] = %x\n", Index, PcieConfig->SwEqCoeffList[Index].Cp));
+ }
+ DEBUG ((DEBUG_INFO, " EnablePort8xhDecode= %x\n", PcieConfig->EnablePort8xhDecode));
+ DEBUG ((DEBUG_INFO, " PchPciePort8xhDecodePortIndex= %x\n", PcieConfig->PchPciePort8xhDecodePortIndex));
+ DEBUG ((DEBUG_INFO, " DisableRootPortClockGating= %x\n", PcieConfig->DisableRootPortClockGating));
+ DEBUG ((DEBUG_INFO, " EnablePeerMemoryWrite= %x\n", PcieConfig->EnablePeerMemoryWrite));
+ DEBUG ((DEBUG_INFO, " AllowNoLtrIccPllShutdown= %x\n", PcieConfig->AllowNoLtrIccPllShutdown));
+ DEBUG ((DEBUG_INFO, " ComplianceTestMode= %x\n", PcieConfig->ComplianceTestMode));
+ DEBUG ((DEBUG_INFO, " RpFunctionSwap= %x\n", PcieConfig->RpFunctionSwap));
+ DEBUG ((DEBUG_INFO, " PcieDeviceOverrideTablePtr= %x\n", PcieConfig->PcieDeviceOverrideTablePtr));
+}
+
+/**
+ Print PCH_SATA_CONFIG and serial out.
+
+ @param[in] SataConfig Pointer to a PCH_SATA_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSataConfig (
+ IN CONST PCH_SATA_CONFIG *SataConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH SATA Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable= %x\n", SataConfig->Enable));
+ DEBUG ((DEBUG_INFO, " SataMode= %x\n", SataConfig->SataMode));
+
+ for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] Enabled= %x\n", Index, SataConfig->PortSettings[Index].Enable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HotPlug= %x\n", Index, SataConfig->PortSettings[Index].HotPlug));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] InterlockSw= %x\n", Index, SataConfig->PortSettings[Index].InterlockSw));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] External= %x\n", Index, SataConfig->PortSettings[Index].External));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] SpinUp= %x\n", Index, SataConfig->PortSettings[Index].SpinUp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] SolidStateDrive= %x\n", Index, SataConfig->PortSettings[Index].SolidStateDrive));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DevSlp= %x\n", Index, SataConfig->PortSettings[Index].DevSlp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] EnableDitoConfig= %x\n", Index, SataConfig->PortSettings[Index].EnableDitoConfig));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DmVal= %x\n", Index, SataConfig->PortSettings[Index].DmVal));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DitoVal= %x\n", Index, SataConfig->PortSettings[Index].DitoVal));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] ZpOdd= %x\n", Index, SataConfig->PortSettings[Index].ZpOdd));
+ }
+
+ DEBUG ((DEBUG_INFO, " RaidAlternateId= %x\n", SataConfig->Rst.RaidAlternateId));
+ DEBUG ((DEBUG_INFO, " Raid0= %x\n", SataConfig->Rst.Raid0));
+ DEBUG ((DEBUG_INFO, " Raid1= %x\n", SataConfig->Rst.Raid1));
+ DEBUG ((DEBUG_INFO, " Raid10= %x\n", SataConfig->Rst.Raid10));
+ DEBUG ((DEBUG_INFO, " Raid5= %x\n", SataConfig->Rst.Raid5));
+ DEBUG ((DEBUG_INFO, " Irrt= %x\n", SataConfig->Rst.Irrt));
+ DEBUG ((DEBUG_INFO, " OromUiBanner= %x\n", SataConfig->Rst.OromUiBanner));
+ DEBUG ((DEBUG_INFO, " OromUiDelay= %x\n", SataConfig->Rst.OromUiDelay));
+ DEBUG ((DEBUG_INFO, " HddUnlock= %x\n", SataConfig->Rst.HddUnlock));
+ DEBUG ((DEBUG_INFO, " LedLocate= %x\n", SataConfig->Rst.LedLocate));
+ DEBUG ((DEBUG_INFO, " IrrtOnly= %x\n", SataConfig->Rst.IrrtOnly));
+ DEBUG ((DEBUG_INFO, " SmartStorage= %x\n", SataConfig->Rst.SmartStorage));
+ DEBUG ((DEBUG_INFO, " LegacyOrom= %x\n", SataConfig->Rst.LegacyOrom));
+ DEBUG ((DEBUG_INFO, " OptaneMemory= %x\n", SataConfig->Rst.OptaneMemory));
+
+ DEBUG ((DEBUG_INFO, " SpeedSupport= %x\n", SataConfig->SpeedLimit));
+ DEBUG ((DEBUG_INFO, " EsataSpeedLimit= %x\n", SataConfig->EsataSpeedLimit));
+ DEBUG ((DEBUG_INFO, " TestMode= %x\n", SataConfig->TestMode));
+ DEBUG ((DEBUG_INFO, " SalpSupport= %x\n", SataConfig->SalpSupport));
+ DEBUG ((DEBUG_INFO, " PwrOptEnable= %x\n", SataConfig->PwrOptEnable));
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].Enable = %x\n", Index, SataConfig->RstPcieStorageRemap[Index].Enable));
+ DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].RstPcieStoragePort = %x\n", Index, SataConfig->RstPcieStorageRemap[Index].RstPcieStoragePort));
+ DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].DeviceResetDelay = %x\n", Index, SataConfig->RstPcieStorageRemap[Index].DeviceResetDelay));
+ }
+}
+
+/**
+ Print PCH_IOAPIC_CONFIG and serial out.
+
+ @param[in] IoApicConfig Pointer to a PCH_IOAPIC_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintIoApicConfig (
+ IN CONST PCH_IOAPIC_CONFIG *IoApicConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH IOAPIC Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " BdfValid= %x\n", IoApicConfig->BdfValid));
+ DEBUG ((DEBUG_INFO, " BusNumber= %x\n", IoApicConfig->BusNumber));
+ DEBUG ((DEBUG_INFO, " DeviceNumber= %x\n", IoApicConfig->DeviceNumber));
+ DEBUG ((DEBUG_INFO, " FunctionNumber= %x\n", IoApicConfig->FunctionNumber));
+ DEBUG ((DEBUG_INFO, " IoApicEntry24_119= %x\n", IoApicConfig->IoApicEntry24_119));
+ DEBUG ((DEBUG_INFO, " Early8254ClockGatingEnable= %x\n", IoApicConfig->Early8254ClockGatingEnable));
+ DEBUG ((DEBUG_INFO, " IoApicId= %x\n", IoApicConfig->IoApicId));
+ DEBUG ((DEBUG_INFO, " ApicRangeSelect= %x\n", IoApicConfig->ApicRangeSelect));
+}
+
+/**
+ Print PCH_LOCK_DOWN_CONFIG and serial out.
+
+ @param[in] LockDownConfig Pointer to a PCH_LOCK_DOWN_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintLockDownConfig (
+ IN CONST PCH_LOCK_DOWN_CONFIG *LockDownConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH Lock Down Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " GlobalSmi= %x\n", LockDownConfig->GlobalSmi));
+ DEBUG ((DEBUG_INFO, " BiosInterface= %x\n", LockDownConfig->BiosInterface));
+ DEBUG ((DEBUG_INFO, " RtcLock= %x\n", LockDownConfig->RtcLock));
+ DEBUG ((DEBUG_INFO, " BiosLock= %x\n", LockDownConfig->BiosLock));
+ DEBUG ((DEBUG_INFO, " SpiEiss= %x\n", LockDownConfig->SpiEiss));
+}
+
+/**
+ Print PCH_HDAUDIO_CONFIG and serial out.
+
+ @param[in] HdaConfig Pointer to a PCH_HDAUDIO_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHdAudioConfig (
+ IN CONST PCH_HDAUDIO_CONFIG *HdaConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH HD-Audio Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " HDA Enable = %x\n", HdaConfig->Enable));
+ DEBUG ((DEBUG_INFO, " DSP Enable = %x\n", HdaConfig->DspEnable));
+ DEBUG ((DEBUG_INFO, " DSP UAA Compliance = %x\n", HdaConfig->DspUaaCompliance));
+ DEBUG ((DEBUG_INFO, " iDisp Codec Disconnect = %x\n", HdaConfig->IDispCodecDisconnect));
+ DEBUG ((DEBUG_INFO, " Pme = %x\n", HdaConfig->Pme));
+ DEBUG ((DEBUG_INFO, " I/O Buffer Ownership = %x\n", HdaConfig->IoBufferOwnership));
+ DEBUG ((DEBUG_INFO, " I/O Buffer Voltage = %x\n", HdaConfig->IoBufferVoltage));
+ DEBUG ((DEBUG_INFO, " VC Type = %x\n", HdaConfig->VcType));
+ DEBUG ((DEBUG_INFO, " HD-A Link Frequency = %x\n", HdaConfig->HdAudioLinkFrequency));
+ DEBUG ((DEBUG_INFO, " iDisp Link Frequency = %x\n", HdaConfig->IDispLinkFrequency));
+ DEBUG ((DEBUG_INFO, " iDisp Link T-Mode = %x\n", HdaConfig->IDispLinkTmode));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint DMIC = %x\n", HdaConfig->DspEndpointDmic));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint I2S = %x\n", HdaConfig->DspEndpointI2s));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint BT = %x\n", HdaConfig->DspEndpointBluetooth));
+ DEBUG ((DEBUG_INFO, " DSP Feature Mask = %x\n", HdaConfig->DspFeatureMask));
+ DEBUG ((DEBUG_INFO, " ResetWaitTimer = %x\n", HdaConfig->ResetWaitTimer));
+ DEBUG ((DEBUG_INFO, " VerbTableEntryNum = %x\n", HdaConfig->VerbTableEntryNum));
+ DEBUG ((DEBUG_INFO, " VerbTablePtr = %x\n", HdaConfig->VerbTablePtr));
+}
+
+/**
+ Print PCH_PM_CONFIG and serial out.
+
+ @param[in] PmConfig Pointer to a PCH_PM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintPmConfig (
+ IN CONST PCH_PM_CONFIG *PmConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH PM Config ------------------\n"));
+
+ DEBUG ((DEBUG_INFO, " WakeConfig PmeB0S5Dis = %x\n", PmConfig->WakeConfig.PmeB0S5Dis));
+ DEBUG ((DEBUG_INFO, " WakeConfig WolEnableOverride = %x\n", PmConfig->WakeConfig.WolEnableOverride));
+ DEBUG ((DEBUG_INFO, " WakeConfig LanWakeFromDeepSx = %x\n", PmConfig->WakeConfig.LanWakeFromDeepSx));
+ DEBUG ((DEBUG_INFO, " WakeConfig PcieWakeFromDeepSx = %x\n", PmConfig->WakeConfig.PcieWakeFromDeepSx));
+ DEBUG ((DEBUG_INFO, " WakeConfig WoWlanEnable = %x\n", PmConfig->WakeConfig.WoWlanEnable));
+ DEBUG ((DEBUG_INFO, " WakeConfig WoWlanDeepSxEnable = %x\n", PmConfig->WakeConfig.WoWlanDeepSxEnable));
+
+ DEBUG ((DEBUG_INFO, " PchDeepSxPol = %x\n", PmConfig->PchDeepSxPol));
+ DEBUG ((DEBUG_INFO, " PchSlpS3MinAssert = %x\n", PmConfig->PchSlpS3MinAssert));
+ DEBUG ((DEBUG_INFO, " PchSlpS4MinAssert = %x\n", PmConfig->PchSlpS4MinAssert));
+ DEBUG ((DEBUG_INFO, " PchSlpSusMinAssert = %x\n", PmConfig->PchSlpSusMinAssert));
+ DEBUG ((DEBUG_INFO, " PchSlpAMinAssert = %x\n", PmConfig->PchSlpAMinAssert));
+ DEBUG ((DEBUG_INFO, " LpcClockRun = %x\n", PmConfig->LpcClockRun));
+ DEBUG ((DEBUG_INFO, " SlpStrchSusUp = %x\n", PmConfig->SlpStrchSusUp));
+ DEBUG ((DEBUG_INFO, " SlpLanLowDc = %x\n", PmConfig->SlpLanLowDc));
+ DEBUG ((DEBUG_INFO, " PwrBtnOverridePeriod = %x\n", PmConfig->PwrBtnOverridePeriod));
+ DEBUG ((DEBUG_INFO, " DisableEnergyReport = %x\n", PmConfig->DisableEnergyReport));
+ DEBUG ((DEBUG_INFO, " DisableDsxAcPresentPulldown = %x\n", PmConfig->DisableDsxAcPresentPulldown));
+ DEBUG ((DEBUG_INFO, " PmcReadDisable = %x\n", PmConfig->PmcReadDisable));
+ DEBUG ((DEBUG_INFO, " PchPwrCycDur = %x\n", PmConfig->PchPwrCycDur));
+ DEBUG ((DEBUG_INFO, " DisableNativePowerButton = %x\n", PmConfig->DisableNativePowerButton));
+ DEBUG ((DEBUG_INFO, " SlpS0Enabled = %x\n", PmConfig->SlpS0Enable));
+ DEBUG ((DEBUG_INFO, " MeWakeSts = %x\n", PmConfig->MeWakeSts));
+ DEBUG ((DEBUG_INFO, " WolOvrWkSts = %x\n", PmConfig->WolOvrWkSts));
+ DEBUG ((DEBUG_INFO, " EnableTcoTimer = %x\n", PmConfig->EnableTcoTimer));
+ DEBUG ((DEBUG_INFO, " SlpS0VmEnable = %x\n", PmConfig->SlpS0VmEnable));
+
+}
+
+/**
+ Print PCH_DMI_CONFIG and serial out.
+
+ @param[in] DmiConfig Pointer to a PCH_DMI_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintDmiConfig (
+ IN CONST PCH_DMI_CONFIG *DmiConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH DMI Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " DmiAspm= %x\n", DmiConfig->DmiAspm));
+ DEBUG ((DEBUG_INFO, " PwrOptEnable= %x\n", DmiConfig->PwrOptEnable));
+ DEBUG ((DEBUG_INFO, " LegacyIoLowLatency= %x\n", DmiConfig->LegacyIoLowLatency));
+
+}
+
+/**
+ Print PCH_LPC_SIRQ_CONFIG and serial out.
+
+ @param[in] SerialIrqConfig Pointer to a PCH_LPC_SIRQ_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSerialIrqConfig (
+ IN CONST PCH_LPC_SIRQ_CONFIG *SerialIrqConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH LPC SIRQ Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " SirqEnable= %x\n", SerialIrqConfig->SirqEnable));
+ DEBUG ((DEBUG_INFO, " SirqMode= %x\n", SerialIrqConfig->SirqMode));
+ DEBUG ((DEBUG_INFO, " StartFramePulse= %x\n", SerialIrqConfig->StartFramePulse));
+}
+
+/**
+ Print PCH_THERMAL_CONFIG and serial out.
+
+ @param[in] ThermalConfig Pointer to a PCH_THERMAL_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintThermalConfig (
+ IN CONST PCH_THERMAL_CONFIG *ThermalConfig
+ )
+{
+ UINTN Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH Thermal Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " TsmicLock= %x\n", ThermalConfig->TsmicLock));
+ DEBUG ((DEBUG_INFO, " TTLevels T0Level %x centigrade degree\n", ThermalConfig->TTLevels.T0Level));
+ DEBUG ((DEBUG_INFO, " TTLevels T1Level %x centigrade degree\n", ThermalConfig->TTLevels.T1Level));
+ DEBUG ((DEBUG_INFO, " TTLevels T2Level %x centigrade degree\n", ThermalConfig->TTLevels.T2Level));
+ DEBUG ((DEBUG_INFO, " TTLevels TTEnable %x\n", ThermalConfig->TTLevels.TTEnable));
+ DEBUG ((DEBUG_INFO, " TTLevels TTState13Enable %x\n", ThermalConfig->TTLevels.TTState13Enable));
+ DEBUG ((DEBUG_INFO, " TTLevels TTLock %x\n", ThermalConfig->TTLevels.TTLock));
+ DEBUG ((DEBUG_INFO, " TTLevels SuggestedSetting %x\n", ThermalConfig->TTLevels.SuggestedSetting));
+ DEBUG ((DEBUG_INFO, " TTLevels PchCrossThrottling %x\n", ThermalConfig->TTLevels.PchCrossThrottling));
+
+ DEBUG ((DEBUG_INFO, " DmiHaAWC DmiTsawEn %x\n", ThermalConfig->DmiHaAWC.DmiTsawEn));
+ DEBUG ((DEBUG_INFO, " DmiHaAWC TS0TW %x\n", ThermalConfig->DmiHaAWC.TS0TW));
+ DEBUG ((DEBUG_INFO, " DmiHaAWC TS1TW %x\n", ThermalConfig->DmiHaAWC.TS1TW));
+ DEBUG ((DEBUG_INFO, " DmiHaAWC TS2TW %x\n", ThermalConfig->DmiHaAWC.TS2TW));
+ DEBUG ((DEBUG_INFO, " DmiHaAWC TS3TW %x\n", ThermalConfig->DmiHaAWC.TS3TW));
+ DEBUG ((DEBUG_INFO, " DmiHaAWC SuggestedSetting %x\n", ThermalConfig->DmiHaAWC.SuggestedSetting));
+
+ DEBUG ((DEBUG_INFO, " SataTT P0T1M %x\n", ThermalConfig->SataTT.P0T1M));
+ DEBUG ((DEBUG_INFO, " SataTT P0T2M %x\n", ThermalConfig->SataTT.P0T2M));
+ DEBUG ((DEBUG_INFO, " SataTT P0T3M %x\n", ThermalConfig->SataTT.P0T3M));
+ DEBUG ((DEBUG_INFO, " SataTT P0TDisp %x\n", ThermalConfig->SataTT.P0TDisp));
+ DEBUG ((DEBUG_INFO, " SataTT P0Tinact %x\n", ThermalConfig->SataTT.P0Tinact));
+ DEBUG ((DEBUG_INFO, " SataTT P0TDispFinit %x\n", ThermalConfig->SataTT.P0TDispFinit));
+ DEBUG ((DEBUG_INFO, " SataTT P1T1M %x\n", ThermalConfig->SataTT.P1T1M));
+ DEBUG ((DEBUG_INFO, " SataTT P1T2M %x\n", ThermalConfig->SataTT.P1T2M));
+ DEBUG ((DEBUG_INFO, " SataTT P1T3M %x\n", ThermalConfig->SataTT.P1T3M));
+ DEBUG ((DEBUG_INFO, " SataTT P1TDisp %x\n", ThermalConfig->SataTT.P1TDisp));
+ DEBUG ((DEBUG_INFO, " SataTT P1Tinact %x\n", ThermalConfig->SataTT.P1Tinact));
+ DEBUG ((DEBUG_INFO, " SataTT P1TDispFinit %x\n", ThermalConfig->SataTT.P1TDispFinit));
+ DEBUG ((DEBUG_INFO, " SataTT SuggestedSetting %x\n", ThermalConfig->SataTT.SuggestedSetting));
+
+ DEBUG ((DEBUG_INFO, " MemoryThrottling Enable= %x\n", ThermalConfig->MemoryThrottling.Enable));
+ for (Index = 0; Index < MaxTsGpioPin; Index++) {
+ DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting PmsyncEnable= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].PmsyncEnable));
+ DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting C0TransmitEnable= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].C0TransmitEnable));
+ DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting PinSelection= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[Index].PinSelection));
+ }
+ DEBUG ((DEBUG_INFO, " PchHotLevel = %x\n", ThermalConfig->PchHotLevel));
+ DEBUG ((DEBUG_INFO, " ThermalDeviceEnable %x\n", ThermalConfig->ThermalDeviceEnable));
+}
+
+/**
+ Print PCH_GENERAL_CONFIG and serial out.
+
+ @param[in] PchGeneralConfig Pointer to a PCH_GENERAL_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintGeneralConfig (
+ IN CONST PCH_GENERAL_CONFIG *PchGeneralConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH General Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " SubSystemVendorId= %x\n", PchGeneralConfig->SubSystemVendorId));
+ DEBUG ((DEBUG_INFO, " SubSystemId= %x\n", PchGeneralConfig->SubSystemId));
+ DEBUG ((DEBUG_INFO, " Crid= %x\n", PchGeneralConfig->Crid));
+}
+
+/**
+ Print PCH_LAN_CONFIG and serial out.
+
+ @param[in] LanConfig Pointer to a PCH_LAN_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintLanConfig (
+ IN CONST PCH_LAN_CONFIG *LanConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH LAN Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable= %x\n", LanConfig->Enable));
+ DEBUG ((DEBUG_INFO, " LtrEnable= %x\n", LanConfig->LtrEnable));
+ DEBUG ((DEBUG_INFO, " K1OffEnable= %x\n", LanConfig->K1OffEnable));
+ DEBUG ((DEBUG_INFO, " ClkReqSupported= %d\n", LanConfig->ClkReqSupported));
+ DEBUG ((DEBUG_INFO, " ClkReqNumber= %d\n", LanConfig->ClkReqNumber));
+}
+
+/**
+ Print PCH_SERIAL_IO_CONFIG and serial out.
+
+ @param[in] SerialIoConfig Pointer to a PCH_SERIAL_IO_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSerialIoConfig (
+ IN CONST PCH_SERIAL_IO_CONFIG *SerialIoConfig
+ )
+{
+ UINTN Index;
+#ifndef MDEPKG_NDEBUG
+ static CHAR16 DeviceName[11][5] = {L"I2C0",L"I2C1",L"I2C2",L"I2C3",L"I2C4",L"I2C5",L"SPI0",L"SPI1",L"UA00",L"UA01",L"UA02"};
+#endif
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH Serial IO Config ------------------\n"));
+ DEBUG_CODE_BEGIN ();
+ for (Index=0; Index<PCH_SERIALIO_MAX_CONTROLLERS; Index++) {
+ DEBUG ((DEBUG_INFO, " SerialIoController %s: Mode %x\n", DeviceName[Index], SerialIoConfig->DevMode[Index]));
+ }
+ DEBUG_CODE_END ();
+ DEBUG ((DEBUG_INFO, " Gpio= %x\n", SerialIoConfig->Gpio));
+ for (Index=0; Index<PCH_SERIALIO_MAX_I2C_CONTROLLERS; Index++) {
+ DEBUG ((DEBUG_INFO, " I2cVoltage[%d] = %x\n", Index, SerialIoConfig->I2cVoltage[Index]));
+ }
+ for (Index=0; Index<PCH_SERIALIO_MAX_SPI_CONTROLLERS; Index++) {
+ DEBUG ((DEBUG_INFO, " SpiCsPolarity[%d] = %x\n", Index, SerialIoConfig->SpiCsPolarity[Index]));
+ }
+ for (Index=0; Index<PCH_SERIALIO_MAX_UART_CONTROLLERS; Index++) {
+ DEBUG ((DEBUG_INFO, " UartHwFlowCtrl[%d] = %x\n", Index, SerialIoConfig->UartHwFlowCtrl[Index]));
+ }
+ DEBUG ((DEBUG_INFO, " DebugUartNumber = %x\n", SerialIoConfig->DebugUartNumber));
+ DEBUG ((DEBUG_INFO, " EnableDebugUartAfterPost = %x\n", SerialIoConfig->EnableDebugUartAfterPost));
+}
+
+/**
+ Print PCH_INTERRUPT_CONFIG and serial out
+
+ @param[in] InterruptConfig Pointer to Interrupt Configuration structure
+
+**/
+VOID
+PchPrintInterruptConfig (
+ IN CONST PCH_INTERRUPT_CONFIG *InterruptConfig
+ )
+{
+ UINTN Index;
+ //
+ // Print interrupt information
+ //
+ DEBUG ((DEBUG_INFO, "------------------ PCH Interrupt Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Interrupt assignment:\n"));
+ DEBUG ((DEBUG_INFO, " Dxx:Fx INTx IRQ\n"));
+ for (Index = 0; Index < InterruptConfig->NumOfDevIntConfig; Index++) {
+ DEBUG ((DEBUG_INFO, " D%02d:F%d %d %03d\n",
+ InterruptConfig->DevIntConfig[Index].Device,
+ InterruptConfig->DevIntConfig[Index].Function,
+ InterruptConfig->DevIntConfig[Index].IntX,
+ InterruptConfig->DevIntConfig[Index].Irq));
+ }
+ DEBUG ((DEBUG_INFO, " Legacy PIC interrupt routing:\n"));
+ DEBUG ((DEBUG_INFO, " PIRQx IRQx\n"));
+ for (Index = 0; Index < PCH_MAX_PXRC_CONFIG; Index++) {
+ DEBUG ((DEBUG_INFO, " PIRQ%c -> IRQ%d\n", Index + 65, InterruptConfig->PxRcConfig[Index]));
+ }
+ DEBUG ((DEBUG_INFO, " Other interrupt configuration:\n"));
+ DEBUG ((DEBUG_INFO, " GpioIrqRoute= %d\n", InterruptConfig->GpioIrqRoute));
+ DEBUG ((DEBUG_INFO, " SciIrqSelect= %d\n", InterruptConfig->SciIrqSelect));
+ DEBUG ((DEBUG_INFO, " TcoIrqEnable= %d\n", InterruptConfig->TcoIrqEnable));
+ DEBUG ((DEBUG_INFO, " TcoIrqSelect= %d\n", InterruptConfig->TcoIrqSelect));
+}
+
+/**
+ Print PCH_SKYCAM_CIO2_CONFIG and serial out.
+
+ @param[in] Cio2Config Pointer to a PCH_SKYCAM_CIO2_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintCio2Config (
+ IN CONST PCH_CIO2_CONFIG *Cio2Config
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH CIO2 Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "DeviceEnable= %x\n", Cio2Config->DeviceEnable));
+ DEBUG ((DEBUG_INFO, "SkyCamPortATermOvrEnable= %x\n", Cio2Config->SkyCamPortATermOvrEnable));
+ DEBUG ((DEBUG_INFO, "SkyCamPortBTermOvrEnable= %x\n", Cio2Config->SkyCamPortBTermOvrEnable));
+ DEBUG ((DEBUG_INFO, "SkyCamPortCTermOvrEnable= %x\n", Cio2Config->SkyCamPortCTermOvrEnable));
+ DEBUG ((DEBUG_INFO, "SkyCamPortDTermOvrEnable= %x\n", Cio2Config->SkyCamPortDTermOvrEnable));
+ DEBUG ((DEBUG_INFO, "------------------ PCH CIO2 FLS Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "PortATrimEnable= %x\n", Cio2Config->PortATrimEnable));
+ DEBUG ((DEBUG_INFO, "PortBTrimEnable= %x\n", Cio2Config->PortBTrimEnable));
+ DEBUG ((DEBUG_INFO, "PortCTrimEnable= %x\n", Cio2Config->PortCTrimEnable));
+ DEBUG ((DEBUG_INFO, "PortDTrimEnable= %x\n", Cio2Config->PortDTrimEnable));
+ DEBUG ((DEBUG_INFO, "PortACtleEnable= %x\n", Cio2Config->PortACtleEnable));
+ DEBUG ((DEBUG_INFO, "PortBCtleEnable= %x\n", Cio2Config->PortBCtleEnable));
+ DEBUG ((DEBUG_INFO, "PortCDCtleEnable= %x\n", Cio2Config->PortCDCtleEnable));
+ DEBUG ((DEBUG_INFO, "PortACtleCapValue= %x\n", Cio2Config->PortACtleCapValue));
+ DEBUG ((DEBUG_INFO, "PortBCtleCapValue= %x\n", Cio2Config->PortBCtleCapValue));
+ DEBUG ((DEBUG_INFO, "PortCDCtleCapValue= %x\n", Cio2Config->PortCDCtleCapValue));
+ DEBUG ((DEBUG_INFO, "PortADataTrimValue= %x\n", Cio2Config->PortADataTrimValue));
+ DEBUG ((DEBUG_INFO, "PortBDataTrimValue= %x\n", Cio2Config->PortBDataTrimValue));
+ DEBUG ((DEBUG_INFO, "PortCDDataTrimValue= %x\n", Cio2Config->PortCDDataTrimValue));
+ DEBUG ((DEBUG_INFO, "PortACtleResValue= %x\n", Cio2Config->PortACtleResValue));
+ DEBUG ((DEBUG_INFO, "PortBCtleResValue= %x\n", Cio2Config->PortBCtleResValue));
+ DEBUG ((DEBUG_INFO, "PortCDCtleResValue= %x\n", Cio2Config->PortCDCtleResValue));
+ DEBUG ((DEBUG_INFO, "PortAClkTrimValue= %x\n", Cio2Config->PortAClkTrimValue));
+ DEBUG ((DEBUG_INFO, "PortBClkTrimValue= %x\n", Cio2Config->PortBClkTrimValue));
+ DEBUG ((DEBUG_INFO, "PortCClkTrimValue= %x\n", Cio2Config->PortCClkTrimValue));
+ DEBUG ((DEBUG_INFO, "PortDClkTrimValue= %x\n", Cio2Config->PortDClkTrimValue));
+}
+
+/**
+ Print PCH_PORT61H_SMM_CONFIG and serial out.
+
+ @param[in] Port61hSmmConfig Pointer to a PCH_PORT61H_SMM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintPort61hSmmConfig (
+ IN CONST PCH_PORT61H_SMM_CONFIG *Port61hSmmConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH Port61 Smm Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "Enable= %x\n", Port61hSmmConfig->Enable));
+}
+
+/**
+ Print PCH_SCS_CONFIG and serial out.
+
+ @param[in] ScsConfig Pointer to a PCH_SCS_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintScsConfig (
+ IN CONST PCH_SCS_CONFIG *ScsConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH SCS Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " ScsEmmcEnabled = %x\n", ScsConfig->ScsEmmcEnabled));
+ DEBUG ((DEBUG_INFO, " ScsSdSwitch = %x\n", ScsConfig->ScsSdSwitch));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400Enabled = %x\n", ScsConfig->ScsEmmcHs400Enabled));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400TuningRequired = %x\n", ScsConfig->ScsEmmcHs400TuningRequired));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400DllDataValid = %x\n", ScsConfig->ScsEmmcHs400DllDataValid));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400RxStrobeDll1 = %x\n", ScsConfig->ScsEmmcHs400RxStrobeDll1));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400TxDataDll = %x\n", ScsConfig->ScsEmmcHs400TxDataDll));
+ DEBUG ((DEBUG_INFO, " ScsEmmcHs400DriverStrength = %x\n", ScsConfig->ScsEmmcHs400DriverStrength));
+}
+
+/**
+ Print PCH_ISH_CONFIG and serial out.
+
+ @param[in] IshConfig Pointer to a PCH_ISH_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintIshConfig (
+ IN CONST PCH_ISH_CONFIG *IshConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH ISH Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " ISH Enabled = %x\n", IshConfig->Enable));
+ DEBUG ((DEBUG_INFO, " SPI GPIO Assigned = %x\n", IshConfig->SpiGpioAssign));
+ DEBUG ((DEBUG_INFO, " UART0 GPIO Assigned = %x\n", IshConfig->Uart0GpioAssign));
+ DEBUG ((DEBUG_INFO, " UART1 GPIO Assigned = %x\n", IshConfig->Uart1GpioAssign));
+ DEBUG ((DEBUG_INFO, " I2C0 GPIO Assigned = %x\n", IshConfig->I2c0GpioAssign));
+ DEBUG ((DEBUG_INFO, " I2C1 GPIO Assigned = %x\n", IshConfig->I2c1GpioAssign));
+ DEBUG ((DEBUG_INFO, " I2C2 GPIO Assigned = %x\n", IshConfig->I2c2GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_0 GPIO Assigned = %x\n", IshConfig->Gp0GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_1 GPIO Assigned = %x\n", IshConfig->Gp1GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_2 GPIO Assigned = %x\n", IshConfig->Gp2GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_3 GPIO Assigned = %x\n", IshConfig->Gp3GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_4 GPIO Assigned = %x\n", IshConfig->Gp4GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_5 GPIO Assigned = %x\n", IshConfig->Gp5GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_6 GPIO Assigned = %x\n", IshConfig->Gp6GpioAssign));
+ DEBUG ((DEBUG_INFO, " GP_7 GPIO Assigned = %x\n", IshConfig->Gp7GpioAssign));
+}
+
+/**
+ Print PCH_FLASH_PROTECTION_CONFIG and serial out.
+
+ @param[in] FlashProtectConfig Pointer to a PCH_FLASH_PROTECTION_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintFlashProtectionConfig (
+ IN CONST PCH_FLASH_PROTECTION_CONFIG *FlashProtectConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH Flash Protection Config ------------------\n"));
+ for (Index = 0; Index < PCH_FLASH_PROTECTED_RANGES; ++Index) {
+ DEBUG ((DEBUG_INFO, " WriteProtectionEnable[%d]= %x\n", Index, FlashProtectConfig->ProtectRange[Index].WriteProtectionEnable));
+ DEBUG ((DEBUG_INFO, " ReadProtectionEnable[%d]= %x\n", Index, FlashProtectConfig->ProtectRange[Index].ReadProtectionEnable));
+ DEBUG ((DEBUG_INFO, " ProtectedRangeLimit[%d]= %x\n", Index, FlashProtectConfig->ProtectRange[Index].ProtectedRangeLimit));
+ DEBUG ((DEBUG_INFO, " ProtectedRangeBase[%d]= %x\n", Index, FlashProtectConfig->ProtectRange[Index].ProtectedRangeBase));
+ }
+}
+
+/**
+ Print PCH_P2SB_CONFIG and serial out.
+
+ @param[in] P2sbConfig Pointer to a PCH_P2SB_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintP2sbConfig (
+ IN CONST PCH_P2SB_CONFIG *P2sbConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH P2SB Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "SbiUnlock= %x\n", P2sbConfig->SbiUnlock));
+ DEBUG ((DEBUG_INFO, "SbAccessUnlock= %x\n", P2sbConfig->SbAccessUnlock));
+}
+
+/**
+ Print PCH_SPI_CONFIG and serial out.
+
+ @param[in] SpiConfig Pointer to a PCH_SPI_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSpiConfig (
+ IN CONST PCH_SPI_CONFIG *SpiConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH SPI Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "ShowSpiController= %x\n", SpiConfig->ShowSpiController));
+}
+
+/**
+ Print PCH_ESPI_CONFIG.
+
+ @param[in] EspiConfig Pointer to a PCH_ESPI_CONFIG that provides the eSPI setting
+
+**/
+VOID
+PchPrintEspiConfig (
+ IN CONST PCH_ESPI_CONFIG *EspiConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH eSPI Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " BME for Master and Slave Enabled %x\n", EspiConfig->BmeMasterSlaveEnabled));
+}
+
+/**
+ Print whole PCH config blocks and serial out.
+
+ @param[in] SiPolicyPpi The RC Policy PPI instance
+
+**/
+VOID
+PchPrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ EFI_STATUS Status;
+ PCH_GENERAL_CONFIG *PchGeneralConfig;
+ PCH_PCIE_CONFIG *PcieRpConfig;
+ PCH_SATA_CONFIG *SataConfig;
+ PCH_IOAPIC_CONFIG *IoApicConfig;
+ PCH_CIO2_CONFIG *Cio2Config;
+ PCH_DMI_CONFIG *DmiConfig;
+ PCH_FLASH_PROTECTION_CONFIG *FlashProtectionConfig;
+ PCH_HDAUDIO_CONFIG *HdAudioConfig;
+ PCH_INTERRUPT_CONFIG *InterruptConfig;
+ PCH_ISH_CONFIG *IshConfig;
+ PCH_LAN_CONFIG *LanConfig;
+ PCH_P2SB_CONFIG *P2sbConfig;
+ PCH_LOCK_DOWN_CONFIG *LockDownConfig;
+ PCH_PM_CONFIG *PmConfig;
+ PCH_PORT61H_SMM_CONFIG *Port61hConfig;
+ PCH_SCS_CONFIG *ScsConfig;
+ PCH_SERIAL_IO_CONFIG *SerialIoConfig;
+ PCH_LPC_SIRQ_CONFIG *SerialIrqConfig;
+ PCH_SPI_CONFIG *SpiConfig;
+ PCH_THERMAL_CONFIG *ThermalConfig;
+ PCH_USB_CONFIG *UsbConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPchGeneralConfigGuid, (VOID *) &PchGeneralConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPcieRpConfigGuid, (VOID *) &PcieRpConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSataConfigGuid, (VOID *) &SataConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gIoApicConfigGuid, (VOID *) &IoApicConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCio2ConfigGuid, (VOID *) &Cio2Config);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gDmiConfigGuid, (VOID *) &DmiConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gFlashProtectionConfigGuid, (VOID *) &FlashProtectionConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gHdAudioConfigGuid, (VOID *) &HdAudioConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gInterruptConfigGuid, (VOID *) &InterruptConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gIshConfigGuid, (VOID *) &IshConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gLanConfigGuid, (VOID *) &LanConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gLockDownConfigGuid, (VOID *) &LockDownConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gP2sbConfigGuid, (VOID *) &P2sbConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPmConfigGuid, (VOID *) &PmConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gPort61ConfigGuid, (VOID *) &Port61hConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gScsConfigGuid, (VOID *) &ScsConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSerialIoConfigGuid, (VOID *) &SerialIoConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSerialIrqConfigGuid, (VOID *) &SerialIrqConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gSpiConfigGuid, (VOID *) &SpiConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gThermalConfigGuid, (VOID *) &ThermalConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gUsbConfigGuid, (VOID *) &UsbConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Print Policy Start ------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision= %x\n", SiPolicyPpi->TableHeader.Header.Revision));
+
+ PchPrintGeneralConfig (PchGeneralConfig);
+ PchPrintPcieConfig (PcieRpConfig);
+ PchPrintSataConfig (SataConfig);
+ PchPrintUsbConfig (UsbConfig);
+ PchPrintIoApicConfig (IoApicConfig);
+ PchPrintHdAudioConfig (HdAudioConfig);
+ PchPrintLanConfig (LanConfig);
+ PchPrintLockDownConfig (LockDownConfig);
+ PchPrintThermalConfig (ThermalConfig);
+ PchPrintPmConfig (PmConfig);
+ PchPrintDmiConfig (DmiConfig);
+ PchPrintSerialIrqConfig (SerialIrqConfig);
+ PchPrintSerialIoConfig (SerialIoConfig);
+ PchPrintInterruptConfig (InterruptConfig);
+ PchPrintCio2Config (Cio2Config);
+ PchPrintPort61hSmmConfig (Port61hConfig);
+ PchPrintScsConfig (ScsConfig);
+ PchPrintIshConfig (IshConfig);
+ PchPrintFlashProtectionConfig (FlashProtectionConfig);
+ PchPrintP2sbConfig (P2sbConfig);
+ PchPrintSpiConfig (SpiConfig);
+
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Print Policy End --------------------------\n"));
+ DEBUG_CODE_END ();
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePolicyLib.c
new file mode 100644
index 0000000000..4e57b72d6e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePolicyLib.c
@@ -0,0 +1,223 @@
+/** @file
+ This file is to load sample board policy.
+
+Copyright (c) 2017, 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 that 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 "PeiPchPolicyLibrary.h"
+
+/*
+ Apply sample board PCH specific default settings
+
+ @param[in] SiPolicy The pointer to SI Policy PPI instance
+*/
+VOID
+EFIAPI
+PchLoadSamplePolicy (
+ IN SI_POLICY_PPI *SiPolicy
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ PCH_PCIE_CONFIG *PcieRpConfig;
+ PCH_IOAPIC_CONFIG *IoApicConfig;
+ PCH_CIO2_CONFIG *Cio2Config;
+ PCH_DMI_CONFIG *DmiConfig;
+ PCH_LAN_CONFIG *LanConfig;
+ PCH_LOCK_DOWN_CONFIG *LockDownConfig;
+ PCH_PM_CONFIG *PmConfig;
+ PCH_SCS_CONFIG *ScsConfig;
+ PCH_SERIAL_IO_CONFIG *SerialIoConfig;
+ PCH_THERMAL_CONFIG *ThermalConfig;
+ PCH_USB_CONFIG *UsbConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gPcieRpConfigGuid, (VOID *) &PcieRpConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gIoApicConfigGuid, (VOID *) &IoApicConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gCio2ConfigGuid, (VOID *) &Cio2Config);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gDmiConfigGuid, (VOID *) &DmiConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gLanConfigGuid, (VOID *) &LanConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gLockDownConfigGuid, (VOID *) &LockDownConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gPmConfigGuid, (VOID *) &PmConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gScsConfigGuid, (VOID *) &ScsConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gSerialIoConfigGuid, (VOID *) &SerialIoConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gThermalConfigGuid, (VOID *) &ThermalConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPolicy, &gUsbConfigGuid, (VOID *) &UsbConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // PCIE RP
+ //
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ PcieRpConfig->RootPort[Index].ClkReqDetect = TRUE;
+ PcieRpConfig->RootPort[Index].AdvancedErrorReporting = TRUE;
+ PcieRpConfig->RootPort[Index].Gen3EqPh3Method = PchPcieEqSoftware;
+ }
+
+ PcieRpConfig->RootPort[0].ClkReqSupported = TRUE;
+ PcieRpConfig->RootPort[0].ClkReqNumber = 2;
+
+ PcieRpConfig->RootPort[4].ClkReqSupported = TRUE;
+ PcieRpConfig->RootPort[4].ClkReqNumber = 3;
+
+ PcieRpConfig->RootPort[5].ClkReqSupported = TRUE;
+ PcieRpConfig->RootPort[5].ClkReqNumber = 1;
+
+ PcieRpConfig->RootPort[8].ClkReqSupported = TRUE;
+ PcieRpConfig->RootPort[8].ClkReqNumber = 5;
+
+ PcieRpConfig->RootPort[9].ClkReqSupported = TRUE;
+ PcieRpConfig->RootPort[9].ClkReqNumber = 4;
+
+ //
+ // USB
+ //
+ UsbConfig->PortUsb20[0].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[0].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[0].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[0].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[1].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[1].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[1].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[1].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[2].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[2].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[2].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[2].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[3].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[3].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[3].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[3].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[4].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[4].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[4].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[4].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[5].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[5].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[5].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[5].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[6].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[6].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[6].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[6].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[7].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[7].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[7].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[7].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[8].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[8].Afe.Txiset = 5;
+ UsbConfig->PortUsb20[8].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[8].Afe.Pehalfbit = 1;
+
+ UsbConfig->PortUsb20[9].Afe.Petxiset = 7;
+ UsbConfig->PortUsb20[9].Afe.Txiset = 0;
+ UsbConfig->PortUsb20[9].Afe.Predeemp = 2;
+ UsbConfig->PortUsb20[9].Afe.Pehalfbit = 1;
+
+ // OC Map for USB2 Ports
+ UsbConfig->PortUsb20[ 0].OverCurrentPin = PchUsbOverCurrentPin0;
+ UsbConfig->PortUsb20[ 1].OverCurrentPin = PchUsbOverCurrentPin2;
+ UsbConfig->PortUsb20[ 2].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[ 3].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[ 4].OverCurrentPin = PchUsbOverCurrentPin2;
+ UsbConfig->PortUsb20[ 5].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[ 6].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[ 7].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[ 8].OverCurrentPin = PchUsbOverCurrentPin1;
+ UsbConfig->PortUsb20[ 9].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[10].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[11].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[12].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb20[13].OverCurrentPin = PchUsbOverCurrentPinSkip;
+
+ // OC Map for USB3 Ports
+ UsbConfig->PortUsb30[0].OverCurrentPin = PchUsbOverCurrentPin0;
+ UsbConfig->PortUsb30[1].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb30[2].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb30[3].OverCurrentPin = PchUsbOverCurrentPin1;
+ UsbConfig->PortUsb30[4].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ UsbConfig->PortUsb30[5].OverCurrentPin = PchUsbOverCurrentPinSkip;
+
+ UsbConfig->SsicConfig.SsicPort[0].Enable = TRUE;
+ UsbConfig->SsicConfig.SsicPort[1].Enable = TRUE;
+
+ //
+ // IOAPIC
+ //
+ IoApicConfig->BdfValid = 1;
+ IoApicConfig->BusNumber = 0xF0;
+ IoApicConfig->DeviceNumber = 0x1F;
+ IoApicConfig->FunctionNumber = 0;
+
+ //
+ // LAN
+ //
+ LanConfig->K1OffEnable = TRUE;
+ LanConfig->ClkReqSupported = TRUE;
+ LanConfig->ClkReqNumber = 3;
+
+ //
+ // PM CONFIG
+ //
+ PmConfig->LpcClockRun = TRUE;
+
+ //
+ // DMI
+ //
+ DmiConfig->PwrOptEnable = TRUE;
+
+ //
+ // SERIALIO
+ //
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C0] = PchSerialIoPci;
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C1] = PchSerialIoPci;
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C2] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C3] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C4] = PchSerialIoAcpiHidden;
+ SerialIoConfig->DevMode[PchSerialIoIndexI2C5] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexSpi0] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexSpi1] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexUart0] = PchSerialIoPci;
+ SerialIoConfig->DevMode[PchSerialIoIndexUart1] = PchSerialIoDisabled;
+ SerialIoConfig->DevMode[PchSerialIoIndexUart2] = PchSerialIoLegacyUart;
+
+ SerialIoConfig->I2cVoltage[2] = 1;
+ SerialIoConfig->I2cVoltage[3] = 1;
+
+ SerialIoConfig->SpiCsPolarity[0] = 1;
+
+ SerialIoConfig->UartHwFlowCtrl[0] = 1;
+ SerialIoConfig->UartHwFlowCtrl[1] = 1;
+ SerialIoConfig->UartHwFlowCtrl[2] = 1;
+
+
+ //
+ // SCS
+ //
+ ScsConfig->ScsEmmcHs400Enabled = TRUE;
+ ScsConfig->ScsEmmcHs400TuningRequired = TRUE;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePreMemPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePreMemPolicyLib.c
new file mode 100644
index 0000000000..fcefd76e8e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PchSamplePreMemPolicyLib.c
@@ -0,0 +1,80 @@
+/** @file
+ This file is to load sample board policy.
+
+Copyright (c) 2017, 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 that 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 "PeiPchPolicyLibrary.h"
+
+/*
+ Apply sample board PCH specific default settings
+
+ @param[in] SiPreMemPolicy The pointer to SI PREMEM Policy PPI instance
+*/
+VOID
+EFIAPI
+PchLoadSamplePreMemPolicy (
+ IN SI_PREMEM_POLICY_PPI *SiPreMemPolicy
+ )
+{
+ EFI_STATUS Status;
+ PCH_TRACE_HUB_PREMEM_CONFIG *TraceHubPreMemConfig;
+ PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig;
+ PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig;
+
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gTraceHubPreMemConfigGuid, (VOID *) &TraceHubPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gHsioPciePreMemConfigGuid, (VOID *) &HsioPciePreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicy, &gHsioSataPreMemConfigGuid, (VOID *) &HsioSataPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // TRACEHUB
+ //
+ TraceHubPreMemConfig->MemReg0Size = 0x100000; // 1MB
+ TraceHubPreMemConfig->MemReg1Size = 0x100000; // 1MB
+
+ //
+ // HSIO PCIE
+ //
+ HsioPciePreMemConfig->Lane[0].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[0].HsioRxSetCtle = 6;
+ HsioPciePreMemConfig->Lane[1].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[1].HsioRxSetCtle = 6;
+ HsioPciePreMemConfig->Lane[2].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[2].HsioRxSetCtle = 6;
+ HsioPciePreMemConfig->Lane[3].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[3].HsioRxSetCtle = 6;
+ HsioPciePreMemConfig->Lane[5].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[5].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->Lane[7].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[7].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->Lane[8].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[8].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->Lane[9].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[9].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->Lane[10].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[10].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->Lane[11].HsioRxSetCtleEnable = TRUE;
+ HsioPciePreMemConfig->Lane[11].HsioRxSetCtle = 8;
+ HsioPciePreMemConfig->PciePllSsc = 0xFF;
+
+ //
+ // HSIO SATA
+ //
+ HsioSataPreMemConfig->PortLane[0].HsioRxGen3EqBoostMagEnable = TRUE;
+ HsioSataPreMemConfig->PortLane[0].HsioRxGen3EqBoostMag = 4;
+ HsioSataPreMemConfig->PortLane[0].HsioTxGen1DownscaleAmpEnable = TRUE;
+ HsioSataPreMemConfig->PortLane[0].HsioTxGen1DownscaleAmp = 0x2C;
+ HsioSataPreMemConfig->PortLane[0].HsioTxGen2DownscaleAmpEnable = 0;
+ HsioSataPreMemConfig->PortLane[0].HsioTxGen2DownscaleAmp = 0x38;
+
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c
new file mode 100644
index 0000000000..f0f9f33f71
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.c
@@ -0,0 +1,892 @@
+/** @file
+ This file is PeiPchPolicy library.
+
+Copyright (c) 2017, 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 that 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 "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));
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf
new file mode 100644
index 0000000000..d4d4ac1e54
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf
@@ -0,0 +1,93 @@
+## @file
+# Component description file for the PeiPchPolicy libbrary.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiPchPolicyLib
+FILE_GUID = BB1AC992-B2CA-4744-84B7-915C185576C5
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = PchPolicyLib
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+PcdLib
+PeiServicesLib
+BaseMemoryLib
+MemoryAllocationLib
+PchInfoLib
+ConfigBlockLib
+SiConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress
+gSiPkgTokenSpaceGuid.PcdSmbusBaseAddress
+gSiPkgTokenSpaceGuid.PcdSerialIoUartDebugEnable
+gSiPkgTokenSpaceGuid.PcdSerialIoUartNumber
+
+
+[Sources]
+PeiPchPolicyLib.c
+PeiPchPolicyLibrary.h
+PchPrintPolicy.c
+PchSamplePolicyLib.c
+PeiPchPreMemPolicyLib.c
+PchPreMemPrintPolicy.c
+PchSamplePreMemPolicyLib.c
+
+
+[Guids]
+gPchGeneralConfigGuid ## CONSUMES
+gPcieRpConfigGuid ## CONSUMES
+gSataConfigGuid ## CONSUMES
+gIoApicConfigGuid ## CONSUMES
+gCio2ConfigGuid ## CONSUMES
+gDmiConfigGuid ## CONSUMES
+gFlashProtectionConfigGuid ## CONSUMES
+gHdAudioConfigGuid ## CONSUMES
+gInterruptConfigGuid ## CONSUMES
+gIshConfigGuid ## CONSUMES
+gLanConfigGuid ## CONSUMES
+gLockDownConfigGuid ## CONSUMES
+gP2sbConfigGuid ## CONSUMES
+gPmConfigGuid ## CONSUMES
+gPort61ConfigGuid ## CONSUMES
+gScsConfigGuid ## CONSUMES
+gSerialIoConfigGuid ## CONSUMES
+gSerialIrqConfigGuid ## CONSUMES
+gSpiConfigGuid ## CONSUMES
+gEspiConfigGuid ## CONSUMES
+gThermalConfigGuid ## CONSUMES
+gUsbConfigGuid ## CONSUMES
+gPchGeneralPreMemConfigGuid ## COMSUMES
+gDciPreMemConfigGuid ## CONSUMES
+gWatchDogPreMemConfigGuid ## CONSUMES
+gTraceHubPreMemConfigGuid ## CONSUMES
+gHpetPreMemConfigGuid ## CONSUMES
+gSmbusPreMemConfigGuid ## CONSUMES
+gLpcPreMemConfigGuid ## CONSUMES
+gHsioPciePreMemConfigGuid ## CONSUMES
+gHsioSataPreMemConfigGuid ## CONSUMES
+gHsioPreMemConfigGuid ## CONSUMES
+gPcieRpPreMemConfigGuid ## CONSUMES
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h
new file mode 100644
index 0000000000..9be618d38a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h
@@ -0,0 +1,32 @@
+/** @file
+ Header file for the PeiPchPolicy library.
+
+Copyright (c) 2017, 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 that 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 _PEI_PCH_POLICY_LIBRARY_H_
+#define _PEI_PCH_POLICY_LIBRARY_H_
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/SiConfigBlockLib.h>
+#include <Library/PchInfoLib.h>
+#include <Ppi/SiPolicy.h>
+#include <PchAccess.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/PchPolicyLib.h>
+
+#define PCH_HPET_BASE_ADDRESS 0xFED00000
+
+#endif // _PEI_PCH_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c
new file mode 100644
index 0000000000..5480cf3d5c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchPolicyLib/PeiPchPreMemPolicyLib.c
@@ -0,0 +1,306 @@
+/** @file
+ This file is PeiPchPreMemPolicy library.
+
+Copyright (c) 2017, 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 that 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 "PeiPchPolicyLibrary.h"
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPchGeneralPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig;
+ PchGeneralPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "PchGeneralPreMemConfig->Header.GuidHob.Name = %g\n", &PchGeneralPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "PchGeneralPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PchGeneralPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ PCH general premem configuration
+ ********************************/
+ //
+ // Default SVID SDID configuration
+ //
+ PchGeneralPreMemConfig->AcpiBase = PcdGet16 (PcdAcpiBaseAddress);
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadDciPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_DCI_PREMEM_CONFIG *DciPreMemConfig;
+ DciPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "DciPreMemConfig->Header.GuidHob.Name = %g\n", &DciPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "DciPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", DciPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ DCI Configuration
+ ********************************/
+ DciPreMemConfig->DciAutoDetect = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadWatchDogPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_WDT_PREMEM_CONFIG *WdtPreMemConfig;
+ WdtPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "WdtPreMemConfig->Header.GuidHob.Name = %g\n", &WdtPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "WdtPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", WdtPreMemConfig->Header.GuidHob.Header.HobLength));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadTraceHubPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_TRACE_HUB_PREMEM_CONFIG *TraceHubPreMemConfig;
+ TraceHubPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "TraceHubPreMemConfig->Header.GuidHob.Name = %g\n", &TraceHubPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "TraceHubPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", TraceHubPreMemConfig->Header.GuidHob.Header.HobLength));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadHpetPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_HPET_PREMEM_CONFIG *HpetPreMemConfig;
+ HpetPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HpetPreMemConfig->Header.GuidHob.Name = %g\n", &HpetPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "HpetPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HpetPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ HPET Configuration
+ ********************************/
+ HpetPreMemConfig->Enable = TRUE;
+ HpetPreMemConfig->Base = PCH_HPET_BASE_ADDRESS;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSmbusRsvdAddresses[] = {
+ 0xA0,
+ 0xA2,
+ 0xA4,
+ 0xA6
+};
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadSmbusPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_SMBUS_PREMEM_CONFIG *SmbusPreMemConfig;
+ SmbusPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "SmbusPreMemConfig->Header.GuidHob.Name = %g\n", &SmbusPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "SmbusPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", SmbusPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ SMBus configuration
+ ********************************/
+ SmbusPreMemConfig->Enable = TRUE;
+ SmbusPreMemConfig->SpdWriteDisable = TRUE;
+ SmbusPreMemConfig->SmbusIoBase = PcdGet16 (PcdSmbusBaseAddress);
+ ASSERT (sizeof (mSmbusRsvdAddresses) <= PCH_MAX_SMBUS_RESERVED_ADDRESS);
+ SmbusPreMemConfig->NumRsvdSmbusAddresses = sizeof (mSmbusRsvdAddresses);
+ CopyMem (
+ SmbusPreMemConfig->RsvdSmbusAddressTable,
+ mSmbusRsvdAddresses,
+ sizeof (mSmbusRsvdAddresses)
+ );
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadLpcPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_LPC_PREMEM_CONFIG *LpcPreMemConfig;
+ LpcPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.GuidHob.Name = %g\n", &LpcPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", LpcPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ /********************************
+ LPC Configuration
+ ********************************/
+ LpcPreMemConfig->EnhancePort8xhDecoding = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadHsioPciePreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_HSIO_PCIE_PREMEM_CONFIG *HsioPciePreMemConfig;
+ HsioPciePreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HsioPciePreMemConfig->Header.GuidHob.Name = %g\n", &HsioPciePreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "HsioPciePreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HsioPciePreMemConfig->Header.GuidHob.Header.HobLength));
+
+ HsioPciePreMemConfig->PciePllSsc = 0xFF;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadHsioSataPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_HSIO_SATA_PREMEM_CONFIG *HsioSataPreMemConfig;
+ HsioSataPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HsioSataPreMemConfig->Header.GuidHob.Name = %g\n", &HsioSataPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "HsioSataPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HsioSataPreMemConfig->Header.GuidHob.Header.HobLength));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadHsioPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_HSIO_PREMEM_CONFIG *HsioPreMemConfig;
+ HsioPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HsioPreMemConfig->Header.GuidHob.Name = %g\n", &HsioPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "HsioPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HsioPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ HsioPreMemConfig->ChipsetInitMessage = TRUE;
+ HsioPreMemConfig->BypassPhySyncReset = FALSE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPcieRpPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCH_PCIE_RP_PREMEM_CONFIG *PcieRpPreMemConfig;
+ UINT32 RpIndex;
+
+ PcieRpPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Name = %g\n", &PcieRpPreMemConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "PcieRpPreMemConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PcieRpPreMemConfig->Header.GuidHob.Header.HobLength));
+
+ for (RpIndex = 0; RpIndex < GetPchMaxPciePortNum (); RpIndex ++) {
+ PcieRpPreMemConfig->RpEnabledMask |= (UINT32) (1 << RpIndex);
+ }
+}
+
+
+static COMPONENT_BLOCK_ENTRY mPchIpBlocksPreMem [] = {
+ {&gPchGeneralPreMemConfigGuid, sizeof (PCH_GENERAL_PREMEM_CONFIG), PCH_GENERAL_PREMEM_CONFIG_REVISION, LoadPchGeneralPreMemConfigDefault},
+ {&gDciPreMemConfigGuid, sizeof (PCH_DCI_PREMEM_CONFIG), DCI_PREMEM_CONFIG_REVISION, LoadDciPreMemConfigDefault},
+ {&gWatchDogPreMemConfigGuid, sizeof (PCH_WDT_PREMEM_CONFIG), WATCH_DOG_PREMEM_CONFIG_REVISION, LoadWatchDogPreMemConfigDefault},
+ {&gTraceHubPreMemConfigGuid, sizeof (PCH_TRACE_HUB_PREMEM_CONFIG), TRACEHUB_PREMEM_CONFIG_REVISION, LoadTraceHubPreMemConfigDefault},
+ {&gHpetPreMemConfigGuid, sizeof (PCH_HPET_PREMEM_CONFIG), HPET_PREMEM_CONFIG_REVISION, LoadHpetPreMemConfigDefault},
+ {&gSmbusPreMemConfigGuid, sizeof (PCH_SMBUS_PREMEM_CONFIG), SMBUS_PREMEM_CONFIG_REVISION, LoadSmbusPreMemConfigDefault},
+ {&gLpcPreMemConfigGuid, sizeof (PCH_LPC_PREMEM_CONFIG), LPC_PREMEM_CONFIG_REVISION, LoadLpcPreMemConfigDefault},
+ {&gHsioPciePreMemConfigGuid, sizeof (PCH_HSIO_PCIE_PREMEM_CONFIG), HSIO_PCIE_PREMEM_CONFIG_REVISION, LoadHsioPciePreMemConfigDefault},
+ {&gHsioSataPreMemConfigGuid, sizeof (PCH_HSIO_SATA_PREMEM_CONFIG), HSIO_SATA_PREMEM_CONFIG_REVISION, LoadHsioSataPreMemConfigDefault},
+ {&gHsioPreMemConfigGuid, sizeof (PCH_HSIO_PREMEM_CONFIG), HSIO_PREMEM_CONFIG_REVISION, LoadHsioPreMemConfigDefault},
+ {&gPcieRpPreMemConfigGuid, sizeof (PCH_PCIE_RP_PREMEM_CONFIG), PCIE_RP_PREMEM_CONFIG_REVISION, LoadPcieRpPreMemConfigDefault},
+
+};
+
+/**
+ Get PCH PREMEM config block table total size.
+
+ @retval Size of PCH PREMEM config block table
+**/
+UINT16
+EFIAPI
+PchGetPreMemConfigBlockTotalSize (
+ VOID
+ )
+{
+ return GetComponentConfigBlockTotalSize (&mPchIpBlocksPreMem[0], sizeof (mPchIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
+
+/**
+ PchAddPreMemConfigBlocks add all PCH PREMEM config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add PCH PREMEM config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+PchAddPreMemConfigBlocks (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ DEBUG ((DEBUG_INFO, "PCH AddPreMemConfigBlocks\n"));
+
+ return AddComponentConfigBlocks (ConfigBlockTableAddress, &mPchIpBlocksPreMem[0], sizeof (mPchIpBlocksPreMem) / sizeof (COMPONENT_BLOCK_ENTRY));
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c
new file mode 100644
index 0000000000..79f3f779dc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PchReset.c
@@ -0,0 +1,194 @@
+/** @file
+ PCH RESET PEIM DRIVER.
+
+Copyright (c) 2017, 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 that 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 <PiPei.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <PchAccess.h>
+#include <Ppi/Reset2.h>
+#include <Ppi/PchReset.h>
+#include <Library/ResetSystemLib.h>
+#include <PchResetPlatformSpecific.h>
+
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ );
+
+
+/**
+ Resets the entire platform.
+
+ @param[in] ResetType UEFI defined reset type.
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetSystem (
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ switch (ResetType) {
+ case EfiResetWarm:
+ ResetWarm ();
+ break;
+
+ case EfiResetCold:
+ ResetCold ();
+ break;
+
+ case EfiResetShutdown:
+ ResetShutdown ();
+ return;
+
+ case EfiResetPlatformSpecific:
+ ResetPlatformSpecific (ResetStatus, DataSize, ResetData);
+ return;
+
+ default:
+ return;
+ }
+
+ //
+ // Given we should have reset getting here would be bad
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Execute Pch Reset from the host controller.
+
+ @param[in] This Pointer to the PCH_RESET_PPI instance.
+ @param[in] PchResetType Pch Reset Types which includes PchColdReset, PchWarmReset,
+ PchShutdownReset, PchGlobalReset
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER If ResetType is invalid.
+**/
+EFI_STATUS
+EFIAPI
+Reset (
+ IN PCH_RESET_PPI *This,
+ IN PCH_RESET_TYPE PchResetType
+ )
+{
+ PCH_RESET_DATA ResetData;
+
+ switch (PchResetType) {
+ case PchColdReset:
+ ResetCold();
+ break;
+
+ case PchWarmReset:
+ ResetWarm();
+ break;
+
+ case PchShutdownReset:
+ ResetShutdown();
+ break;
+
+ case PchGlobalReset:
+ CopyMem (&ResetData.Guid, &gPchGlobalResetGuid, sizeof (EFI_GUID));
+ StrCpyS (ResetData.Description, PCH_RESET_DATA_STRING_MAX_LENGTH, PCH_PLATFORM_SPECIFIC_RESET_STRING);
+ ResetPlatformSpecific (EFI_SUCCESS, sizeof (PCH_RESET_DATA), &ResetData);
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize PCH Reset APIs
+
+ @retval EFI_SUCCESS APIs are installed successfully
+ @retval EFI_OUT_OF_RESOURCES Can't allocate pool
+**/
+EFI_STATUS
+EFIAPI
+PchInitializeReset (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PCH_RESET_PPI *PeiPchResetPpi;
+ EFI_PEI_PPI_DESCRIPTOR *PeiPchResetDescriptor;
+ EFI_PEI_RESET2_PPI *EfiPeiReset2Ppi;
+ EFI_PEI_PPI_DESCRIPTOR *EfiPeiReset2Descriptor;
+
+ DEBUG ((DEBUG_INFO, "PchInitializeReset() Start\n"));
+
+ PeiPchResetDescriptor = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ PeiPchResetPpi = (PCH_RESET_PPI *) AllocateZeroPool (sizeof (PCH_RESET_PPI));
+ if ((PeiPchResetDescriptor == NULL) ||
+ (PeiPchResetPpi == NULL)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ///
+ /// Initialize the Reset ppi instance
+ ///
+ PeiPchResetPpi->Reset = Reset;
+ PeiPchResetDescriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ PeiPchResetDescriptor->Guid = &gPchResetPpiGuid;
+ PeiPchResetDescriptor->Ppi = PeiPchResetPpi;
+
+ ///
+ /// Install the PCH RESET PPI
+ ///
+ Status = PeiServicesInstallPpi (PeiPchResetDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ EfiPeiReset2Descriptor = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ EfiPeiReset2Ppi = (EFI_PEI_RESET2_PPI *) AllocateZeroPool (sizeof (EFI_PEI_RESET2_PPI));
+ if ((EfiPeiReset2Descriptor == NULL) ||
+ (EfiPeiReset2Ppi == NULL)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ///
+ /// Initialize the EFI Reset2 ppi instance
+ ///
+ EfiPeiReset2Ppi->ResetSystem = ResetSystem;
+
+ EfiPeiReset2Descriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ EfiPeiReset2Descriptor->Guid = &gEfiPeiReset2PpiGuid;
+ EfiPeiReset2Descriptor->Ppi = EfiPeiReset2Ppi;
+
+ Status = PeiServicesInstallPpi (EfiPeiReset2Descriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "PchInitializeReset() End\n"));
+
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLib.inf
new file mode 100644
index 0000000000..b03a986313
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiPchResetLib/PeiPchResetLib.inf
@@ -0,0 +1,48 @@
+## @file
+# Component description file for PCH Reset Lib Pei Phase
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiPchResetLib
+FILE_GUID = DB91FFF0-5B99-4A88-9EC8-183A2106DCA2
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = PchResetLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+DebugLib
+PeiServicesLib
+PeiServicesTablePointerLib
+ResetSystemLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PchReset.c
+
+[Ppis]
+gPchResetPpiGuid ## PRODUCES
+gEfiPeiReset2PpiGuid ## PRODUCES
+gPchResetCallbackPpiGuid ## CONSUMES
+
+[Guids]
+gPchGlobalResetGuid
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c
new file mode 100644
index 0000000000..6a017a40a7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.c
@@ -0,0 +1,286 @@
+/** @file
+ System reset library services.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <PchAccess.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchResetLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Ppi/PchReset.h>
+#ifdef FSP_FLAG
+#include <Library/FspCommonLib.h>
+#endif
+/**
+ Dump reset message for debug build readability
+**/
+VOID
+DumpResetMessage (
+ VOID
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINTN Index;
+ //
+ // ******************************
+ // ** SYSTEM REBOOT !!! **
+ // ******************************
+ //
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n** SYSTEM REBOOT !!! **\n"));
+ for (Index = 0; Index < 30; Index++) {
+ DEBUG ((DEBUG_INFO, "*"));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] ResetType Reset Types which includes PowerCycle, GlobalReset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of
+ callback protocol is installed.
+**/
+EFI_STATUS
+PchResetCallback (
+ IN PCH_RESET_TYPE ResetType
+ )
+{
+ EFI_STATUS Status;
+ UINTN Instance;
+ PCH_RESET_CALLBACK_PPI *PchResetCallbackPpi;
+
+ Instance = 0;
+ do {
+ Status = PeiServicesLocatePpi (
+ &gPchResetCallbackPpiGuid,
+ Instance,
+ NULL,
+ (VOID **) &PchResetCallbackPpi
+ );
+
+ switch (Status) {
+ case EFI_SUCCESS:
+ PchResetCallbackPpi->ResetCallback (ResetType);
+ break;
+ case EFI_NOT_FOUND:
+ break;
+ default:
+ ASSERT_EFI_ERROR (Status);
+ break;
+ }
+ ++Instance;
+ } while (Status == EFI_SUCCESS);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback PPI
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetCold);
+#ifdef FSP_FLAG
+ FspApiReturnStatusReset (FSP_STATUS_RESET_REQUIRED_COLD);
+#endif
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ //
+ // Loop through callback functions of PchResetCallback PPI
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetWarm);
+#ifdef FSP_FLAG
+ FspApiReturnStatusReset (FSP_STATUS_RESET_REQUIRED_WARM);
+#endif
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_HARDRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ UINT16 ABase;
+ UINT32 Data32;
+
+ //
+ // Loop through callback functions of PchResetCallback PPI
+ //
+ PchResetCallback ((PCH_RESET_TYPE) EfiResetShutdown);
+
+ PchAcpiBaseGet (&ABase);
+ ///
+ /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system from S5
+ ///
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_GPE0_EN_127_96), 0);
+
+ ///
+ /// Secondly, PwrSts register must be cleared
+ ///
+ /// Write a "1" to bit[8] of power button status register at
+ /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
+ ///
+ IoWrite16 ((UINTN) (ABase + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_PWRBTN);
+
+ ///
+ /// Finally, transform system into S5 sleep state
+ ///
+ Data32 = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT));
+
+ Data32 = (UINT32) ((Data32 &~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S5);
+
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ DumpResetMessage ();
+
+ IoWrite32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT), Data32);
+
+ return;
+}
+
+/**
+ Internal function to execute the required HECI command for GlobalReset,
+ if failed will use PCH Reest.
+
+**/
+STATIC
+VOID
+PeiPchGlobalReset (
+ VOID
+ )
+{
+ UINTN PchPmcBase;
+
+ //
+ // Loop through callback functions of PchResetCallback PPI
+ //
+ PchResetCallback (PchGlobalReset);
+
+#ifdef FSP_FLAG
+ FspApiReturnStatusReset (FSP_STATUS_RESET_REQUIRED_3);
+#endif
+
+ PchPmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ //
+ // PCH BIOS Spec Section 4.6 GPIO Reset Requirement
+ //
+ MmioOr32 (PchPmcBase + R_PCH_PMC_ETR3, (UINT32) B_PCH_PMC_ETR3_CF9GR);
+
+ DumpResetMessage ();
+
+ IoWrite8 (R_PCH_RST_CNT, V_PCH_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state for platform specific.
+
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ EFI_GUID *GuidPtr;
+
+ if (ResetData == NULL) {
+ DEBUG ((DEBUG_ERROR, "[PeiResetSystemLib] ResetData is not available.\n"));
+ return;
+ }
+ GuidPtr = (EFI_GUID *) ((UINT8 *) ResetData + DataSize - sizeof (EFI_GUID));
+ if (CompareGuid (GuidPtr, &gPchGlobalResetGuid)) {
+ PeiPchGlobalReset();
+ } else {
+ return;
+ }
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ ASSERT (FALSE);
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf
new file mode 100644
index 0000000000..a259bdf6ec
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLib.inf
@@ -0,0 +1,54 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiResetSystemLib
+FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+DebugLib
+BaseMemoryLib
+PeiServicesLib
+MmPciLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiResetSystemLib.c
+
+
+[Ppis]
+gPchResetCallbackPpiGuid ## CONSUMES
+
+
+[Guids]
+gPchGlobalResetGuid
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLibFsp.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLibFsp.inf
new file mode 100644
index 0000000000..9abb7c2107
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiResetSystemLib/PeiResetSystemLibFsp.inf
@@ -0,0 +1,58 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiResetSystemLib
+FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+PciLib
+BaseLib
+DebugLib
+BaseMemoryLib
+PeiServicesLib
+MmPciLib
+PchCycleDecodingLib
+FspCommonLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+
+[Sources]
+PeiResetSystemLib.c
+
+
+[Ppis]
+gPchResetCallbackPpiGuid ## CONSUMES
+
+
+[Guids]
+gPchGlobalResetGuid
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
new file mode 100644
index 0000000000..c7b3e864eb
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
@@ -0,0 +1,59 @@
+### @file
+# SMM Library instance of Spi Flash Common Library Class
+#
+# Copyright (c) 2017, 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 = 0x00010017
+ BASE_NAME = SmmSpiFlashCommonLib
+ FILE_GUID = 9632D96E-E849-4217-9217-DC500B8AAE47
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_SMM_DRIVER
+ LIBRARY_CLASS = SpiFlashCommonLib|DXE_SMM_DRIVER
+ CONSTRUCTOR = SmmSpiFlashCommonLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ PciLib
+ IoLib
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ SmmServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ MmPciLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+ gSiPkgTokenSpaceGuid.PcdFlashAreaBaseAddress ## CONSUMES
+ gSiPkgTokenSpaceGuid.PcdFlashAreaSize ## CONSUMES
+ gSiPkgTokenSpaceGuid.PcdBiosGuardEnable ## CONSUMES
+
+[Sources]
+ SpiFlashCommonSmmLib.c
+ SpiFlashCommon.c
+
+[Protocols]
+ gPchSmmSpiProtocolGuid ## CONSUMES
+ gSmmBiosGuardProtocolGuid ## CONSUMES
+
+[Depex.X64.DXE_SMM_DRIVER]
+ gPchSmmSpiProtocolGuid
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
new file mode 100644
index 0000000000..d95f51af41
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
@@ -0,0 +1,202 @@
+/** @file
+ Wrap EFI_SPI_PROTOCOL to provide some library level interfaces
+ for module use.
+
+Copyright (c) 2017, 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 that 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 <Library/SpiFlashCommonLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <PchAccess.h>
+#include <Library/MmPciLib.h>
+#include <Protocol/Spi.h>
+
+
+PCH_SPI_PROTOCOL *mSpiProtocol;
+
+//
+// FlashAreaBaseAddress and Size for boottime and runtime usage.
+//
+UINTN mFlashAreaBaseAddress = 0;
+UINTN mFlashAreaSize = 0;
+
+/**
+ Enable block protection on the Serial Flash device.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashLock (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Read NumBytes bytes of data from the address specified by
+ PAddress into Buffer.
+
+ @param[in] Address The starting physical address of the read.
+ @param[in,out] NumBytes On input, the number of bytes to read. On output, the number
+ of bytes actually read.
+ @param[out] Buffer The destination data buffer for the read.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashRead (
+ IN UINTN Address,
+ IN OUT UINT32 *NumBytes,
+ OUT UINT8 *Buffer
+ )
+{
+ ASSERT ((NumBytes != NULL) && (Buffer != NULL));
+ if ((NumBytes == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // This function is implemented specifically for those platforms
+ // at which the SPI device is memory mapped for read. So this
+ // function just do a memory copy for Spi Flash Read.
+ //
+ CopyMem (Buffer, (VOID *) Address, *NumBytes);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write NumBytes bytes of data from Buffer to the address specified by
+ PAddresss.
+
+ @param[in] Address The starting physical address of the write.
+ @param[in,out] NumBytes On input, the number of bytes to write. On output,
+ the actual number of bytes written.
+ @param[in] Buffer The source data buffer for the write.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashWrite (
+ IN UINTN Address,
+ IN OUT UINT32 *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ UINT32 Length;
+ UINT32 RemainingBytes;
+
+ ASSERT ((NumBytes != NULL) && (Buffer != NULL));
+ if ((NumBytes == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (Address >= mFlashAreaBaseAddress);
+
+ Offset = Address - mFlashAreaBaseAddress;
+
+ ASSERT ((*NumBytes + Offset) <= mFlashAreaSize);
+
+ Status = EFI_SUCCESS;
+ RemainingBytes = *NumBytes;
+
+
+ while (RemainingBytes > 0) {
+ if (RemainingBytes > SECTOR_SIZE_4KB) {
+ Length = SECTOR_SIZE_4KB;
+ } else {
+ Length = RemainingBytes;
+ }
+ Status = mSpiProtocol->FlashWrite (
+ mSpiProtocol,
+ FlashRegionBios,
+ (UINT32) Offset,
+ Length,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ RemainingBytes -= Length;
+ Offset += Length;
+ Buffer += Length;
+ }
+
+ //
+ // Actual number of bytes written
+ //
+ *NumBytes -= RemainingBytes;
+
+ return Status;
+}
+
+/**
+ Erase the block starting at Address.
+
+ @param[in] Address The starting physical address of the block to be erased.
+ This library assume that caller garantee that the PAddress
+ is at the starting address of this block.
+ @param[in] NumBytes On input, the number of bytes of the logical block to be erased.
+ On output, the actual number of bytes erased.
+
+ @retval EFI_SUCCESS. Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashBlockErase (
+ IN UINTN Address,
+ IN UINTN *NumBytes
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ UINTN RemainingBytes;
+
+ ASSERT (NumBytes != NULL);
+ if (NumBytes == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (Address >= mFlashAreaBaseAddress);
+
+ Offset = Address - mFlashAreaBaseAddress;
+
+ ASSERT ((*NumBytes % SECTOR_SIZE_4KB) == 0);
+ ASSERT ((*NumBytes + Offset) <= mFlashAreaSize);
+
+ Status = EFI_SUCCESS;
+ RemainingBytes = *NumBytes;
+
+
+ Status = mSpiProtocol->FlashErase (
+ mSpiProtocol,
+ FlashRegionBios,
+ (UINT32) Offset,
+ (UINT32) RemainingBytes
+ );
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c
new file mode 100644
index 0000000000..8d2238dbf1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c
@@ -0,0 +1,60 @@
+/** @file
+ SMM Library instance of SPI Flash Common Library Class
+
+Copyright (c) 2017, 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 that 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 <Library/SpiFlashCommonLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Protocol/Spi.h>
+
+extern PCH_SPI_PROTOCOL *mSpiProtocol;
+
+extern UINTN mFlashAreaBaseAddress;
+extern UINTN mFlashAreaSize;
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library
+ instance.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+ It will ASSERT on error for debug version.
+ @retval EFI_ERROR Please reference LocateProtocol for error code details.
+**/
+EFI_STATUS
+EFIAPI
+SmmSpiFlashCommonLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ mFlashAreaBaseAddress = (UINTN)PcdGet32 (PcdFlashAreaBaseAddress);
+ mFlashAreaSize = (UINTN)PcdGet32 (PcdFlashAreaSize);
+
+ //
+ // Locate the SMM SPI protocol.
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gPchSmmSpiProtocolGuid,
+ NULL,
+ (VOID **) &mSpiProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
new file mode 100644
index 0000000000..128f7adcea
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the PchSpiCommonLib
+#
+# Copyright (c) 2017, 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 = BasePchSpiCommonLib
+ FILE_GUID = A37CB67E-7D85-45B3-B07E-BF65BDB603E8
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchSpiCommonLib
+
+[Sources]
+ SpiCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PchCycleDecodingLib
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c
new file mode 100644
index 0000000000..46184d4994
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c
@@ -0,0 +1,1058 @@
+/** @file
+ PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (c) 2017, 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 that 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 <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/MmPciLib.h>
+#include <Protocol/Spi.h>
+#include <Library/PchSpiCommonLib.h>
+
+/**
+ Initialize an SPI protocol instance.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @exception EFI_UNSUPPORTED The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ UINTN PchSpiBar0;
+ UINT32 Data32;
+
+ //
+ // Initialize the SPI protocol instance
+ //
+ SpiInstance->Signature = PCH_SPI_PRIVATE_DATA_SIGNATURE;
+ SpiInstance->Handle = NULL;
+ SpiInstance->SpiProtocol.Revision = PCH_SPI_SERVICES_REVISION;
+ SpiInstance->SpiProtocol.FlashRead = SpiProtocolFlashRead;
+ SpiInstance->SpiProtocol.FlashWrite = SpiProtocolFlashWrite;
+ SpiInstance->SpiProtocol.FlashErase = SpiProtocolFlashErase;
+ SpiInstance->SpiProtocol.FlashReadSfdp = SpiProtocolFlashReadSfdp;
+ SpiInstance->SpiProtocol.FlashReadJedecId = SpiProtocolFlashReadJedecId;
+ SpiInstance->SpiProtocol.FlashWriteStatus = SpiProtocolFlashWriteStatus;
+ SpiInstance->SpiProtocol.FlashReadStatus = SpiProtocolFlashReadStatus;
+ SpiInstance->SpiProtocol.GetRegionAddress = SpiProtocolGetRegionAddress;
+ SpiInstance->SpiProtocol.ReadPchSoftStrap = SpiProtocolReadPchSoftStrap;
+ SpiInstance->SpiProtocol.ReadCpuSoftStrap = SpiProtocolReadCpuSoftStrap;
+
+ SpiInstance->PchSpiBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+
+ PchAcpiBaseGet (&(SpiInstance->PchAcpiBase));
+ ASSERT (SpiInstance->PchAcpiBase != 0);
+
+ PchSpiBar0 = MmioRead32 (SpiInstance->PchSpiBase + R_PCH_SPI_BAR0) & ~(B_PCH_SPI_BAR0_MASK);
+ if (PchSpiBar0 == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR : PchSpiBar0 is invalid!\n"));
+ ASSERT (FALSE);
+ }
+
+ if ((MmioRead32 (PchSpiBar0 + R_PCH_SPI_HSFSC) & B_PCH_SPI_HSFSC_FDV) == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR : SPI Flash Signature invalid, cannot use the Hardware Sequencing registers!\n"));
+ ASSERT (FALSE);
+ }
+
+ //
+ // Get Region 0 - 7 read Permission bits, region 8 and above are not permitted.
+ //
+ SpiInstance->ReadPermission = MmioRead8 (PchSpiBar0 + R_PCH_SPI_FRAP) & B_PCH_SPI_FRAP_BRRA_MASK;
+ DEBUG ((DEBUG_INFO, "Flash Region read Permission : %0x\n", SpiInstance->ReadPermission));
+ //
+ // Get Region 0 - 7 write Permission bits, region 8 and above are not permitted.
+ //
+ SpiInstance->WritePermission = (UINT8) ((MmioRead16 (PchSpiBar0 + R_PCH_SPI_FRAP) &
+ B_PCH_SPI_FRAP_BRWA_MASK) >> N_PCH_SPI_FRAP_BRWA);
+ DEBUG ((DEBUG_INFO, "Flash Region write Permission : %0x\n", SpiInstance->WritePermission));
+
+ SpiInstance->SfdpVscc0Value = MmioRead32 (PchSpiBar0 + R_PCH_SPI_SFDP0_VSCC0);
+ DEBUG ((DEBUG_INFO, "Component 0 SFDP VSCC value : %0x\n", SpiInstance->SfdpVscc0Value));
+ SpiInstance->SfdpVscc1Value = MmioRead32 (PchSpiBar0 + R_PCH_SPI_SFDP1_VSCC1);
+ DEBUG ((DEBUG_INFO, "Component 1 SFDP VSCC value : %0x\n", SpiInstance->SfdpVscc1Value));
+
+ //
+ // Select to Flash Map 0 Register to get the number of flash Component
+ //
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_PCH_SPI_FDOC,
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP0)
+ );
+
+ //
+ // Copy Zero based Number Of Components
+ //
+ SpiInstance->NumberOfComponents = (UINT8) ((MmioRead16 (PchSpiBar0 + R_PCH_SPI_FDOD) & B_PCH_SPI_FDBAR_NC) >> N_PCH_SPI_FDBAR_NC);
+ DEBUG ((DEBUG_INFO, "Component Number : %0x\n", SpiInstance->NumberOfComponents + 1));
+
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_PCH_SPI_FDOC,
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_COMP | R_PCH_SPI_FCBA_FLCOMP)
+ );
+
+ //
+ // Copy Component 0 Density
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+ if (SpiInstance->NumberOfComponents > 0) {
+ SpiInstance->Component1StartAddr = V_PCH_SPI_FLCOMP_COMP_512KB <<
+ (Data32 & B_PCH_SPI_FLCOMP_COMP0_MASK);
+ DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n", SpiInstance->Component1StartAddr));
+ SpiInstance->TotalFlashSize = SpiInstance->Component1StartAddr +
+ (V_PCH_SPI_FLCOMP_COMP_512KB <<
+ ((Data32 & B_PCH_SPI_FLCOMP_COMP1_MASK) >>
+ N_PCH_SPI_FLCOMP_COMP1));
+ } else {
+ SpiInstance->TotalFlashSize = V_PCH_SPI_FLCOMP_COMP_512KB <<
+ (Data32 & B_PCH_SPI_FLCOMP_COMP0_MASK);
+ }
+ DEBUG ((DEBUG_INFO, "Total Flash Size : %0x\n", SpiInstance->TotalFlashSize));
+
+ //
+ // Select FLASH_MAP1 to get Flash PCH Strap Base Address
+ //
+ MmioAndThenOr32 (
+ (PchSpiBar0 + R_PCH_SPI_FDOC),
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP1)
+ );
+ //
+ // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+ SpiInstance->PchStrapBaseAddr = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_FPSBA)
+ >> N_PCH_SPI_FDBAR_FPSBA)
+ << N_PCH_SPI_FDBAR_FPSBA_REPR);
+ DEBUG ((DEBUG_INFO, "PchStrapBaseAddr : %0x\n", SpiInstance->PchStrapBaseAddr));
+ ASSERT (SpiInstance->PchStrapBaseAddr != 0);
+ //
+ // PCH Strap Length, [31:24] represents number of Dwords
+ //
+ SpiInstance->PchStrapSize = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_PCHSL)
+ >> N_PCH_SPI_FDBAR_PCHSL)
+ * sizeof (UINT32));
+ DEBUG ((DEBUG_INFO, "PchStrapSize : %0x\n", SpiInstance->PchStrapSize));
+
+ //
+ // Select FLASH_MAP2 to get Flash CPU Strap Base Address
+ //
+ MmioAndThenOr32 (
+ (PchSpiBar0 + R_PCH_SPI_FDOC),
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP2)
+ );
+ //
+ // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+ SpiInstance->CpuStrapBaseAddr = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_FCPUSBA)
+ >> N_PCH_SPI_FDBAR_FCPUSBA)
+ << N_PCH_SPI_FDBAR_FCPUSBA_REPR);
+ DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n", SpiInstance->CpuStrapBaseAddr));
+ ASSERT (SpiInstance->CpuStrapBaseAddr != 0);
+ //
+ // CPU Strap Length, [15:8] represents number of Dwords
+ //
+ SpiInstance->CpuStrapSize = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_CPUSL)
+ >> N_PCH_SPI_FDBAR_CPUSL)
+ * sizeof (UINT32));
+ DEBUG ((DEBUG_INFO, "CpuStrapSize : %0x\n", SpiInstance->CpuStrapSize));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delay for at least the request number of microseconds for Runtime usage.
+
+ @param[in] ABase Acpi base address
+ @param[in] Microseconds Number of microseconds to delay.
+
+**/
+VOID
+EFIAPI
+PchPmTimerStallRuntimeSafe (
+ IN UINT16 ABase,
+ IN UINTN Microseconds
+ )
+{
+ UINTN Ticks;
+ UINTN Counts;
+ UINTN CurrentTick;
+ UINTN OriginalTick;
+ UINTN RemainingTick;
+
+ if (Microseconds == 0) {
+ return;
+ }
+
+ OriginalTick = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL;
+ CurrentTick = OriginalTick;
+
+ //
+ // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks
+ //
+ Ticks = Microseconds * 358 / 100 + OriginalTick + 1;
+
+ //
+ // The loops needed by timer overflow
+ //
+ Counts = Ticks / V_PCH_ACPI_PM1_TMR_MAX_VAL;
+
+ //
+ // Remaining clocks within one loop
+ //
+ RemainingTick = Ticks % V_PCH_ACPI_PM1_TMR_MAX_VAL;
+
+ //
+ // not intend to use TMROF_STS bit of register PM1_STS, because this adds extra
+ // one I/O operation, and maybe generate SMI
+ //
+ while ((Counts != 0) || (RemainingTick > CurrentTick)) {
+ CurrentTick = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL;
+ //
+ // Check if timer overflow
+ //
+ if ((CurrentTick < OriginalTick)) {
+ if (Counts != 0) {
+ Counts--;
+ } else {
+ //
+ // If timer overflow and Counts equ to 0, that means we already stalled more than
+ // RemainingTick, break the loop here
+ //
+ break;
+ }
+ }
+
+ OriginalTick = CurrentTick;
+ }
+}
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleRead,
+ Address,
+ ByteCount,
+ Buffer
+ );
+ return Status;
+}
+
+/**
+ Write data to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleWrite,
+ Address,
+ ByteCount,
+ Buffer
+ );
+ return Status;
+}
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleErase,
+ Address,
+ ByteCount,
+ NULL
+ );
+ return Status;
+}
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ EFI_STATUS Status;
+ UINT32 FlashAddress;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ Status = EFI_SUCCESS;
+
+ if (ComponentNumber > SpiInstance->NumberOfComponents) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FlashAddress = 0;
+ if (ComponentNumber == FlashComponent1) {
+ FlashAddress = SpiInstance->Component1StartAddr;
+ }
+ FlashAddress += Address;
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadSfdp,
+ FlashAddress,
+ ByteCount,
+ SfdpData
+ );
+ return Status;
+}
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ EFI_STATUS Status;
+ UINT32 Address;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ Status = EFI_SUCCESS;
+
+ if (ComponentNumber > SpiInstance->NumberOfComponents) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address = 0;
+ if (ComponentNumber == FlashComponent1) {
+ Address = SpiInstance->Component1StartAddr;
+ }
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadJedecId,
+ Address,
+ ByteCount,
+ JedecId
+ );
+ return Status;
+}
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleWriteStatus,
+ 0,
+ ByteCount,
+ StatusValue
+ );
+ return Status;
+}
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadStatus,
+ 0,
+ ByteCount,
+ StatusValue
+ );
+ return Status;
+}
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchSpiBar0;
+ UINT32 ReadValue;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (FlashRegionType >= FlashRegionMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FlashRegionType == FlashRegionAll) {
+ *BaseAddress = 0;
+ *RegionSize = SpiInstance->TotalFlashSize;
+ return EFI_SUCCESS;
+ }
+
+ PchSpiBar0 = AcquireSpiBar0 (SpiInstance);
+ ReadValue = MmioRead32 (PchSpiBar0 + (R_PCH_SPI_FREG0_FLASHD + (S_PCH_SPI_FREGX * ((UINT32) FlashRegionType))));
+ ReleaseSpiBar0 (SpiInstance);
+
+ //
+ // If the region is not used, the Region Base is 7FFFh and Region Limit is 0000h
+ //
+ if (ReadValue == B_PCH_SPI_FREGX_BASE_MASK) {
+ return EFI_DEVICE_ERROR;
+ }
+ *BaseAddress = ((ReadValue & B_PCH_SPI_FREGX_BASE_MASK) >> N_PCH_SPI_FREGX_BASE) <<
+ N_PCH_SPI_FREGX_BASE_REPR;
+ //
+ // Region limit address Bits[11:0] are assumed to be FFFh
+ //
+ *RegionSize = ((((ReadValue & B_PCH_SPI_FREGX_LIMIT_MASK) >> N_PCH_SPI_FREGX_LIMIT) + 1) <<
+ N_PCH_SPI_FREGX_LIMIT_REPR) - *BaseAddress;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINT32 StrapFlashAddr;
+ EFI_STATUS Status;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (ByteCount == 0) {
+ *(UINT16 *) SoftStrapValue = SpiInstance->PchStrapSize;
+ return EFI_SUCCESS;
+ }
+
+ if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->PchStrapSize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // PCH Strap Flash Address = FPSBA + RamAddr
+ //
+ StrapFlashAddr = SpiInstance->PchStrapBaseAddr + SoftStrapAddr;
+
+ //
+ // Read PCH Soft straps from using execute command
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionDescriptor,
+ FlashCycleRead,
+ StrapFlashAddr,
+ ByteCount,
+ SoftStrapValue
+ );
+ return Status;
+}
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINT32 StrapFlashAddr;
+ EFI_STATUS Status;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (ByteCount == 0) {
+ *(UINT16 *) SoftStrapValue = SpiInstance->CpuStrapSize;
+ return EFI_SUCCESS;
+ }
+
+ if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->CpuStrapSize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // CPU Strap Flash Address = FCPUSBA + RamAddr
+ //
+ StrapFlashAddr = SpiInstance->CpuStrapBaseAddr + SoftStrapAddr;
+
+ //
+ // Read Cpu Soft straps from using execute command
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionDescriptor,
+ FlashCycleRead,
+ StrapFlashAddr,
+ ByteCount,
+ SoftStrapValue
+ );
+ return Status;
+}
+
+/**
+ This function sends the programmed SPI command to the slave device.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SpiRegionType The SPI Region type for flash cycle which is listed in the Descriptor
+ @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in,out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+ @retval EFI_SUCCESS SPI command completes successfully.
+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+**/
+EFI_STATUS
+SendSpiCmd (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN FLASH_CYCLE_TYPE FlashCycleType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ SPI_INSTANCE *SpiInstance;
+ UINTN SpiBaseAddress;
+ UINTN PchSpiBar0;
+ UINT32 HardwareSpiAddr;
+ UINT32 FlashRegionSize;
+ UINT32 SpiDataCount;
+ UINT32 FlashCycle;
+ UINT8 BiosCtlSave;
+ UINT32 SmiEnSave;
+ UINT16 ABase;
+
+ Status = EFI_SUCCESS;
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ SpiBaseAddress = SpiInstance->PchSpiBase;
+ PchSpiBar0 = AcquireSpiBar0 (SpiInstance);
+ SpiBaseAddress = SpiInstance->PchSpiBase;
+ ABase = SpiInstance->PchAcpiBase;
+
+ //
+ // Disable SMIs to make sure normal mode flash access is not interrupted by an SMI
+ // whose SMI handler accesses flash (e.g. for error logging)
+ //
+ // *** NOTE: if the SMI_LOCK bit is set (i.e., PMC PCI Offset A0h [4]='1'),
+ // clearing B_GBL_SMI_EN will not have effect. In this situation, some other
+ // synchronization methods must be applied here or in the consumer of the
+ // SendSpiCmd. An example method is disabling the specific SMI sources
+ // whose SMI handlers access flash before flash cycle and re-enabling the SMI
+ // sources after the flash cycle .
+ //
+ SmiEnSave = IoRead32 ((UINTN) (ABase + R_PCH_SMI_EN));
+ IoWrite32 ((UINTN) (ABase + R_PCH_SMI_EN), SmiEnSave & (UINT32) (~B_PCH_SMI_EN_GBL_SMI));
+ BiosCtlSave = MmioRead8 (SpiBaseAddress + R_PCH_SPI_BC) & B_PCH_SPI_BC_SRC;
+
+ //
+ // If it's write cycle, disable Prefetching, Caching and disable BIOS Write Protect
+ //
+ if ((FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleErase)) {
+ Status = DisableBiosWriteProtect ();
+ if (EFI_ERROR (Status)) {
+ goto SendSpiCmdEnd;
+ }
+ MmioAndThenOr8 (
+ SpiBaseAddress + R_PCH_SPI_BC,
+ (UINT8) (~B_PCH_SPI_BC_SRC),
+ (UINT8) (V_PCH_SPI_BC_SRC_PREF_DIS_CACHE_DIS << N_PCH_SPI_BC_SRC)
+ );
+ }
+ //
+ // Make sure it's safe to program the command.
+ //
+ if (!WaitForSpiCycleComplete (This, PchSpiBar0, FALSE)) {
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+
+ Status = SpiProtocolGetRegionAddress (This, FlashRegionType, &HardwareSpiAddr, &FlashRegionSize);
+ if (EFI_ERROR (Status)) {
+ goto SendSpiCmdEnd;
+ }
+ HardwareSpiAddr += Address;
+ if ((Address + ByteCount) > FlashRegionSize) {
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ }
+
+ //
+ // Check for PCH SPI hardware sequencing required commands
+ //
+ FlashCycle = 0;
+ switch (FlashCycleType) {
+ case FlashCycleRead:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleWrite:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_WRITE << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleErase:
+ if (((ByteCount % SIZE_4KB) != 0) ||
+ ((HardwareSpiAddr % SIZE_4KB) != 0)) {
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ }
+ break;
+ case FlashCycleReadSfdp:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_SFDP << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleReadJedecId:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_JEDEC_ID << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleWriteStatus:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_WRITE_STATUS << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleReadStatus:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_STATUS << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ default:
+ //
+ // Unrecognized Operation
+ //
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ break;
+ }
+
+ do {
+ SpiDataCount = ByteCount;
+ if ((FlashCycleType == FlashCycleRead) ||
+ (FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleReadSfdp)) {
+ //
+ // Trim at 256 byte boundary per operation,
+ // - PCH SPI controller requires trimming at 4KB boundary
+ // - Some SPI chips require trimming at 256 byte boundary for write operation
+ // - Trimming has limited performance impact as we can read / write atmost 64 byte
+ // per operation
+ //
+ if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
+ SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
+ }
+ //
+ // Calculate the number of bytes to shift in/out during the SPI data cycle.
+ // Valid settings for the number of bytes duing each data portion of the
+ // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ if (SpiDataCount >= 64) {
+ SpiDataCount = 64;
+ } else if ((SpiDataCount &~0x07) != 0) {
+ SpiDataCount = SpiDataCount &~0x07;
+ }
+ }
+ if (FlashCycleType == FlashCycleErase) {
+ if (((ByteCount / SIZE_64KB) != 0) &&
+ ((ByteCount % SIZE_64KB) == 0) &&
+ ((HardwareSpiAddr % SIZE_64KB) == 0)) {
+ if (HardwareSpiAddr < SpiInstance->Component1StartAddr) {
+ //
+ // Check whether Component0 support 64k Erase
+ //
+ if ((SpiInstance->SfdpVscc0Value & B_PCH_SPI_SFDPX_VSCCX_EO_64K) != 0) {
+ SpiDataCount = SIZE_64KB;
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ } else {
+ //
+ // Check whether Component1 support 64k Erase
+ //
+ if ((SpiInstance->SfdpVscc1Value & B_PCH_SPI_SFDPX_VSCCX_EO_64K) != 0) {
+ SpiDataCount = SIZE_64KB;
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ }
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ if (SpiDataCount == SIZE_4KB) {
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_4K_ERASE << N_PCH_SPI_HSFSC_CYCLE);
+ } else {
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_64K_ERASE << N_PCH_SPI_HSFSC_CYCLE);
+ }
+ }
+ //
+ // If it's write cycle, load data into the SPI data buffer.
+ //
+ if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleWriteStatus)) {
+ if ((SpiDataCount & 0x07) != 0) {
+ //
+ // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+ //
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ MmioWrite8 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index, Buffer[Index]);
+ }
+ } else {
+ //
+ // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index, *(UINT32 *) (Buffer + Index));
+ }
+ }
+ }
+
+ //
+ // Set the Flash Address
+ //
+ MmioWrite32 (
+ (PchSpiBar0 + R_PCH_SPI_FADDR),
+ (UINT32) (HardwareSpiAddr & B_PCH_SPI_FADDR_MASK)
+ );
+
+ //
+ // Set Data count, Flash cycle, and Set Go bit to start a cycle
+ //
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_PCH_SPI_HSFSC,
+ (UINT32) (~(B_PCH_SPI_HSFSC_FDBC_MASK | B_PCH_SPI_HSFSC_CYCLE_MASK)),
+ (UINT32) ((((SpiDataCount - 1) << N_PCH_SPI_HSFSC_FDBC) & B_PCH_SPI_HSFSC_FDBC_MASK) | FlashCycle | B_PCH_SPI_HSFSC_CYCLE_FGO)
+ );
+ //
+ // end of command execution
+ //
+ // Wait the SPI cycle to complete.
+ //
+ if (!WaitForSpiCycleComplete (This, PchSpiBar0, TRUE)) {
+ ASSERT (FALSE);
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+ //
+ // If it's read cycle, load data into the call's buffer.
+ //
+ if ((FlashCycleType == FlashCycleRead) ||
+ (FlashCycleType == FlashCycleReadSfdp) ||
+ (FlashCycleType == FlashCycleReadJedecId) ||
+ (FlashCycleType == FlashCycleReadStatus)) {
+ if ((SpiDataCount & 0x07) != 0) {
+ //
+ // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+ //
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ Buffer[Index] = MmioRead8 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index);
+ }
+ } else {
+ //
+ // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+ *(UINT32 *) (Buffer + Index) = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index);
+ }
+ }
+ }
+
+ HardwareSpiAddr += SpiDataCount;
+ Buffer += SpiDataCount;
+ ByteCount -= SpiDataCount;
+ } while (ByteCount > 0);
+
+SendSpiCmdEnd:
+ //
+ // Restore the settings for SPI Prefetching and Caching and enable BIOS Write Protect
+ //
+ if ((FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleErase)) {
+ EnableBiosWriteProtect ();
+ MmioAndThenOr8 (
+ SpiBaseAddress + R_PCH_SPI_BC,
+ (UINT8) ~B_PCH_SPI_BC_SRC,
+ BiosCtlSave
+ );
+ }
+ //
+ // Restore SMIs.
+ //
+ IoWrite32 ((UINTN) (ABase + R_PCH_SMI_EN), SmiEnSave);
+
+ ReleaseSpiBar0 (SpiInstance);
+
+ return Status;
+}
+
+/**
+ Wait execution cycle to complete on the SPI interface.
+
+ @param[in] This The SPI protocol instance
+ @param[in] PchSpiBar0 Spi MMIO base address
+ @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check
+
+ @retval TRUE SPI cycle completed on the interface.
+ @retval FALSE Time out while waiting the SPI cycle to complete.
+ It's not safe to program the next command on the SPI interface.
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINTN PchSpiBar0,
+ IN BOOLEAN ErrorCheck
+ )
+{
+ UINT64 WaitTicks;
+ UINT64 WaitCount;
+ UINT32 Data32;
+ SPI_INSTANCE *SpiInstance;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ //
+ // Convert the wait period allowed into to tick count
+ //
+ WaitCount = WAIT_TIME / WAIT_PERIOD;
+ //
+ // Wait for the SPI cycle to complete.
+ //
+ for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_HSFSC);
+ if ((Data32 & B_PCH_SPI_HSFSC_SCIP) == 0) {
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_HSFSC, B_PCH_SPI_HSFSC_FCERR | B_PCH_SPI_HSFSC_FDONE);
+ if (((Data32 & B_PCH_SPI_HSFSC_FCERR) != 0) && (ErrorCheck == TRUE)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+ PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, WAIT_PERIOD);
+ }
+ return FALSE;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf
new file mode 100644
index 0000000000..52d7c8bbaf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Component information file for PCH HD Audio Library
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = DxePchHdaLib
+FILE_GUID = DA915B7F-EE08-4C1D-B3D0-DE7C52AB155A
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchHdaLib
+
+
+[LibraryClasses]
+BaseLib
+DebugLib
+MemoryAllocationLib
+BaseMemoryLib
+PchInfoLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemId
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+
+
+[Sources]
+PchHdaLib.c
+PchHdaEndpoints.c
+PchHdaNhltConfig.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c
new file mode 100644
index 0000000000..11c6ec0269
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c
@@ -0,0 +1,318 @@
+/** @file
+ This file contains HD Audio NHLT Endpoints definitions
+
+Copyright (c) 2017, 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 that 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 <PchHdaEndpoints.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch1_48kHz16bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 1,
+ 48000,
+ 96000,
+ 2,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_MONO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch2_48kHz16bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 192000,
+ 4,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch2_48kHz24bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {24},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch2_48kHz32bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {32},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch4_48kHz16bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 4,
+ 48000,
+ 384000,
+ 8,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_QUAD,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch4_48kHz32bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 4,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {32},
+ KSAUDIO_SPEAKER_QUAD,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE NarrowbandFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 1,
+ 8000,
+ 16000,
+ 2,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_MONO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE WidebandFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 1,
+ 16000,
+ 32000,
+ 2,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_MONO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE A2dpFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {24},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointDmicX1 = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkDmic, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae20, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceDmic, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointDmicX2 = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkDmic, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae20, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceDmic, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointDmicX4 = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkDmic, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae20, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceDmic, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointBtRender = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae30, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceBt, // DeviceType
+ 0, // Direction
+ 2, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointBtCapture = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae30, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceBt, // DeviceType
+ 1, // Direction
+ 2, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointI2sRender = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 1, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae34, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceI2s, // DeviceType
+ 0, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointI2sCapture = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 1, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae34, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceI2s, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DmicX1Config[] =
+{
+ 0x00, // VirtualSlot
+ 0x00, // eIntcConfigTypeMicArray = 1 , eIntcConfigTypeGeneric = 0
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicX1ConfigSize = sizeof (DmicX1Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DmicX2Config[] =
+{
+ 0x00, // VirtualSlot
+ 0x01, // eIntcConfigTypeMicArray = 1 , eIntcConfigTypeGeneric = 0
+ 0x0A // ArrayType
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicX2ConfigSize = sizeof (DmicX2Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DmicX4Config[] =
+{
+ 0x00, // VirtualSlot
+ 0x01, // eIntcConfigTypeMicArray = 1 , eIntcConfigTypeGeneric = 0
+ 0x0D // ArrayType
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicX4ConfigSize = sizeof (DmicX4Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 BtConfig[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 BtConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 I2sRender1Config[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRender1ConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 I2sRender2Config[] = {0x01};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRender2ConfigSize = sizeof (I2sRender2Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 I2sCaptureConfig[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sCaptureConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 NhltConfiguration[] = { 0xEFBEADDE };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 NhltConfigurationSize = sizeof (NhltConfiguration);
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c
new file mode 100644
index 0000000000..e577cd9038
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c
@@ -0,0 +1,842 @@
+/** @file
+ PCH HD Audio Library implementation.
+
+Copyright (c) 2017, 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 that 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 <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PchHdaLib.h>
+#include <Library/PchInfoLib.h>
+
+/**
+ Returns pointer to Endpoint ENDPOINT_DESCRIPTOR structure.
+
+ @param[in] *NhltTable Endpoint for which Format address is retrieved
+ @param[in] FormatIndex Index of Format to be retrieved
+
+ @retval Pointer to ENDPOINT_DESCRIPTOR structure with given index
+**/
+ENDPOINT_DESCRIPTOR *
+GetNhltEndpoint (
+ IN CONST NHLT_ACPI_TABLE *NhltTable,
+ IN CONST UINT8 EndpointIndex
+ )
+{
+ UINT8 i;
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ Endpoint = (ENDPOINT_DESCRIPTOR*) (NhltTable->EndpointDescriptors);
+
+ if (EndpointIndex > NhltTable->EndpointCount) {
+ return NULL;
+ }
+
+ for (i = 0; i < EndpointIndex; i++) {
+ Endpoint = (ENDPOINT_DESCRIPTOR*) ((UINT8*) (Endpoint) + Endpoint->EndpointDescriptorLength);
+ }
+
+ return Endpoint;
+}
+
+/**
+ Returns pointer to Endpoint Specific Configuration SPECIFIC_CONFIG structure.
+
+ @param[in] *Endpoint Endpoint for which config address is retrieved
+
+ @retval Pointer to SPECIFIC_CONFIG structure with endpoint's capabilities
+**/
+SPECIFIC_CONFIG *
+GetNhltEndpointDeviceCapabilities (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ return (SPECIFIC_CONFIG*) (&Endpoint->EndpointConfig);
+}
+
+/**
+ Returns pointer to all Formats Configuration FORMATS_CONFIG structure.
+
+ @param[in] *Endpoint Endpoint for which Formats address is retrieved
+
+ @retval Pointer to FORMATS_CONFIG structure
+**/
+FORMATS_CONFIG *
+GetNhltEndpointFormatsConfig (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ FORMATS_CONFIG *FormatsConfig;
+ FormatsConfig = (FORMATS_CONFIG*) ((UINT8*) (&Endpoint->EndpointConfig)
+ + sizeof (Endpoint->EndpointConfig.CapabilitiesSize)
+ + Endpoint->EndpointConfig.CapabilitiesSize);
+
+ return FormatsConfig;
+}
+
+/**
+ Returns pointer to Format Configuration FORMAT_CONFIG structure.
+
+ @param[in] *Endpoint Endpoint for which Format address is retrieved
+ @param[in] FormatIndex Index of Format to be retrieved
+
+ @retval Pointer to FORMAT_CONFIG structure with given index
+**/
+FORMAT_CONFIG *
+GetNhltEndpointFormat (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint,
+ IN CONST UINT8 FormatIndex
+ )
+{
+ UINT8 i;
+ UINT32 Length;
+ FORMATS_CONFIG *FormatsConfig;
+ FORMAT_CONFIG *Format;
+
+ Length = 0;
+ FormatsConfig = GetNhltEndpointFormatsConfig (Endpoint);
+ Format = FormatsConfig->FormatsConfiguration;
+
+ if (FormatIndex > FormatsConfig->FormatsCount) {
+ return NULL;
+ }
+
+ for (i = 0; i < FormatIndex; i++) {
+ Length = sizeof (Format->Format) + Format->FormatConfiguration.CapabilitiesSize
+ + sizeof (Format->FormatConfiguration.CapabilitiesSize);
+ Format = (FORMAT_CONFIG*) ((UINT8*) (Format) + Length);
+ }
+
+ return Format;
+}
+
+/**
+ Returns pointer to OED Configuration SPECIFIC_CONFIG structure.
+
+ @param[in] *NhltTable NHLT table for which OED address is retrieved
+
+ @retval Pointer to SPECIFIC_CONFIG structure with NHLT capabilities
+**/
+SPECIFIC_CONFIG *
+GetNhltOedConfig (
+ IN CONST NHLT_ACPI_TABLE *NhltTable
+ )
+{
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ SPECIFIC_CONFIG *OedConfig;
+
+ Endpoint = GetNhltEndpoint (NhltTable, (NhltTable->EndpointCount));
+ OedConfig = (SPECIFIC_CONFIG*) ((UINT8*) (Endpoint));
+
+ return OedConfig;
+}
+
+/**
+ Prints Format configuration.
+
+ @param[in] *Format Format to be printed
+
+ @retval None
+**/
+VOID
+NhltFormatDump (
+ IN CONST FORMAT_CONFIG *Format
+ )
+{
+ UINT32 i;
+
+ DEBUG ((DEBUG_INFO, "------------------------------- FORMAT -------------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.wFormatTag = 0x%x\n", Format->Format.Format.wFormatTag));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nChannels = %d\n", Format->Format.Format.nChannels));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nSamplesPerSec = %d\n", Format->Format.Format.nSamplesPerSec));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nAvgBytesPerSec = %d\n", Format->Format.Format.nAvgBytesPerSec));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nBlockAlign = %d\n", Format->Format.Format.nBlockAlign));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.wBitsPerSample = %d\n", Format->Format.Format.wBitsPerSample));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.cbSize = %d\n", Format->Format.Format.cbSize));
+ DEBUG ((DEBUG_INFO, " Format->Format.Samples = %d\n", Format->Format.Samples));
+ DEBUG ((DEBUG_INFO, " Format->Format.dwChannelMask = 0x%x\n", Format->Format.dwChannelMask));
+ DEBUG ((DEBUG_INFO, " Format->Format.SubFormat = %g\n", Format->Format.SubFormat));
+
+
+ DEBUG ((DEBUG_INFO, " Format->FormatConfiguration.CapabilitiesSize = %d B\n", Format->FormatConfiguration.CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " Format->FormatConfiguration.Capabilities:"));
+ for (i = 0; i < ( Format->FormatConfiguration.CapabilitiesSize ) ; i++) {
+ if (i % 16 == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ }
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", Format->FormatConfiguration.Capabilities[i]));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints Endpoint configuration.
+
+ @param[in] *Endpoint Endpoint to be printed
+
+ @retval None
+**/
+VOID
+NhltEndpointDump (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ UINT8 i;
+ FORMATS_CONFIG *FormatsConfigs;
+ FORMAT_CONFIG *Format;
+
+ DEBUG ((DEBUG_INFO, "------------------------------ ENDPOINT ------------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Endpoint->DeviceDescriptorLength = %d B\n", Endpoint->EndpointDescriptorLength));
+ DEBUG ((DEBUG_INFO, " Endpoint->LinkType = 0x%x\n", Endpoint->LinkType));
+ DEBUG ((DEBUG_INFO, " Endpoint->InstanceId = 0x%x\n", Endpoint->InstanceId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwVendorId = 0x%x\n", Endpoint->HwVendorId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwDeviceId = 0x%x\n", Endpoint->HwDeviceId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwRevisionId = 0x%x\n", Endpoint->HwRevisionId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwSubsystemId = 0x%x\n", Endpoint->HwSubsystemId));
+ DEBUG ((DEBUG_INFO, " Endpoint->DeviceType = 0x%x\n", Endpoint->DeviceType));
+ DEBUG ((DEBUG_INFO, " Endpoint->Direction = 0x%x\n", Endpoint->Direction));
+ DEBUG ((DEBUG_INFO, " Endpoint->VirtualBusId = 0x%x\n", Endpoint->VirtualBusId));
+
+ DEBUG ((DEBUG_INFO, " Endpoint->EndpointConfig.CapabilitiesSize = %d B\n", Endpoint->EndpointConfig.CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " Endpoint->EndpointConfig.Capabilities:"));
+ for (i = 0; i < (Endpoint->EndpointConfig.CapabilitiesSize ) ; i++) {
+ if (i % 16 == 0) DEBUG ((DEBUG_VERBOSE, "\n"));
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", Endpoint->EndpointConfig.Capabilities[i]));
+ }
+
+ FormatsConfigs = GetNhltEndpointFormatsConfig (Endpoint);
+
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, " Endpoint->FormatsConfig.FormatsCount = %d\n", FormatsConfigs->FormatsCount));
+ for (i = 0; i < FormatsConfigs->FormatsCount; i++) {
+ Format = GetNhltEndpointFormat (Endpoint, i);
+ if (Format != NULL) {
+ NhltFormatDump (Format);
+ }
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints OED (Offload Engine Driver) configuration.
+
+ @param[in] *OedConfig OED to be printed
+
+ @retval None
+**/
+VOID
+NhltOedConfigDump (
+ IN CONST SPECIFIC_CONFIG *OedConfig
+ )
+{
+ UINT8 i;
+
+ DEBUG ((DEBUG_INFO, "-------------------------- OED CONFIGURATION -------------------------\n"));
+ DEBUG ((DEBUG_INFO, " OedConfig->CapabilitiesSize = %d B\n", OedConfig->CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " OedConfig->Capabilities:"));
+ for (i = 0; i < (OedConfig->CapabilitiesSize) ; i++) {
+ if (i % 16 == 0) DEBUG ((DEBUG_VERBOSE, "\n"));
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", OedConfig->Capabilities[i]));
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints NHLT (Non HDA-Link Table) to be exposed via ACPI (aka. OED (Offload Engine Driver) Configuration Table).
+
+ @param[in] *NhltTable The NHLT table to print
+
+ @retval None
+**/
+VOID
+NhltAcpiTableDump (
+ IN NHLT_ACPI_TABLE *NhltTable
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINT8 i;
+
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, "--- NHLT ACPI Table Dump [OED (Offload Engine Driver) Configuration] ---\n"));
+
+ DEBUG ((DEBUG_INFO, "sizeof NHLT_ACPI_TABLE = %d B\n", sizeof (NHLT_ACPI_TABLE)));
+ DEBUG ((DEBUG_INFO, "sizeof EFI_ACPI_DESCRIPTION_HEADER = %d B\n", sizeof (EFI_ACPI_DESCRIPTION_HEADER)));
+ DEBUG ((DEBUG_INFO, "sizeof ENDPOINT_DESCRIPTOR = %d B\n", sizeof (ENDPOINT_DESCRIPTOR)));
+ DEBUG ((DEBUG_INFO, "sizeof SPECIFIC_CONFIG = %d B\n", sizeof (SPECIFIC_CONFIG)));
+ DEBUG ((DEBUG_INFO, "sizeof FORMATS_CONFIG = %d B\n", sizeof (FORMATS_CONFIG)));
+ DEBUG ((DEBUG_INFO, "sizeof FORMAT_CONFIG = %d B\n", sizeof (FORMAT_CONFIG)));
+ DEBUG ((DEBUG_INFO, "sizeof WAVEFORMATEXTENSIBLE = %d B\n", sizeof (WAVEFORMATEXTENSIBLE)));
+
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Signature = 0x%08x\n", NhltTable->Header.Signature));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Length = 0x%08x\n", NhltTable->Header.Length));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Revision = 0x%02x\n", NhltTable->Header.Revision));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Checksum = 0x%02x\n", NhltTable->Header.Checksum));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.OemId = %a\n", NhltTable->Header.OemId));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.OemTableId = 0x%lx\n", NhltTable->Header.OemTableId));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.OemRevision = 0x%08x\n", NhltTable->Header.OemRevision));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.CreatorId = 0x%08x\n", NhltTable->Header.CreatorId));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.CreatorRevision = 0x%08x\n", NhltTable->Header.CreatorRevision));
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE EndpointCount = %d\n", NhltTable->EndpointCount));
+ for (i = 0; i < NhltTable->EndpointCount; i++) {
+ NhltEndpointDump (GetNhltEndpoint (NhltTable, i));
+ }
+
+ NhltOedConfigDump (GetNhltOedConfig (NhltTable));
+ DEBUG ((DEBUG_INFO, "----------------------------------------------------------------------\n"));
+
+ DEBUG_CODE_END ();
+}
+
+/**
+ Constructs FORMATS_CONFIGS structure based on given formats list.
+
+ @param[in][out] *Endpoint Endpoint for which format structures are created
+ @param[in] FormatBitmask Bitmask of formats supported for given endpoint
+
+ @retval Size of created FORMATS_CONFIGS structure
+**/
+UINT32
+NhltFormatsConstructor (
+ IN OUT ENDPOINT_DESCRIPTOR *Endpoint,
+ IN CONST UINT32 FormatsBitmask
+ )
+{
+ FORMATS_CONFIG *FormatsConfig;
+ FORMAT_CONFIG *Format;
+ UINT8 FormatIndex;
+ UINT32 FormatsConfigLength;
+
+ DEBUG ((DEBUG_INFO, "NhltFormatsConstructor() Start, FormatsBitmask = 0x%08x\n", FormatsBitmask));
+
+ FormatsConfig = NULL;
+ FormatIndex = 0;
+ FormatsConfigLength = 0;
+
+ if (!FormatsBitmask) {
+ DEBUG ((DEBUG_WARN, "No supported format found!\n"));
+ return 0;
+ }
+
+ FormatsConfig = GetNhltEndpointFormatsConfig (Endpoint);
+ FormatsConfig->FormatsCount = 0;
+
+ if (FormatsBitmask & B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicStereo16BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicStereo16BitFormatConfig, DmicStereo16BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicStereo32BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicStereo32BitFormatConfig, DmicStereo32BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch4_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicQuad16BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicQuad16BitFormatConfig, DmicQuad16BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch4_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicQuad32BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicQuad32BitFormatConfig, DmicQuad32BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch1_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicMono16BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicMono16BitFormatConfig, DmicMono16BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_BT_NARROWBAND_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_BT_NARROWBAND_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &NarrowbandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = BtFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, BtFormatConfig, BtFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_BT_WIDEBAND_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_BT_WIDEBAND_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &WidebandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = BtFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, BtFormatConfig, BtFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_BT_A2DP_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_BT_A2DP_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &A2dpFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = BtFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, BtFormatConfig, BtFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sRtk298Render4ch48kHz24bitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sRtk298Render4ch48kHz24bitFormatConfig, I2sRtk298Render4ch48kHz24bitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_RTK298_CAPTURE_4CH_48KHZ_24BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_RTK298_CAPTURE_4CH_48KHZ_24BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sRtk298Capture4ch48kHz24bitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sRtk298Capture4ch48kHz24bitFormatConfig, I2sRtk298Capture4ch48kHz24bitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_RTK286S_2CH_48KHZ_24BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_RTK286S_2CH_48KHZ_24BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sRtk286S2ch48kHzFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sRtk286S2ch48kHzFormatConfig, I2sRtk286S2ch48kHzFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_ADI_4CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_ADI_4CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch4_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sAdi4ch48kHzFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sAdi4ch48kHzFormatConfig, I2sAdi4ch48kHzFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_48KHZ_24BIT_MASTER_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_48KHZ_24BIT_MASTER_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2s48kHz24bitMasterFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2s48kHz24bitMasterFormatConfig, I2s48kHz24bitMasterFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_48KHZ_24BIT_SLAVE_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_48KHZ_24BIT_SLAVE_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2s48kHz24bitSlaveFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2s48kHz24bitSlaveFormatConfig, I2s48kHz24bitSlaveFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_PCM_8KHZ_16BIT_MASTER_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_PCM_8KHZ_16BIT_MASTER_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &NarrowbandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sPcm8kHz16bitMasterFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sPcm8kHz16bitMasterFormatConfig, I2sPcm8kHz16bitMasterFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_PCM_8KHZ_16BIT_SLAVE_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_PCM_8KHZ_16BIT_SLAVE_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &NarrowbandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sPcm8kHz16bitSlaveFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sPcm8kHz16bitSlaveFormatConfig, I2sPcm8kHz16bitSlaveFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "NhltFormatsConstructor() End, FormatsCount = %d, FormatsConfigLength = %d B\n", FormatsConfig->FormatsCount, FormatsConfigLength));
+ return FormatsConfigLength;
+}
+
+/**
+ Constructs NHLT_ENDPOINT structure based on given endpoint type.
+
+ @param[in][out] *NhltTable NHLT table for which endpoint is created
+ @param[in] EndpointType Type of endpoint to be created
+ @param[in] EndpointFormatsBitmask Bitmask of formats supported by endpoint
+ @param[in] EndpointIndex Endpoint index in NHLT table
+
+ @retval Size of created NHLT_ENDPOINT structure
+**/
+UINT32
+NhltEndpointConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable,
+ IN NHLT_ENDPOINT EndpointType,
+ IN UINT32 EndpointFormatsBitmask,
+ IN UINT8 EndpointIndex
+ )
+{
+
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ SPECIFIC_CONFIG *EndpointConfig;
+ CONST UINT8 *EndpointConfigBuffer;
+ UINT32 EndpointConfigBufferSize;
+ UINT32 EndpointDescriptorLength;
+
+ DEBUG ((DEBUG_INFO, "NhltEndpointConstructor() Start, EndpointIndex = %d\n", EndpointIndex));
+
+ EndpointDescriptorLength = 0;
+ Endpoint = GetNhltEndpoint (NhltTable, EndpointIndex);
+ if (Endpoint == NULL) {
+ return 0;
+ }
+ EndpointDescriptorLength = sizeof (ENDPOINT_DESCRIPTOR)
+ - sizeof (SPECIFIC_CONFIG)
+ - sizeof (FORMAT_CONFIG);
+
+ switch (EndpointType) {
+ case HdaDmicX1:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX1\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX1, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX1Config;
+ EndpointConfigBufferSize = DmicX1ConfigSize;
+ break;
+ case HdaDmicX2:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX2\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX2, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX2Config;
+ EndpointConfigBufferSize = DmicX2ConfigSize;
+ break;
+ case HdaDmicX4:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX4\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX4, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX4Config;
+ EndpointConfigBufferSize = DmicX4ConfigSize;
+ break;
+ case HdaBtRender:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaBtRender\n"));
+ CopyMem (Endpoint, &HdaEndpointBtRender, sizeof (ENDPOINT_DESCRIPTOR));
+ if (GetPchSeries () == PchH) {
+ Endpoint->VirtualBusId = 0;
+ }
+
+ EndpointConfigBuffer = BtConfig;
+ EndpointConfigBufferSize = BtConfigSize;
+ break;
+ case HdaBtCapture:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaBtCapture\n"));
+ CopyMem (Endpoint, &HdaEndpointBtCapture, sizeof (ENDPOINT_DESCRIPTOR));
+ if (GetPchSeries () == PchH) {
+ Endpoint->VirtualBusId = 0;
+ }
+
+ EndpointConfigBuffer = BtConfig;
+ EndpointConfigBufferSize = BtConfigSize;
+ break;
+ case HdaI2sRender1:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sRender1\n"));
+ CopyMem (Endpoint, &HdaEndpointI2sRender, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sRender1Config;
+ EndpointConfigBufferSize = I2sRender1ConfigSize;
+ break;
+ case HdaI2sRender2:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sRender2\n"));
+ CopyMem (Endpoint, &HdaEndpointI2sRender, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sRender2Config;
+ EndpointConfigBufferSize = I2sRender2ConfigSize;
+ break;
+ case HdaI2sCapture:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sCapture\n"));
+ CopyMem (Endpoint, &HdaEndpointI2sCapture, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sCaptureConfig;
+ EndpointConfigBufferSize = I2sCaptureConfigSize;
+ break;
+ default:
+ DEBUG ((DEBUG_WARN, "Unknown endpoint!\n"));
+ return 0;
+ }
+
+ EndpointConfig = GetNhltEndpointDeviceCapabilities (Endpoint);
+ EndpointConfig->CapabilitiesSize = EndpointConfigBufferSize;
+ CopyMem (EndpointConfig->Capabilities, EndpointConfigBuffer, EndpointConfig->CapabilitiesSize);
+ EndpointDescriptorLength += sizeof (*EndpointConfig)
+ - sizeof (EndpointConfig->Capabilities)
+ + EndpointConfig->CapabilitiesSize;
+
+ EndpointDescriptorLength += NhltFormatsConstructor (Endpoint, EndpointFormatsBitmask);
+ Endpoint->EndpointDescriptorLength = EndpointDescriptorLength;
+
+ DEBUG ((DEBUG_INFO, "NhltEndpointConstructor() End, EndpointDescriptorLength = %d B\n", Endpoint->EndpointDescriptorLength));
+ return Endpoint->EndpointDescriptorLength;
+}
+
+/**
+ Constructs SPECIFIC_CONFIG structure for OED configuration.
+
+ @param[in][out] *NhltTable NHLT table for which OED config is created
+
+ @retval Size of created SPECIFIC_CONFIG structure
+**/
+UINT32
+NhltOedConfigConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable
+ )
+{
+ SPECIFIC_CONFIG *OedConfig;
+ UINT32 OedConfigLength;
+
+ OedConfigLength = 0;
+ OedConfig = GetNhltOedConfig (NhltTable);
+
+ OedConfig->CapabilitiesSize = NhltConfigurationSize;
+ CopyMem (OedConfig->Capabilities, (UINT8*) NhltConfiguration, NhltConfigurationSize);
+
+ OedConfigLength = sizeof (*OedConfig)
+ - sizeof (OedConfig->Capabilities)
+ + OedConfig->CapabilitiesSize;
+
+ return OedConfigLength;
+}
+
+/**
+ Constructs NHLT_ACPI_TABLE structure based on given Endpoints list.
+
+ @param[in] *EndpointTable List of endpoints for NHLT
+ @param[in][out] **NhltTable NHLT table to be created
+ @param[in][out] *NhltTableSize Size of created NHLT table
+
+ @retval EFI_SUCCESS NHLT created successfully
+ @retval EFI_BAD_BUFFER_SIZE Not enough resources to allocate NHLT
+**/
+EFI_STATUS
+NhltConstructor (
+ IN PCH_HDA_NHLT_ENDPOINTS *EndpointTable,
+ IN OUT NHLT_ACPI_TABLE **NhltTable,
+ IN OUT UINT32 *NhltTableSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINT32 TableSize;
+ UINT32 EndpointDescriptorsLength;
+ UINT32 OedConfigLength;
+ NHLT_ACPI_TABLE *Table;
+
+
+ Status = EFI_SUCCESS;
+ TableSize = PCH_HDA_NHLT_TABLE_SIZE;
+ EndpointDescriptorsLength = 0;
+ OedConfigLength = 0;
+
+ Table = AllocateZeroPool (TableSize);
+
+ if (Table == NULL) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ Table->EndpointCount = 0;
+
+ for (Index = 0; Index < HdaEndpointMax; Index++) {
+ if (EndpointTable[Index].Enable == TRUE) {
+ EndpointDescriptorsLength += NhltEndpointConstructor (Table,
+ EndpointTable[Index].EndpointType,
+ EndpointTable[Index].EndpointFormatsBitmask,
+ Table->EndpointCount++);
+ }
+ }
+ DEBUG ((DEBUG_INFO, "NhltConstructor: EndpointCount = %d, All EndpointDescriptorsLength = %d B\n", Table->EndpointCount, EndpointDescriptorsLength));
+
+ OedConfigLength = NhltOedConfigConstructor (Table);
+ DEBUG ((DEBUG_INFO, "NhltConstructor: OedConfigLength = %d B\n", OedConfigLength));
+
+ TableSize = EndpointDescriptorsLength + OedConfigLength;
+
+ *NhltTableSize = TableSize;
+ *NhltTable = Table;
+
+ return Status;
+}
+
+/**
+ Constructs EFI_ACPI_DESCRIPTION_HEADER structure for NHLT table.
+
+ @param[in][out] *NhltTable NHLT table for which header will be created
+ @param[in] NhltTableSize Size of NHLT table
+
+ @retval None
+**/
+VOID
+NhltAcpiHeaderConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable,
+ IN UINT32 NhltTableSize
+ )
+{
+ DEBUG ((DEBUG_INFO, "NhltAcpiHeaderConstructor() Start\n"));
+
+ // Header
+ NhltTable->Header.Signature = NHLT_ACPI_TABLE_SIGNATURE;
+ NhltTable->Header.Length = (UINT32) (NhltTableSize + sizeof (NHLT_ACPI_TABLE) - sizeof (ENDPOINT_DESCRIPTOR) - sizeof (SPECIFIC_CONFIG));
+ NhltTable->Header.Revision = 0x0;
+ NhltTable->Header.Checksum = 0x0;
+
+ CopyMem (NhltTable->Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (NhltTable->Header.OemId));
+ NhltTable->Header.OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+ NhltTable->Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
+ NhltTable->Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
+ NhltTable->Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+
+ DEBUG ((DEBUG_INFO, "NhltAcpiHeaderConstructor(), NhltAcpiTable->Header.Length = %d B\n", NhltTable->Header.Length));
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c
new file mode 100644
index 0000000000..46096a0ac3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c
@@ -0,0 +1,336 @@
+/** @file
+ This file contains HD Audio NHLT Configuration BLOBs
+
+Copyright (c) 2017, 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 that 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.
+
+**/
+
+//
+// DMIC Configuration BLOBs
+//
+// DMIC Config 2 channels, 16 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicStereo16BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x00300003, 0x00300003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicStereo16BitFormatConfigSize = sizeof (DmicStereo16BitFormatConfig);
+
+// DMIC Config 2 channels, 32 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicStereo32BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x00380003, 0x00380003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicStereo32BitFormatConfigSize = sizeof (DmicStereo32BitFormatConfig);
+
+// DMIC Config 4 channels, 16 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicQuad16BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x00320003, 0x00320003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicQuad16BitFormatConfigSize = sizeof (DmicQuad16BitFormatConfig);
+
+// DMIC Config 4 channels, 32 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicQuad32BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x003a0003, 0x003a0003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicQuad32BitFormatConfigSize = sizeof (DmicQuad32BitFormatConfig);
+
+// DMIC Config 1 channel, 16 bits
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicMono16BitFormatConfig[] =
+{
+ 0x00000000,
+ 0xfffffff0,0xfffffff0,0xfffffff0,0xfffffff0,
+ 3,
+ 3,
+ 0x00300003,
+ 0x00300003,
+ 0x3,
+ 0x0, 0x09001303, 0x0, 0x0301, 0, 0, 0, 0,
+ 0x10, 0x402a0, 0, 0, 0, 0, 0, 0,
+ 0x10, 0xe03ae, 0, 0, 0, 0, 0, 0,
+ 0x00008, 0xfffae, 0xfff12, 0xffdfb, 0xffc61, 0xffa5a, 0xff82b, 0xff641, 0xff520, 0xff544, 0xff6f4, 0xffa25, 0xffe65,
+ 0x002e0, 0x0068f, 0x00876, 0x007f1, 0x004f5, 0x0002a, 0xffad4, 0xff68a, 0xff4bf, 0xff64f, 0xffb20,
+ 0x0020f, 0x00929, 0x00e2d, 0x00f40, 0x00b92, 0x003bf, 0xff9cd, 0xff0b0, 0xfeb6e, 0xfec2a, 0xff351,
+ 0xfff4f, 0x00ccd, 0x0179d, 0x01bfc, 0x017d7, 0x00ba3, 0xffa7e, 0xfe96f, 0xfddf5, 0xfdc4d, 0xfe5ee,
+ 0xff8ce, 0x00fb7, 0x023a8, 0x02df5, 0x02a74, 0x01910, 0xffe2c, 0xfe19c, 0xfcc64, 0xfc5ee, 0xfd17e,
+ 0xfecd4, 0x01071, 0x03198, 0x0457e, 0x044c9, 0x02e24, 0x00728, 0xfdb0e, 0xfb781, 0xfa86b, 0xfb408,
+ 0xfd884, 0x00c02, 0x03f37, 0x061e8, 0x06807, 0x04dc5, 0x01954, 0xfd98c, 0xfa1c8, 0xf840f, 0xf8b52,
+ 0xfb78c, 0xffd23, 0x047db, 0x080b1, 0x094e3, 0x07c08, 0x03b41, 0xfe45e, 0xf9101, 0xf5b1e, 0xf54f4,
+ 0xf8307, 0xfda0b, 0x0418f, 0x09ad0, 0x0c9d6, 0x0be16, 0x0780b, 0x009dd, 0xf92ba, 0xf3606, 0xf10ed,
+ 0xf315e, 0xf9135, 0x0172c, 0x09d83, 0x0fc9e, 0x11695, 0x0e05b, 0x065bf, 0xfc6ed, 0xf2ff4, 0xecc96,
+ 0xebbc9, 0xf0668, 0xf9be7, 0x05601, 0x1029e, 0x17140, 0x18065, 0x12728, 0x07874, 0xf9edb, 0xed202,
+ 0xe486c, 0xe294d, 0xe820f, 0xf424a, 0x03f29, 0x13d68, 0x1ff61, 0x253b2, 0x220fa, 0x16be1, 0x05638,
+ 0xf1798, 0xdf165, 0xd211a, 0xcd3f9, 0xd1eb5, 0xdfa89, 0xf4802, 0x0d656, 0x26d63, 0x3d808, 0x4ecc3,
+ 0x59315, 0x5c520, 0x58db6, 0x503d6, 0x444dd, 0x36ecb, 0x29b9a, 0x1de5d, 0x14234, 0x0cae0, 0x07669,
+ 0x03f40, 0x01e4e, 0x00c95, 0x0043b, 0x000f9,0xff961, 0x00823, 0x0084f, 0x00a39, 0x00d21, 0x010a8, 0x0149a, 0x018cc, 0x01d15, 0x0214d, 0x02543, 0x028c8, 0x02baa,
+ 0x02db8, 0x02ec6, 0x02eac, 0x02d4c, 0x02a90, 0x02672, 0x020f9, 0x01a3b, 0x0125c, 0x00994, 0x00025,
+ 0xff662, 0xfeca3, 0xfe34c, 0xfdabe, 0xfd364, 0xfcd94, 0xfc9a4, 0xfc7dd, 0xfc86b, 0xfcb6e, 0xfd0e6,
+ 0xfd8bb, 0xfe2b9, 0xfee8f, 0xffbd5, 0x00a0c, 0x018a3, 0x026fc, 0x03474, 0x04065, 0x04a36, 0x0515a,
+ 0x0555a, 0x055df, 0x052b2, 0x04bc3, 0x0412c, 0x03332, 0x02242, 0x00ef3, 0xff9fb, 0xfe430, 0xfce78,
+ 0xfb9c6, 0xfa70f, 0xf973a, 0xf8b1e, 0xf836e, 0xf80b7, 0xf8355, 0xf8b6e, 0xf98ea, 0xfab78, 0xfc288,
+ 0xfdd52, 0xffadf, 0x01a0a, 0x03992, 0x05823, 0x07465, 0x08d0c, 0x0a0e3, 0x0aedc, 0x0b61f, 0x0b614,
+ 0x0ae6b, 0x09f23, 0x0888d, 0x06b4c, 0x04850, 0x020d3, 0xff647, 0xfca4f, 0xf9eae, 0xf7533, 0xf4fa8,
+ 0xf2fc0, 0xf1702, 0xf06ba, 0xeffe6, 0xf032d, 0xf10d3, 0xf28b4, 0xf4a42, 0xf7486, 0xfa62a, 0xfdd81,
+ 0x01896, 0x0553d, 0x09128, 0x0c9fe, 0x0fd6f, 0x1294e, 0x14ba5, 0x162cb, 0x16d75, 0x16ac4, 0x15a52,
+ 0x13c38, 0x1110d, 0x0d9e9, 0x09856, 0x04e4a, 0xffe17, 0xfaa51, 0xf55c4, 0xf0350, 0xeb5d6, 0xe7020,
+ 0xe34c8, 0xe0620, 0xde61c, 0xdd64b, 0xdd7bd, 0xdeb03, 0xe102a, 0xe46b5, 0xe8dab, 0xee397, 0xf4699,
+ 0xfb479, 0x02ab3, 0x0a691, 0x1253c, 0x1a3d9, 0x21f98, 0x295cc, 0x30400, 0x36803, 0x3bff8, 0x40a63,
+ 0x44628, 0x4729b, 0x48f76, 0x49cd2, 0x49b35, 0x48b71, 0x46ea5, 0x44632, 0x413a6, 0x3d8b3, 0x3971b,
+ 0x350a6, 0x30716, 0x2bc15, 0x27131, 0x227cb, 0x1e11d, 0x19e2a, 0x15fc1, 0x1267c, 0x0f2c0, 0x0c4c2,
+ 0x09c8b, 0x079fb, 0x05cd2, 0x044b2, 0x0312d, 0x021c5, 0x015f4, 0x0135e,
+ 0x0, 0x09001303, 0x0, 0x0301, 0, 0, 0, 0,
+ 0x10, 0x402a0, 0, 0, 0, 0, 0, 0,
+ 0x10, 0xe03ae, 0, 0, 0, 0, 0, 0,
+ 0x00008, 0xfffae, 0xfff12, 0xffdfb, 0xffc61, 0xffa5a, 0xff82b, 0xff641, 0xff520, 0xff544, 0xff6f4, 0xffa25, 0xffe65,
+ 0x002e0, 0x0068f, 0x00876, 0x007f1, 0x004f5, 0x0002a, 0xffad4, 0xff68a, 0xff4bf, 0xff64f, 0xffb20,
+ 0x0020f, 0x00929, 0x00e2d, 0x00f40, 0x00b92, 0x003bf, 0xff9cd, 0xff0b0, 0xfeb6e, 0xfec2a, 0xff351,
+ 0xfff4f, 0x00ccd, 0x0179d, 0x01bfc, 0x017d7, 0x00ba3, 0xffa7e, 0xfe96f, 0xfddf5, 0xfdc4d, 0xfe5ee,
+ 0xff8ce, 0x00fb7, 0x023a8, 0x02df5, 0x02a74, 0x01910, 0xffe2c, 0xfe19c, 0xfcc64, 0xfc5ee, 0xfd17e,
+ 0xfecd4, 0x01071, 0x03198, 0x0457e, 0x044c9, 0x02e24, 0x00728, 0xfdb0e, 0xfb781, 0xfa86b, 0xfb408,
+ 0xfd884, 0x00c02, 0x03f37, 0x061e8, 0x06807, 0x04dc5, 0x01954, 0xfd98c, 0xfa1c8, 0xf840f, 0xf8b52,
+ 0xfb78c, 0xffd23, 0x047db, 0x080b1, 0x094e3, 0x07c08, 0x03b41, 0xfe45e, 0xf9101, 0xf5b1e, 0xf54f4,
+ 0xf8307, 0xfda0b, 0x0418f, 0x09ad0, 0x0c9d6, 0x0be16, 0x0780b, 0x009dd, 0xf92ba, 0xf3606, 0xf10ed,
+ 0xf315e, 0xf9135, 0x0172c, 0x09d83, 0x0fc9e, 0x11695, 0x0e05b, 0x065bf, 0xfc6ed, 0xf2ff4, 0xecc96,
+ 0xebbc9, 0xf0668, 0xf9be7, 0x05601, 0x1029e, 0x17140, 0x18065, 0x12728, 0x07874, 0xf9edb, 0xed202,
+ 0xe486c, 0xe294d, 0xe820f, 0xf424a, 0x03f29, 0x13d68, 0x1ff61, 0x253b2, 0x220fa, 0x16be1, 0x05638,
+ 0xf1798, 0xdf165, 0xd211a, 0xcd3f9, 0xd1eb5, 0xdfa89, 0xf4802, 0x0d656, 0x26d63, 0x3d808, 0x4ecc3,
+ 0x59315, 0x5c520, 0x58db6, 0x503d6, 0x444dd, 0x36ecb, 0x29b9a, 0x1de5d, 0x14234, 0x0cae0, 0x07669,
+ 0x03f40, 0x01e4e, 0x00c95, 0x0043b, 0x000f9,0xff961, 0x00823, 0x0084f, 0x00a39, 0x00d21, 0x010a8, 0x0149a, 0x018cc, 0x01d15, 0x0214d, 0x02543, 0x028c8, 0x02baa,
+ 0x02db8, 0x02ec6, 0x02eac, 0x02d4c, 0x02a90, 0x02672, 0x020f9, 0x01a3b, 0x0125c, 0x00994, 0x00025,
+ 0xff662, 0xfeca3, 0xfe34c, 0xfdabe, 0xfd364, 0xfcd94, 0xfc9a4, 0xfc7dd, 0xfc86b, 0xfcb6e, 0xfd0e6,
+ 0xfd8bb, 0xfe2b9, 0xfee8f, 0xffbd5, 0x00a0c, 0x018a3, 0x026fc, 0x03474, 0x04065, 0x04a36, 0x0515a,
+ 0x0555a, 0x055df, 0x052b2, 0x04bc3, 0x0412c, 0x03332, 0x02242, 0x00ef3, 0xff9fb, 0xfe430, 0xfce78,
+ 0xfb9c6, 0xfa70f, 0xf973a, 0xf8b1e, 0xf836e, 0xf80b7, 0xf8355, 0xf8b6e, 0xf98ea, 0xfab78, 0xfc288,
+ 0xfdd52, 0xffadf, 0x01a0a, 0x03992, 0x05823, 0x07465, 0x08d0c, 0x0a0e3, 0x0aedc, 0x0b61f, 0x0b614,
+ 0x0ae6b, 0x09f23, 0x0888d, 0x06b4c, 0x04850, 0x020d3, 0xff647, 0xfca4f, 0xf9eae, 0xf7533, 0xf4fa8,
+ 0xf2fc0, 0xf1702, 0xf06ba, 0xeffe6, 0xf032d, 0xf10d3, 0xf28b4, 0xf4a42, 0xf7486, 0xfa62a, 0xfdd81,
+ 0x01896, 0x0553d, 0x09128, 0x0c9fe, 0x0fd6f, 0x1294e, 0x14ba5, 0x162cb, 0x16d75, 0x16ac4, 0x15a52,
+ 0x13c38, 0x1110d, 0x0d9e9, 0x09856, 0x04e4a, 0xffe17, 0xfaa51, 0xf55c4, 0xf0350, 0xeb5d6, 0xe7020,
+ 0xe34c8, 0xe0620, 0xde61c, 0xdd64b, 0xdd7bd, 0xdeb03, 0xe102a, 0xe46b5, 0xe8dab, 0xee397, 0xf4699,
+ 0xfb479, 0x02ab3, 0x0a691, 0x1253c, 0x1a3d9, 0x21f98, 0x295cc, 0x30400, 0x36803, 0x3bff8, 0x40a63,
+ 0x44628, 0x4729b, 0x48f76, 0x49cd2, 0x49b35, 0x48b71, 0x46ea5, 0x44632, 0x413a6, 0x3d8b3, 0x3971b,
+ 0x350a6, 0x30716, 0x2bc15, 0x27131, 0x227cb, 0x1e11d, 0x19e2a, 0x15fc1, 0x1267c, 0x0f2c0, 0x0c4c2,
+ 0x09c8b, 0x079fb, 0x05cd2, 0x044b2, 0x0312d, 0x021c5, 0x015f4, 0x0135e
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicMono16BitFormatConfigSize = sizeof (DmicMono16BitFormatConfig);
+
+//
+// I2S Configuration BLOBs
+// Audio Format and Configuration details
+//
+// Frequency: 48kHz, PCM resolution: 24 bits
+// TDM slots: 4
+// Codec: Realtek ALC298, mode: slave
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sRtk298Render4ch48kHz24bitFormatConfig[] = {0x0, 0xffffff10, 0xffffff32, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0x83d00437, 0xc0700000, 0x0, 0x02010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0x00000001, 0x00000fff};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRtk298Render4ch48kHz24bitFormatConfigSize = sizeof (I2sRtk298Render4ch48kHz24bitFormatConfig);
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sRtk298Capture4ch48kHz24bitFormatConfig[] = {0x0, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0x83d00437, 0xc0700000, 0x0, 0x02010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0x00000001, 0x00000fff};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRtk298Capture4ch48kHz24bitFormatConfigSize = sizeof (I2sRtk298Capture4ch48kHz24bitFormatConfig);
+
+// Audio Format: 48kHz, 2channels, master clock
+// Codec: Realtek ALC286S
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sRtk286S2ch48kHzFormatConfig[] = { 0, 0xffffff10, 0xffffff32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x83d00437, 0xc0700000, 0x0, 0x2990000, 0xf, 0xf, 0x4002, 0x0, 0x7070f00, 0x20, 0x1, 0xfff };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRtk286S2ch48kHzFormatConfigSize = sizeof (I2sRtk286S2ch48kHzFormatConfig);
+
+// Audio Format: 48kHz, 4 channels
+// Codec: ADI SSM4567
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sAdi4ch48kHzFormatConfig[] = { 0, 0xffffff10, 0xffffff32, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0x83d00437, 0xc0700000, 0x0, 0x2010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0, 0 };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sAdi4ch48kHzFormatConfigSize = sizeof (I2sAdi4ch48kHzFormatConfig);
+
+// Audio Format: 24bit, 48kHz, Master
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2s48kHz24bitMasterFormatConfig[] = { 0, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0x81d00937, 0xc0700000, 0x0, 0x02990000, 0x3, 0x3, 0x4002, 0x0, 0x7070f00, 0x20, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2s48kHz24bitMasterFormatConfigSize = sizeof (I2s48kHz24bitMasterFormatConfig);
+
+// Audio Format: 24bit, 48kHz, Slave
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2s48kHz24bitSlaveFormatConfig[] = { 0, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0x81d00037, 0xd3700000, 0x0, 0x02000000, 0x3, 0x3, 0x4002, 0x0, 0x7070f00, 0x00, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2s48kHz24bitSlaveFormatConfigSize = sizeof (I2s48kHz24bitSlaveFormatConfig);
+
+// Audio Format: PCM 16bit, 8kHz, Master
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sPcm8kHz16bitMasterFormatConfig[] = { 0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0x80c0953f, 0xc0400000, 0x0, 0x02010004, 0x1, 0x1, 0x4002, 0x4, 0x7020000, 0x20, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sPcm8kHz16bitMasterFormatConfigSize = sizeof (I2sPcm8kHz16bitMasterFormatConfig);
+
+// Audio Format: PCM 16bit, 8kHz, Slave
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sPcm8kHz16bitSlaveFormatConfig[] = { 0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0x80c0003f, 0xd3400000, 0x0, 0x02000004, 0x1, 0x1, 0x4002, 0x0, 0x7020000, 0x00, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sPcm8kHz16bitSlaveFormatConfigSize = sizeof (I2sPcm8kHz16bitSlaveFormatConfig);
+
+//
+// BlueTooth Configuration BLOBs
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 BtFormatConfig[] =
+{
+ 0x0, 0xfffffff0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x80c0003f, 0xd3400000, 0x0, 0x02000005, 0x01, 0x01, 0x4002,
+ 0x0, 0x07020000, 0x0, 0x01, 0x0
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 BtFormatConfigSize = sizeof (BtFormatConfig);
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c
new file mode 100644
index 0000000000..32814bf773
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c
@@ -0,0 +1,545 @@
+/** @file
+ Implement the I2C controller driver.
+
+Copyright (c) 2017, 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 that 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 <Uefi.h>
+#include <Base.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiLib.h>
+#include <PchAccess.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/I2cMaster.h>
+#include <Pi/PiI2c.h>
+#include <Library/DevicePathLib.h>
+#include <Library/I2cMasterCommonLib.h>
+
+/**
+ Prepare I2c controller for use: enable its mmio range, put in D0, get out of reset
+
+ @param[in] Context - driver context
+**/
+VOID
+PrepareController (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ MmioOr32 (Context->ConfigAddress + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ MmioAnd32 (Context->ConfigAddress + R_PCH_SERIAL_IO_PME_CTRL_STS, (UINT32) (~B_PCH_SERIAL_IO_PME_CTRL_STS_PWR_ST));
+ MmioOr32 (Context->MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA);
+}
+
+/**
+ Determine the state of the I2C controller
+
+ @param[in] Context - driver context
+
+ @retval TRUE The I2C controller is active
+ @retval FALSE The I2C controller is idle
+**/
+BOOLEAN
+IsHardwareActive (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ return (MmioRead32 (Context->MmioAddress + R_IC_STATUS) & B_IC_STATUS_ACTIVITY );
+}
+
+/**
+ Updates WriteOperation and WritePosition, two variables that determine
+ which part of Request is being committed to I2C bus.
+ This iterates over both Read and Write operations from a request, because
+ things that need to be written to WriteFifo are both I2c bus writes
+ and I2c bus reads (the command to perform bus read needs to be put into Write Fifo)
+
+ @param[in] Context - driver context
+**/
+VOID
+UpdateWritePosition (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ( Context->WritePos == Context->Request->Operation[Context->WriteOp].LengthInBytes - 1) {
+ Context->WritePos = 0;
+ Context->WriteOp ++;
+ } else {
+ Context->WritePos ++;
+ }
+}
+
+/*
+ FindReadOp checks if current Operation is of Read type. If so, returns.
+ If not, increases ReadOp until it finds one or goes beyond Request's OperationCount
+
+ @param[in] Context - driver context
+*/
+VOID
+FindReadOp (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ while (Context->ReadOp < Context->Request->OperationCount &&
+ !(Context->Request->Operation[Context->ReadOp].Flags & I2C_FLAG_READ)) {
+ Context->ReadOp++;
+ }
+}
+
+/**
+ Updates ReadOperation and ReadPosition, two variables that determine
+ which part of Request is being filled with data incoming from I2C reads.
+ This iterates only over Read operations from a request.
+
+ @param[in] Context - driver context
+**/
+VOID
+UpdateReadPosition (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ( Context->ReadPos == Context->Request->Operation[Context->ReadOp].LengthInBytes - 1) {
+ Context->ReadPos = 0;
+ Context->ReadOp ++;
+ FindReadOp (Context);
+ } else {
+ Context->ReadPos ++;
+ }
+}
+
+/**
+ ValidateRequest checks if Request is valid and can be started
+
+ @param[in] Context - driver context
+ @param[in] RequestPacket
+
+ @retval EFI_SUCCESS Request is valid and can be started
+ @retval EFI_ALREADY_STARTED The controller is busy with another transfer
+ @retval EFI_BAD_BUFFER_SIZE Transfer size too big
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL, invalid Operation flags
+ @retval EFI_UNSUPPORTED "ping" operation attempted (0-byte transfer, address byte not followed by any data)
+**/
+EFI_STATUS
+ValidateRequest (
+ I2C_MASTER_CONTEXT *Context,
+ CONST EFI_I2C_REQUEST_PACKET *RequestPacket
+ )
+{
+ UINTN TotalSize;
+ UINTN Operation;
+ UINTN OperationSize;
+
+ if (Context->TransferInProgress) {
+ return EFI_ALREADY_STARTED;
+ }
+ if (RequestPacket == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (RequestPacket->OperationCount == 0) {
+ // 0-size operations ("pings") not supported
+ return EFI_UNSUPPORTED;
+ }
+
+ TotalSize = 0;
+
+ for (Operation=0; Operation < RequestPacket->OperationCount; Operation++) {
+ // unsupported flags?
+ if ((RequestPacket->Operation[Operation].Flags & (~I2C_FLAG_READ)) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ OperationSize = RequestPacket->Operation[Operation].LengthInBytes;
+ // 0-size operations ("pings") not supported
+ if (OperationSize == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ TotalSize += OperationSize;
+ // read operation too big?
+ if (RequestPacket->Operation[Operation].Flags & I2C_FLAG_READ) {
+ if (OperationSize > Context->Capabilities.MaximumReceiveBytes) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ // write operation too big?
+ } else {
+ if (OperationSize > Context->Capabilities.MaximumTransmitBytes) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ }
+ }
+ // total request too big?
+ if (TotalSize > Context->Capabilities.MaximumTotalBytes) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ IsLastFromRequest checks if WritePos and WriteOp point to the last byte of the request
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsLastFromRequest (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ((Context->WriteOp == Context->Request->OperationCount - 1 ) &&
+ (Context->WritePos == Context->Request->Operation[Context->WriteOp].LengthInBytes - 1)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ IsFirstFromOperation checks if WritePos and WriteOp point to the first byte of an operation
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsFirstFromOperation (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ((Context->WriteOp != 0) && (Context->WritePos == 0)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ InitializeTransfer checks if HW is ready to accept new transfer.
+ If so, sets up slave address
+
+ @param[in] Context - driver context
+
+ @retval Status
+**/
+EFI_STATUS
+InitializeTransfer (
+ I2C_MASTER_CONTEXT *Context,
+ UINTN SlaveAddress,
+ CONST EFI_I2C_REQUEST_PACKET *RequestPacket
+ )
+{
+ UINT32 Attempts = 10000;
+ UINT32 Address;
+
+ Context->Request = (EFI_I2C_REQUEST_PACKET*) RequestPacket;
+ Context->TransferStatus = EFI_SUCCESS;
+ Context->WriteOp = 0;
+ Context->WritePos = 0;
+ Context->ReadOp = 0;
+ FindReadOp (Context);
+ Context->ReadPos = 0;
+
+ if (MmioRead32 (Context->MmioAddress + R_IC_ENABLE) != 0) {
+ DEBUG (( DEBUG_ERROR, "Address change was attempted while a transfer was underway!\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Address = SlaveAddress & 0xFF;
+ if (SlaveAddress & I2C_ADDRESSING_10_BIT
+ ) {
+ Address |= B_IC_TAR_10BITADDR_MASTER;
+ }
+ MmioWrite32 (Context->MmioAddress + R_IC_TAR, Address);
+ MmioWrite32 (Context->MmioAddress + R_IC_ENABLE, B_IC_EN );
+ //clear errors
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_TX_ABRT);
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_INTR);
+
+ while ( !(MmioRead32 (Context->MmioAddress + R_IC_ENABLE_STATUS ) & B_IC_EN)) {
+ //should never happen, but just to make sure BIOS doesn't hang in infinite loop...
+ MicroSecondDelay (1);
+ if (--Attempts == 0) {
+ MmioWrite32 (Context->MmioAddress + R_IC_ENABLE, 0 );
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ Context->TransferInProgress = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ WriteFifo writes to I2c controller's transmit Fifo. Data written to Fifo could be
+ - data bytes to be written to an i2c slave
+ - read requests that trigger i2c bus reads
+ First transfer from each operation adds Restart bit which triggers Restart condition on bus
+ Last transfer from the whole Request adds Stop bit which triggers Stop condtion on bus
+ Driver keeps track of which parts of Request were already committed to hardware using
+ pointer consisting of WritePosition and WriteOperation variables. This pointer is updated
+ every time data byte/read request is committed to FIFO
+ WriteFifo executes while there's anything more to write and the write fifo isn't full
+
+ @param[in] Context - driver context
+**/
+VOID
+WriteFifo (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ UINT32 Data;
+ while ( MmioRead32 (Context->MmioAddress + R_IC_STATUS ) & B_IC_STATUS_TFNF) {
+ if (Context->WriteOp >= Context->Request->OperationCount ) {
+ return; // request complete, nothing more to write
+ }
+
+ if (Context->Request->Operation[Context->WriteOp].Flags & I2C_FLAG_READ) {
+ Data = B_IC_CMD_READ;
+ } else {
+ Data = Context->Request->Operation[Context->WriteOp].Buffer[Context->WritePos];
+ }
+ if (IsLastFromRequest (Context)) {
+ Data |= B_IC_CMD_STOP;
+ }
+ if (IsFirstFromOperation (Context)) {
+ Data |= B_IC_CMD_RESTART;
+ }
+ MmioWrite32 (Context->MmioAddress + R_IC_DATA_CMD, Data);
+ UpdateWritePosition (Context);
+ }
+}
+
+/**
+ ReadFifo reads from I2c controller's receive Fifo. It contains data retrieved
+ from slave device as a result of executing read transfers, which were
+ triggered by putting read requests into Write Fifo. Retrieved data is copied into buffers
+ pointed to by Request structure.
+ Driver keeps track where to copy incoming data using pointer consisting of
+ ReadPosition and ReadOperation variables. This pointer is updated
+ every time data was retrieved from hardware
+ ReadFifo executes while there's data available and receive buffers were not filled
+
+ @param[in] Context - driver context
+**/
+VOID
+ReadFifo (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ while ( MmioRead32 ( Context->MmioAddress + R_IC_STATUS ) & B_IC_STATUS_RFNE) {
+ if ( Context->ReadOp >= Context->Request->OperationCount ) {
+ return;
+ }
+ Context->Request->Operation[Context->ReadOp].Buffer[Context->ReadPos] = (0xFF & MmioRead32 (Context->MmioAddress + R_IC_DATA_CMD));
+ UpdateReadPosition (Context);
+ }
+}
+
+/**
+ CheckErrors checks if there were any transfer errors.
+
+ @param[in] Context - driver context
+**/
+VOID
+CheckErrors (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if (!(MmioRead32 (Context->MmioAddress + R_IC_INTR_STAT) & B_IC_INTR_TX_ABRT)) {
+ return;
+ }
+ if (MmioRead32 (Context->MmioAddress + R_IC_TX_ABRT_SOURCE) & B_IC_TX_ABRT_7B_ADDR_NACK) {
+ Context->TransferStatus = EFI_NO_RESPONSE;
+ } else {
+ Context->TransferStatus = EFI_DEVICE_ERROR;
+ }
+ DEBUG (( DEBUG_INFO, "I2c CheckErrors: %08x\n", MmioRead32 (Context->MmioAddress + R_IC_TX_ABRT_SOURCE)));
+}
+
+/**
+ Transfer is finished when all requested operations were placed in fifo,
+ all read requests were filled and hardware is inactive
+ The last part is necessary for write-only transfers where after
+ placing all writes in fifo sw needs to wait until they flush down the bus
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsTransferFinished (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if (( Context->WriteOp >= Context->Request->OperationCount ) &&
+ ( Context->ReadOp >= Context->Request->OperationCount ) &&
+ !IsHardwareActive (Context)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/*
+ Clean up Hw activity and errors
+ Return status to Request's submitter and signal the event that tells
+ it that the request is complete
+ Clear up Sw context to allow new request to start
+
+ @param[in] Context - driver context
+*/
+VOID
+FinishTransfer (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ UINT32 Attempts = 10000;
+
+ MmioWrite32 ( Context->MmioAddress + R_IC_ENABLE, 0 );
+
+ while ( MmioRead32 ( Context->MmioAddress + R_IC_ENABLE_STATUS ) & B_IC_EN ) {
+ //try for 1ms; should take no more than 100us even at slowest bus speed, but just to make sure BIOS doesn't hang in infinite loop
+ MicroSecondDelay ( 1 );
+ if (--Attempts == 0) {
+ ASSERT (FALSE);
+ break;
+ }
+ }
+
+ //
+ //clear errors
+ //
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_TX_ABRT);
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_INTR);
+
+ //
+ //clean up context data
+ //
+ Context->TransferInProgress = FALSE;
+}
+
+/**
+ PerformTransfer. For synchronous transfer this function is called in a loop
+ and for asynchronous transfers, as a timer callback. It writes data and/or
+ read requests to hadrware, copies read data to destination buffers. When
+ transfer completes, it cleans up Sw context and Hw registers in preparation
+ for new transfer
+
+ @param[in] Context - driver context
+**/
+VOID
+PerformTransfer (
+ IN I2C_MASTER_CONTEXT *Context
+ )
+{
+ if (!Context->TransferInProgress) {
+ return;
+ }
+ if (EFI_ERROR (Context->TransferStatus) || IsTransferFinished (Context)) {
+ FinishTransfer (Context);
+ return;
+ }
+ WriteFifo (Context);
+ ReadFifo (Context);
+ CheckErrors (Context);
+}
+
+
+/**
+ Set the I2C controller bus clock frequency.
+
+ This routine must be called at or below TPL_NOTIFY.
+
+ The software and controller do a best case effort of using the specified
+ frequency for the I2C bus. If the frequency does not match exactly then
+ the controller will use lower frequency for the I2C to avoid exceeding
+ the operating conditions for any of the I2C devices on the bus.
+ For example if 400 KHz was specified and the controller's divide network
+ only supports 402 KHz or 398 KHz then the controller would be set to 398
+ KHz.
+
+ @param[in] MmioAddress Address of I2C controller
+ @param[in] BusClockHertz New I2C bus clock frequency in Hertz
+
+ @retval EFI_SUCCESS The bus frequency was set successfully.
+ @retval EFI_UNSUPPORTED The controller does not support this frequency.
+**/
+
+EFI_STATUS
+FrequencySet (
+ IN UINTN MmioAddress,
+ IN OUT UINTN *BusClockHertz
+ )
+{
+ UINT32 Speed;
+
+ if ( *BusClockHertz < 100*1000) {
+ //can't run that slowly
+ return EFI_UNSUPPORTED;
+ } else if ( *BusClockHertz < 400*1000) {
+ //for any request in range [100kHz, 400kHz), set 100kHz
+ *BusClockHertz = 100000;
+ Speed = V_IC_SPEED_STANDARD;
+ MmioWrite32 ( MmioAddress + R_IC_SDA_HOLD, 0x001C001C);
+ MmioWrite32 ( MmioAddress + R_IC_SS_SCL_HCNT, 528);
+ MmioWrite32 ( MmioAddress + R_IC_SS_SCL_LCNT, 640);
+ } else if ( *BusClockHertz < 1000*1000) {
+ //for any request in range [400kHz, 1MHz), set 400kHz
+ *BusClockHertz = 400000;
+ Speed = V_IC_SPEED_FAST;
+ MmioWrite32 ( MmioAddress + R_IC_SDA_HOLD, 0x001C001C);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_HCNT, 128);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_LCNT, 160);
+ } else {
+ //for any request in range [1MHz, +inf), set 1MHz. This silicon doesn't support 3.4MHz mode.
+ *BusClockHertz = 1000000;
+ Speed = V_IC_SPEED_FAST;
+ MmioWrite32 ( MmioAddress + R_IC_SDA_HOLD, 0x00280028);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_HCNT, 30);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_LCNT, 80);
+ }
+
+ MmioWrite32 ( MmioAddress + R_IC_CON, Speed | B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_IC_MASTER_MODE);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reset the I2C controller
+
+ @param[in] MmioAddress Address of I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+I2cReset (
+ IN UINTN MmioAddress
+ )
+{
+ MmioAnd32 (
+ MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS,
+ (UINT32) ~(B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA)
+ );
+ MmioRead32 (MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS);
+ MmioOr32 (
+ MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA
+ );
+ MmioRead32 (MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS);
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf
new file mode 100644
index 0000000000..a6af85a4a0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Component description file for the I2C port driver.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeI2cMasterCommonLib
+FILE_GUID = D0E4E669-D467-42af-93D8-21513E226EEA
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = I2cMasterCommonLib
+
+
+[LibraryClasses]
+DebugLib
+PchSerialIoLib
+MmPciLib
+IoLib
+PciLib
+MmPciLib
+TimerLib
+PchInfoLib
+
+
+[Packages]
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+MdePkg/MdePkg.dec
+
+
+[Sources]
+I2cMasterCommonLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c
new file mode 100644
index 0000000000..89bf0a73ee
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c
@@ -0,0 +1,305 @@
+/** @file
+ This file contains routines for GPIO native and chipset specific purpose
+ used by Reference Code only.
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/PchInfoLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+
+//
+// Chipset specific data
+//
+//ISH
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshGPGpio[PCH_ISH_MAX_GP_PINS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshGPGpio[PCH_ISH_MAX_GP_PINS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER];
+
+
+//PCIe SRCCLKREQB
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpPcieSrcClkReqbPinToGpioMap[PCH_LP_PCIE_MAX_CLK_REQ];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHPcieSrcClkReqbPinToGpioMap[PCH_H_PCIE_MAX_CLK_REQ];
+
+//PCH_HOT
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpPchHotbPin;
+extern GPIO_PAD_NATIVE_FUNCTION mPchHPchHotbPin;
+
+//CPU GP
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpCpuGpPinMap[4];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHCpuGpPinMap[4];
+
+/**
+ This function sets ISH I2C controller pins into native mode
+
+ @param[in] IshI2cControllerNumber I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshI2cPinsIntoNativeMode (
+ IN UINT32 IshI2cControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION (*I2cGpio) [PCH_ISH_PINS_PER_I2C_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ I2cGpio = mPchLpIshI2cGpio;
+ } else {
+ I2cGpio = mPchHIshI2cGpio;
+ }
+
+ ASSERT (IshI2cControllerNumber < PCH_ISH_MAX_I2C_CONTROLLERS);
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_I2C_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (I2cGpio[IshI2cControllerNumber][Index].Pad, I2cGpio[IshI2cControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+/**
+ This function sets ISH UART controller pins into native mode
+
+ @param[in] IshUartControllerNumber UART controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshUartPinsIntoNativeMode (
+ IN UINT32 IshUartControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION (*UartGpio) [PCH_ISH_PINS_PER_UART_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ UartGpio = mPchLpIshUartGpio;
+ } else {
+ UartGpio = mPchHIshUartGpio;
+ }
+
+ ASSERT (IshUartControllerNumber < PCH_ISH_MAX_UART_CONTROLLERS);
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_UART_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (UartGpio[IshUartControllerNumber][Index].Pad, UartGpio[IshUartControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+/**
+ This function sets ISH SPI controller pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshSpiPinsIntoNativeMode (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *SpiGpio;
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ SpiGpio = mPchLpIshSpiGpio;
+ } else {
+ SpiGpio = mPchHIshSpiGpio;
+ }
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_SPI_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (SpiGpio[Index].Pad, SpiGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+/**
+ This function sets ISH GP pins into native mode
+
+ @param[in] IshGpPinNumber ISH GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshGpPinsIntoNativeMode (
+ IN UINT32 IshGpPinNumber
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD_NATIVE_FUNCTION *IshGp;
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ IshGp = mPchLpIshGPGpio;
+ } else {
+ IshGp = mPchHIshGPGpio;
+ }
+ ASSERT (IshGpPinNumber < PCH_ISH_MAX_GP_PINS);
+
+ Status = SetGpioPadMode (IshGp[IshGpPinNumber].Pad, IshGp[IshGpPinNumber].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return Status;
+}
+
+/**
+ Returns a pad for given CLKREQ# index.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return CLKREQ# pad.
+**/
+GPIO_PAD
+GpioGetClkreqPad (
+ IN UINT32 ClkreqIndex
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ ASSERT (ClkreqIndex < PCH_LP_PCIE_MAX_CLK_REQ);
+ return mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ } else {
+ ASSERT (ClkreqIndex < PCH_H_PCIE_MAX_CLK_REQ);
+ return mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ }
+}
+
+/**
+ Enables CLKREQ# pad in native mode.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return none
+**/
+VOID
+GpioEnableClkreq (
+ IN UINT32 ClkreqIndex
+ )
+{
+ GPIO_CONFIG PadConfig;
+ GPIO_PAD ClkreqPad;
+ GPIO_PAD_MODE PadMode;
+
+ ZeroMem (&PadConfig, sizeof (PadConfig));
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (ClkreqIndex < PCH_LP_PCIE_MAX_CLK_REQ);
+ ClkreqPad = mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ PadMode = mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Mode;
+ } else {
+ ASSERT (ClkreqIndex < PCH_H_PCIE_MAX_CLK_REQ);
+ ClkreqPad = mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ PadMode = mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Mode;
+ }
+
+ PadConfig.PadMode = PadMode;
+ PadConfig.Direction = GpioDirNone;
+ PadConfig.PowerConfig = GpioHostDeepReset;
+ DEBUG ((DEBUG_INFO, "Enabling CLKREQ%d\n", ClkreqIndex));
+ GpioSetPadConfig (ClkreqPad, &PadConfig);
+}
+
+/**
+ This function checks if GPIO pin for PCHHOTB is in NATIVE MODE
+
+ @param[in] none
+
+ @retval TRUE Pin is in PCHHOTB native mode
+ FALSE Pin is in gpio mode or is not owned by HOST
+**/
+BOOLEAN
+GpioIsPchHotbPinInNativeMode (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD_NATIVE_FUNCTION PchHotbPin;
+ GPIO_PAD_MODE GpioMode;
+
+
+ if (GetPchSeries () == PchLp) {
+ PchHotbPin = mPchLpPchHotbPin;
+ } else {
+ PchHotbPin = mPchHPchHotbPin;
+ }
+
+ Status = GetGpioPadMode (PchHotbPin.Pad, &GpioMode);
+
+ if ((EFI_ERROR (Status)) || (GpioMode != PchHotbPin.Mode)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ This function sets CPU GP pins into native mode
+
+ @param[in] CpuGpPinNum CPU GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCpuGpPinsIntoNativeMode (
+ IN UINT32 CpuGpPinNum
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD_NATIVE_FUNCTION *CpuGpPins;
+
+ if (GetPchSeries () == PchLp) {
+ CpuGpPins = mPchLpCpuGpPinMap;
+ } else {
+ CpuGpPins = mPchHCpuGpPinMap;
+ }
+
+ ASSERT (CpuGpPinNum < 4);
+
+ Status = SetGpioPadMode (CpuGpPins[CpuGpPinNum].Pad, CpuGpPins[CpuGpPinNum].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
new file mode 100644
index 0000000000..b386e071f7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
@@ -0,0 +1,318 @@
+/** @file
+ This file contains GPIO routines for RC usage
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+/**
+ This procedure will get value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[out] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ OUT UINT32 *RegVal
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINTN GroupIndex;
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *RegVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, Offset));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[in] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ IN UINT32 RegVal
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINTN GroupIndex;
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmioWrite32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, Offset), RegVal);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used by PchSmiDispatcher and will return information
+ needed to register GPI SMI. Relation between Index and GpioPad number is:
+ Index = GpioGroup + 24 * GpioPad
+
+ @param[in] Index GPI SMI number
+ @param[out] GpioPin GPIO pin
+ @param[out] GpiSmiBitOffset GPI SMI bit position within GpiSmi Registers
+ @param[out] GpiSmiEnRegAddress Address of GPI SMI Enable register
+ @param[out] GpiSmiStsRegAddress Address of GPI SMI status register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadAndSmiRegs (
+ IN UINT32 Index,
+ OUT GPIO_PAD *GpioPin,
+ OUT UINT8 *GpiSmiBitOffset,
+ OUT UINT32 *GpiSmiEnRegAddress,
+ OUT UINT32 *GpiSmiStsRegAddress
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ GPIO_GROUP GpioGroupOffset;
+ UINTN GpioGroupInfoLength;
+ UINT32 SmiRegOffset;
+
+ GPIO_PAD_OWN PadOwnVal;
+ UINT32 HostOwnVal;
+
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+
+ PadNumber = 0;
+ GroupIndex = 0;
+ for (GroupIndex = 0; GroupIndex < GpioGroupInfoLength; GroupIndex++) {
+ PadNumber = Index;
+ if (PadNumber < GpioGroupInfo[GroupIndex].PadPerGroup) {
+ //
+ // Found group and pad number
+ //
+ break;
+ }
+ Index = Index - GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if selected group has GPI SMI Enable and Status registers
+ //
+ if (GpioGroupInfo[GroupIndex].SmiEnOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH/IE
+ //
+ GpioGetPadOwnership (GpioGetGpioPadFromGroupAndPadNumber (GroupIndex + GpioGroupOffset, PadNumber), &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n",GroupIndex, PadNumber));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check if Host Software Pad Ownership is set to ACPI Mode
+ //
+ GpioGetHostSwOwnershipForPad (GpioGetGpioPadFromGroupAndPadNumber (GroupIndex + GpioGroupOffset, PadNumber), &HostOwnVal);
+ if (HostOwnVal != V_PCH_PCR_GPIO_HOSTSW_OWN_ACPI) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG_CODE_END ();
+
+ *GpioPin = GpioGetGpioPadFromGroupAndPadNumber (GroupIndex + GpioGroupOffset, PadNumber);
+ *GpiSmiBitOffset = (UINT8)(PadNumber % 32);
+
+ SmiRegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset + (PadNumber / 32) * 0x4;
+ *GpiSmiEnRegAddress = PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, SmiRegOffset);
+
+ SmiRegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset + (PadNumber / 32) * 0x4;
+ *GpiSmiStsRegAddress = PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, SmiRegOffset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will clear GPIO_UNLOCK_SMI_STS
+
+ @param[in] None
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearUnlockSmiSts (
+ VOID
+ )
+{
+ UINT16 AcpiBaseAddr;
+
+ PchAcpiBaseGet (&AcpiBaseAddr);
+
+ //
+ // GPIO_UNLOCK_SMI_STS is cleared by writing 1 to it. Other bits in
+ // R_PCH_SMI_STS registers are either RO or RW/1C so writing 0 to them
+ // will not change their state.
+ //
+ IoWrite32 (AcpiBaseAddr + R_PCH_SMI_STS, B_PCH_SMI_STS_GPIO_UNLOCK);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure will set GPIO Driver IRQ number
+
+ @param[in] Irq Irq number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid IRQ number
+**/
+EFI_STATUS
+GpioSetIrq (
+ IN UINT8 Irq
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ //
+ // Check if Irq is 14 or 15
+ //
+ if ((Irq < 14) || (Irq > 15)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data32And = (UINT32) ~(B_PCH_PCR_GPIO_MISCCFG_IRQ_ROUTE);
+ Data32Or = (UINT32) (Irq - 14) << N_PCH_PCR_GPIO_MISCCFG_IRQ_ROUTE;
+
+ //
+ // Program MISCCFG register for Community 0
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM0, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 1
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM1, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 2
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM2, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 3
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM3, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will perform special handling of GPP_A_12 on PCH-LP.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+GpioA12SpecialHandling (
+ VOID
+ )
+{
+ GPIO_PAD_OWN PadOwnVal;
+
+ //
+ // SKL PCH BWG 16.6. PCH-LP GPP_A_12 Special Handling
+ //
+ if (GetPchSeries () == PchLp) {
+ GpioGetPadOwnership (GPIO_SKL_LP_GPP_A12, &PadOwnVal);
+
+ //
+ // If the pad is host-own, BIOS has to always lock this pad after being initialized
+ //
+ if (PadOwnVal == GpioPadOwnHost) {
+ //
+ // Set PadCfgLock for GPP_A_12
+ //
+ GpioLockPadCfg (GPIO_SKL_LP_GPP_A12);
+ }
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c
new file mode 100644
index 0000000000..3d8b128a1c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c
@@ -0,0 +1,200 @@
+/** @file
+ This file contains SKL specific GPIO information
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+
+//
+// ISH GP pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshGPGpio[PCH_ISH_MAX_GP_PINS] =
+{
+ {GPIO_SKL_LP_GPP_A18, GpioPadModeNative1},// ISH_GP_0
+ {GPIO_SKL_LP_GPP_A19, GpioPadModeNative1},// ISH_GP_1
+ {GPIO_SKL_LP_GPP_A20, GpioPadModeNative1},// ISH_GP_2
+ {GPIO_SKL_LP_GPP_A21, GpioPadModeNative1},// ISH_GP_3
+ {GPIO_SKL_LP_GPP_A22, GpioPadModeNative1},// ISH_GP_4
+ {GPIO_SKL_LP_GPP_A23, GpioPadModeNative1},// ISH_GP_5
+ {GPIO_SKL_LP_GPP_A12, GpioPadModeNative2},// ISH_GP_6
+ {GPIO_SKL_LP_GPP_A17, GpioPadModeNative2} // ISH_GP_7
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshGPGpio[PCH_ISH_MAX_GP_PINS] =
+{
+ {GPIO_SKL_H_GPP_A18, GpioPadModeNative1},// ISH_GP_0
+ {GPIO_SKL_H_GPP_A19, GpioPadModeNative1},// ISH_GP_1
+ {GPIO_SKL_H_GPP_A20, GpioPadModeNative1},// ISH_GP_2
+ {GPIO_SKL_H_GPP_A21, GpioPadModeNative1},// ISH_GP_3
+ {GPIO_SKL_H_GPP_A22, GpioPadModeNative1},// ISH_GP_4
+ {GPIO_SKL_H_GPP_A23, GpioPadModeNative1},// ISH_GP_5
+ {GPIO_SKL_H_GPP_A12, GpioPadModeNative2},// ISH_GP_6
+ {GPIO_SKL_H_GPP_A17, GpioPadModeNative1} // ISH_GP_7
+};
+//
+// ISH UART controller pins
+// ISH UART[controller number][pin: RXD/TXD/RTSB/CTSB]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER] =
+{
+ { //UART0
+ {GPIO_SKL_LP_GPP_D13, GpioPadModeNative1},// ISH_UART0_RXD
+ {GPIO_SKL_LP_GPP_D14, GpioPadModeNative1},// ISH_UART0_TXD
+ {GPIO_SKL_LP_GPP_D15, GpioPadModeNative1},// ISH_UART0_RTS
+ {GPIO_SKL_LP_GPP_D16, GpioPadModeNative1} // ISH_UART0_CTS
+ },
+ { //UART1
+ {GPIO_SKL_LP_GPP_C12, GpioPadModeNative2},// ISH_UART1_RXD
+ {GPIO_SKL_LP_GPP_C13, GpioPadModeNative2},// ISH_UART1_TXD
+ {GPIO_SKL_LP_GPP_C14, GpioPadModeNative2},// ISH_UART1_RTSB
+ {GPIO_SKL_LP_GPP_C15, GpioPadModeNative2} // ISH_UART1_CTSB
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER] =
+{
+ { //UART0
+ {GPIO_SKL_H_GPP_D13, GpioPadModeNative1},// ISH_UART0_RXD
+ {GPIO_SKL_H_GPP_D14, GpioPadModeNative1},// ISH_UART0_TXD
+ {GPIO_SKL_H_GPP_D15, GpioPadModeNative1},// ISH_UART0_RTS
+ {GPIO_SKL_H_GPP_D16, GpioPadModeNative1} // ISH_UART0_CTS
+ },
+ { //UART1
+ {GPIO_SKL_H_GPP_C12, GpioPadModeNative2},// ISH_UART1_RXD
+ {GPIO_SKL_H_GPP_C13, GpioPadModeNative2},// ISH_UART1_TXD
+ {GPIO_SKL_H_GPP_C14, GpioPadModeNative2},// ISH_UART1_RTS
+ {GPIO_SKL_H_GPP_C15, GpioPadModeNative2} // ISH_UART1_CTS
+ }
+};
+
+//
+// ISH I2C controller pins
+// ISH I2C[controller number][pin: SDA/SCL]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER] =
+{
+ { //I2C0
+ {GPIO_SKL_LP_GPP_D5, GpioPadModeNative1},// ISH_I2C0_SDA
+ {GPIO_SKL_LP_GPP_D6, GpioPadModeNative1} // ISH_I2C0_SCL
+ },
+ { //I2C1
+ {GPIO_SKL_LP_GPP_D7, GpioPadModeNative1},// ISH_I2C1_SDA
+ {GPIO_SKL_LP_GPP_D8, GpioPadModeNative1} // ISH_I2C1_SCL
+ },
+ { //I2C2
+ {GPIO_SKL_LP_GPP_F10, GpioPadModeNative2},// ISH_I2C2_SDA
+ {GPIO_SKL_LP_GPP_F11, GpioPadModeNative2} // ISH_I2C2_SCL
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER] =
+{
+ { //I2C0
+ {GPIO_SKL_H_GPP_H19, GpioPadModeNative1},// ISH_I2C0_SDA
+ {GPIO_SKL_H_GPP_H20, GpioPadModeNative1} // ISH_I2C0_SCL
+ },
+ { //I2C1
+ {GPIO_SKL_H_GPP_H21, GpioPadModeNative1},// ISH_I2C1_SDA
+ {GPIO_SKL_H_GPP_H22, GpioPadModeNative1} // ISH_I2C1_SCL
+ },
+ { //I2C2
+ {GPIO_SKL_H_GPP_D4, GpioPadModeNative1},// ISH_I2C2_SDA
+ {GPIO_SKL_H_GPP_D23, GpioPadModeNative1} // ISH_I2C2_SCL
+ }
+};
+
+//
+// ISH SPI controller pins
+// ISH SPI[pin: CSB/CLK/MISO/MOSI]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER] =
+{
+ {GPIO_SKL_LP_GPP_D9, GpioPadModeNative1},// ISH_SPI_CSB
+ {GPIO_SKL_LP_GPP_D10, GpioPadModeNative1},// ISH_SPI_CLK
+ {GPIO_SKL_LP_GPP_D11, GpioPadModeNative1},// ISH_SPI_MISO
+ {GPIO_SKL_LP_GPP_D12, GpioPadModeNative1} // ISH_SPI_MOSI
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER] =
+{
+ {GPIO_SKL_H_GPP_D9, GpioPadModeNative1},// ISH_SPI_CSB
+ {GPIO_SKL_H_GPP_D10, GpioPadModeNative1},// ISH_SPI_CLK
+ {GPIO_SKL_H_GPP_D11, GpioPadModeNative1},// ISH_SPI_MISO
+ {GPIO_SKL_H_GPP_D12, GpioPadModeNative1} // ISH_SPI_MOSI
+};
+
+//
+// GPIO pin for PCIE SCRCLKREQB
+// SCRCLKREQB_x -> GPIO pin y
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpPcieSrcClkReqbPinToGpioMap[PCH_LP_PCIE_MAX_CLK_REQ] =
+{
+ {GPIO_SKL_LP_GPP_B5, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B6, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B7, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B8, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B9, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B10, GpioPadModeNative1}
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHPcieSrcClkReqbPinToGpioMap[PCH_H_PCIE_MAX_CLK_REQ] =
+{
+ {GPIO_SKL_H_GPP_B5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B7, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B9, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B10, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H0, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H1, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H2, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H3, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H4, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H7, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H9, GpioPadModeNative1}
+};
+
+//
+// PCHHOTB pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpPchHotbPin = {GPIO_SKL_LP_GPP_B23, GpioPadModeNative2};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHPchHotbPin = {GPIO_SKL_H_GPP_B23, GpioPadModeNative2};
+
+//
+// CPU GP pins
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCpuGpPinMap[4] =
+{
+ {GPIO_SKL_LP_GPP_E3, GpioPadModeNative1}, // CPU_GP_0
+ {GPIO_SKL_LP_GPP_E7, GpioPadModeNative1}, // CPU_GP_1
+ {GPIO_SKL_LP_GPP_B3, GpioPadModeNative1}, // CPU_GP_2
+ {GPIO_SKL_LP_GPP_B4, GpioPadModeNative1}, // CPU_GP_3
+};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHCpuGpPinMap[4] =
+{
+ {GPIO_SKL_H_GPP_E3, GpioPadModeNative1}, // CPU_GP_0
+ {GPIO_SKL_H_GPP_E7, GpioPadModeNative1}, // CPU_GP_1
+ {GPIO_SKL_H_GPP_B3, GpioPadModeNative1}, // CPU_GP_2
+ {GPIO_SKL_H_GPP_B4, GpioPadModeNative1}, // CPU_GP_3
+};
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf
new file mode 100644
index 0000000000..d2542a1673
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file for the PeiDxeSmmGpioPrivateLib
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmGpioPrivateLib
+FILE_GUID = E078A734-BEA0-47CF-A476-3742316D01FC
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioPrivateLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+ PchCycleDecodingLib
+ PchInfoLib
+ GpioLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+ GpioPrivateLib.c
+ GpioNativePrivateLib.c
+ PchSklGpioPrivateData.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c
new file mode 100644
index 0000000000..a49bbc5c18
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c
@@ -0,0 +1,519 @@
+/** @file
+ Pch common library for PCH INIT PEI/DXE/SMM modules
+
+Copyright (c) 2017, 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 that 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 <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <PchPolicyCommon.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchSbiAccessLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/TimerLib.h>
+
+extern CONST PCH_PCIE_CONTROLLER_INFO mPchPcieControllerInfo[];
+extern CONST UINT32 mPchPcieControllerInfoSize;
+
+#define PORT_PLS_TIMEOUT 100 ///< 100 * 10 us = 1ms timeout for USB3 PortSC PLS polling
+
+/**
+ This function returns PID according to PCIe controller index
+
+ @param[in] ControllerIndex PCIe controller index
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+PchGetPcieControllerSbiPid (
+ IN UINT32 ControllerIndex
+ )
+{
+ ASSERT (ControllerIndex < mPchPcieControllerInfoSize);
+ return mPchPcieControllerInfo[ControllerIndex].Pid;
+}
+
+/**
+ This function returns PID according to Root Port Number
+
+ @param[in] RpIndex Root Port Index (0-based)
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+GetRpSbiPid (
+ IN UINTN RpIndex
+ )
+{
+ return PchGetPcieControllerSbiPid ((UINT32) (RpIndex / PCH_PCIE_CONTROLLER_PORTS));
+}
+
+/**
+ Calculate root port device number based on physical port index.
+
+ @param[in] RpIndex Root port index (0-based).
+
+ @retval Root port device number.
+**/
+UINT32
+PchGetPcieRpDevice (
+ IN UINT32 RpIndex
+ )
+{
+ UINTN ControllerIndex;
+ ControllerIndex = RpIndex / PCH_PCIE_CONTROLLER_PORTS;
+ ASSERT (ControllerIndex < mPchPcieControllerInfoSize);
+ return mPchPcieControllerInfo[ControllerIndex].DevNum;
+}
+
+/**
+ This function reads Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[out] *Data32 Value of Config register
+
+ @retval EFI_SUCCESS SBI Read successful.
+**/
+EFI_STATUS
+PchSbiRpPciRead32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ OUT UINT32 *Data32
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RpDevice;
+ UINT8 Response;
+ UINT16 Fid;
+
+
+ RpDevice = PchGetPcieRpDevice (RpIndex);
+ Fid = (UINT16) ((RpDevice << 3) | (RpIndex % 4 ));
+ Status = PchSbiExecutionEx (
+ GetRpSbiPid (RpIndex),
+ Offset,
+ PciConfigRead,
+ FALSE,
+ 0xF,
+ 0,
+ Fid,
+ Data32,
+ &Response
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR,"Sideband Read Failed\n"));
+ ASSERT (FALSE);
+ }
+ return Status;
+}
+
+/**
+ This function And then Or Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[in] Data32And Value of Config register to be And-ed
+ @param[in] Data32AOr Value of Config register to be Or-ed
+
+ @retval EFI_SUCCESS SBI Read and Write successful.
+**/
+EFI_STATUS
+PchSbiRpPciAndThenOr32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ IN UINT32 Data32And,
+ IN UINT32 Data32Or
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RpDevice;
+ UINT32 Data32;
+ UINT8 Response;
+ UINT16 Fid;
+
+ RpDevice = PchGetPcieRpDevice (RpIndex);
+ Status = PchSbiRpPciRead32 (RpIndex, Offset, &Data32);
+ if (Status == EFI_SUCCESS) {
+ Data32 &= Data32And;
+ Data32 |= Data32Or;
+ Fid = (UINT16) ((RpDevice << 3) | (RpIndex % 4 ));
+ Status = PchSbiExecutionEx (
+ GetRpSbiPid (RpIndex),
+ Offset,
+ PciConfigWrite,
+ FALSE,
+ 0xF,
+ 0,
+ Fid,
+ &Data32,
+ &Response
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR,"Sideband Write Failed\n"));
+ ASSERT (FALSE);
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+ return Status;
+}
+
+/**
+ Check if RST PCIe Storage Remapping is enabled based on policy
+
+ @param[in] RstPcieStorageRemap The PCH PCIe Storage remapping
+
+ @retval TRUE RST PCIe Storage Remapping is enabled
+ @retval FALSE RST PCIe Storage Remapping is disabled
+**/
+BOOLEAN
+IsRstPcieStorageRemapEnabled (
+ IN CONST PCH_RST_PCIE_STORAGE_CONFIG *RstPcieStorageRemap
+ )
+{
+ BOOLEAN RstPcieStorageRemapEnabled;
+ UINTN Index;
+
+ RstPcieStorageRemapEnabled = FALSE;
+
+ DEBUG ((DEBUG_INFO, "IsRstPcieStorageRemapEnabled Started\n"));
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ if (RstPcieStorageRemap[Index].Enable == 1) {
+ RstPcieStorageRemapEnabled = TRUE;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "IsRstPcieStorageRemapEnabled Ended\n"));
+ return RstPcieStorageRemapEnabled;
+}
+
+/**
+ Disable the RST remap address decoding range while RST is disabled.
+
+ @param[in] AhciBar ABAR address
+**/
+VOID
+DisableRstRemapDecoding (
+ UINT32 AhciBar
+ )
+{
+ UINTN PciSataRegBase;
+ UINT32 OrgAhciBar;
+ UINT8 OrgCmd;
+
+ if (AhciBar == 0) {
+ DEBUG ((DEBUG_ERROR, "DisableRstRemapDecoding: Invalid AHCI BAR address.\n"));
+ ASSERT (FALSE);
+ return;
+ }
+
+ PciSataRegBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA);
+ OrgCmd = MmioRead8 (PciSataRegBase + PCI_COMMAND_OFFSET);
+ OrgAhciBar = MmioRead32 (PciSataRegBase + R_PCH_SATA_AHCI_BAR);
+
+ if (AhciBar != OrgAhciBar) {
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, 0);
+ MmioWrite32 (PciSataRegBase + R_PCH_SATA_AHCI_BAR, AhciBar);
+ }
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ //
+ // Program "NVM Remap Memory BAR Enable", AHCIBar offset A4h [0] to ['0b']
+ // Also set NRMO AHCIBar offset A4h [27:16] to 0x00F, and MSL AHCIBar offset A4h [12:1] to 0.
+ //
+ DEBUG ((DEBUG_INFO, "DisableRstRemapDecoding: Program AHCIBar offset A4h [27:16, 12:1, 0] to [0x00F, 0, 0] to disable remap decoding\n"));
+ MmioWrite32 (AhciBar + R_PCH_SATA_VS_CAP, (0x00F << N_PCH_SATA_VS_CAP_NRMO));
+
+ if (AhciBar != OrgAhciBar) {
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, 0);
+ MmioWrite32 (PciSataRegBase + R_PCH_SATA_AHCI_BAR, OrgAhciBar);
+ }
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, OrgCmd);
+}
+
+/**
+ This function lock down the P2sb SBI before going into OS.
+
+ @param[in] SbiUnlock
+**/
+VOID
+ConfigureP2sbSbiLock (
+ IN CONST BOOLEAN SbiUnlock
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN P2sbOrgStatus;
+
+ if (SbiUnlock == FALSE) {
+ P2sbBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_P2SB, PCI_FUNCTION_NUMBER_PCH_P2SB);
+ PchRevealP2sb (P2sbBase, &P2sbOrgStatus);
+
+ ///
+ /// Set P2SB PCI Offset 0xE0[31] to 1 to lock down SBI interface.
+ /// @note: SbiLock is write once. Please make sure it's not touched earlier.
+ ///
+ MmioOr8 (P2sbBase + R_PCH_P2SB_E0 + 3, BIT7);
+
+ if (!P2sbOrgStatus) {
+ PchHideP2sb (P2sbBase);
+ }
+ }
+}
+
+/**
+ Bios will remove the host accessing right to Sideband register range
+ prior to any 3rd party code execution.
+
+ 1) Set EPMASK5 Offset C4 (bits 29, 28, 27, 26, 17, 16 (PCH-LP only), 10, 1) to disable Sideband access for PSF and MIPI controller
+ 2) Set EPMASK7 Offset CC (bits 6, 5) to disable Sideband access for XHCI controller
+ 3) Set the "Endpoint Mask Lock!", P2SB PCI offset E2h bit[1] to 1.
+
+**/
+VOID
+RemoveSidebandAccess (
+ VOID
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN P2sbOrgStatus;
+
+ P2sbBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_P2SB, PCI_FUNCTION_NUMBER_PCH_P2SB);
+ PchRevealP2sb (P2sbBase, &P2sbOrgStatus);
+
+ //
+ // Set EPMASK for ports B1, B0, AA, A1 (bits 17, 16 (PCH-LP only), 10, 1) to disable Sideband access for MIPI controller
+ // Set EPMASK for ports BD, BC, BB, BA (bits 29, 28, 27, 26) to disable Sideband access for PCI Root Bridge
+ //
+ if (GetPchSeries () == PchLp) {
+ MmioOr32 (P2sbBase + R_PCH_P2SB_EPMASK5, BIT29 | BIT28 | BIT27 | BIT26 | BIT17 | BIT16 | BIT10 | BIT1);
+ } else {
+ MmioOr32 (P2sbBase + R_PCH_P2SB_EPMASK5, BIT29 | BIT28 | BIT27 | BIT26 | BIT17 | BIT10 | BIT1);
+ }
+
+ //
+ // Set EPMASK for ports E6, E5 (bits 6, 5) to disable Sideband access for XHCI controller
+ //
+ MmioOr32(P2sbBase + R_PCH_P2SB_EPMASK7, BIT6 | BIT5);
+
+ DEBUG((DEBUG_INFO, "Lock the EPMASK registers\n"));
+
+ MmioOr8 (P2sbBase + R_PCH_P2SB_E0 + 2, BIT1);
+
+ if (!P2sbOrgStatus) {
+ PchHideP2sb (P2sbBase);
+ }
+}
+
+/**
+ Configure PMC static function disable lock
+**/
+VOID
+ConfigurePmcStaticFunctionDisableLock (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ MmioOr32 (PchPwrmBase + R_PCH_PWRM_ST_PG_FDIS_PMC_1, B_PCH_PWRM_ST_PG_FDIS_PMC_1_ST_FDIS_LK);
+}
+
+/**
+ Print registers value
+
+ @param[in] PrintMmioBase Mmio base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+PrintRegisters (
+ IN UINTN PrintMmioBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ )
+{
+ UINT32 Offset;
+ DEBUG ((DEBUG_VERBOSE, " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"));
+ for (Offset = 0; Offset < PrintSize; Offset++) {
+ if ((Offset % 16) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFFF0));
+ }
+ DEBUG ((DEBUG_VERBOSE, "%02X ", MmioRead8 (PrintMmioBase + Offset)));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+VOID
+PrintPchPciConfigSpace (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 00 - 0 ] Host Bridge\n"));
+ PrintRegisters (MmPciBase ( 0,0,0 ), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 01 - 0 ] PCI Bridge (0-1) x16@1 (x16)\n"));
+ PrintRegisters (MmPciBase ( 0,1,0 ), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 02 - 0 ] IGD\n"));
+ PrintRegisters (MmPciBase ( 0,2,0 ), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 03 - 0 ] High Def Audio\n"));
+ PrintRegisters (MmPciBase (00, 03, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 20(0x14) - 0 ] XHCI Controller\n"));
+ PrintRegisters (MmPciBase (00, 20, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 22(0x16) - 0 ] ME\n"));
+ PrintRegisters (MmPciBase (00, 22, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 22(0x16) - 2 ] ME IDER\n"));
+ PrintRegisters (MmPciBase (00, 22, 02), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 22(0x16) - 3 ] ME SOL\n"));
+ PrintRegisters (MmPciBase (00, 22, 03), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 25(0x19) - 0 ] LAN\n"));
+ PrintRegisters (MmPciBase (00, 25, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 26(0x1A) - 0 ] EHCI Controller\n"));
+ PrintRegisters (MmPciBase (00, 26, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 27(0x1B) - 0 ] High Def Audio\n"));
+ PrintRegisters (MmPciBase (00, 27, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 28(0x1C) - 0 ] PCI Bridge (0-2) x0@1 (x1)\n"));
+ PrintRegisters (MmPciBase (00, 28, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: AECH\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0100, 0x040,0x0100);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: DFT\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0310, 0x030,0x0310);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: VC0\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0340, 0x020,0x0340);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: Port Configuration Extension\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0400, 0x020,0x0400);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 28(0x1C) - 6 ] PCI Bridge (0-3:10) x0@1 (x1)\n"));
+ PrintRegisters (MmPciBase (00, 28, 06), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 29(0x1D) - 0 ] EHCI Controller\n"));
+ PrintRegisters (MmPciBase (00, 29, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 31(0x1F) - 0 ] ISA Bridge\n"));
+ PrintRegisters (MmPciBase (00, 31, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 31(0x1F) - 2 ] SATA\n"));
+ PrintRegisters (MmPciBase (00, 31, 02), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 31(0x1F) - 4 ] SMBus Controller\n"));
+ PrintRegisters (MmPciBase (00, 31, 04), 256, 0);
+
+ DEBUG ((DEBUG_VERBOSE, "\n\n"));
+}
+
+/**
+ Program Xhci Port Disable Override
+
+ @param[in] XhciMmioBase xHCI controller MBAR0 address
+ @param[in] Usb2DisabledPorts Disabled USB2 ports where each port has its disabling bit
+ @param[in] Usb3DisabledPorts Disabled USB3 ports where each port has its disabling bit
+
+ @retval TRUE if platform reset is needed, otherwise FALSE is returned
+**/
+BOOLEAN
+UsbPdoProgramming (
+ IN UINTN XhciMmioBase,
+ IN UINT32 Usb2DisabledPorts,
+ IN UINT32 Usb3DisabledPorts
+ )
+{
+ UINT32 Index;
+ UINT32 XhciUsb2Pdo;
+ UINT32 XhciUsb3Pdo;
+ UINT32 XhciUsb2PdoRd;
+ UINT32 XhciUsb3PdoRd;
+ UINT32 XhciUsb3PortScStartingOffset;
+ UINT32 XhciUsb3PortScOffset;
+ UINT32 XhciPlsTimeout;
+
+ DEBUG ((DEBUG_INFO, "UsbPdoProgramming () start\n"));
+ DEBUG ((DEBUG_INFO, "xHCI: Usb2DisabledPorts = 0x%x\n", Usb2DisabledPorts));
+ DEBUG ((DEBUG_INFO, "xHCI: Usb3DisabledPorts = 0x%x\n", Usb3DisabledPorts));
+
+ //
+ // XHCI PDO for HS
+ //
+ if (GetPchSeries () == PchLp) {
+ XhciUsb2Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB2PDO) & B_PCH_XHCI_LP_USB2PDO_MASK;
+ } else {
+ XhciUsb2Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB2PDO) & B_PCH_XHCI_H_USB2PDO_MASK;
+ }
+ XhciUsb2Pdo |= Usb2DisabledPorts;
+
+ //
+ // XHCI PDO for SS
+ //
+ if (GetPchSeries () == PchLp) {
+ XhciUsb3Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB3PDO) & B_PCH_XHCI_LP_USB3PDO_MASK;
+ XhciUsb3PortScStartingOffset = R_PCH_LP_XHCI_PORTSC01USB3;
+ } else {
+ XhciUsb3Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB3PDO) & B_PCH_XHCI_H_USB3PDO_MASK;
+ XhciUsb3PortScStartingOffset = R_PCH_H_XHCI_PORTSC01USB3;
+ }
+
+ for (Index = 0; Index < GetPchXhciMaxUsb3PortNum (); Index++) {
+ // Check if port should be disabled
+ if ((Usb3DisabledPorts & (BIT0 << Index)) != 0) {
+ // Check if PDO bit has not been set yet
+ if (((XhciUsb3Pdo & (UINT32)(BIT0 << Index)) == 0)) {
+ // Calculate port PortSC register offset in xHCI MMIO space
+ XhciUsb3PortScOffset = (XhciUsb3PortScStartingOffset + (Index * 0x10));
+
+ // Disable port before setting PDO bit for it
+ MmioOr32 (XhciMmioBase + XhciUsb3PortScOffset, B_PCH_XHCI_PORTSCXUSB3_PED);
+
+ // Poll for PLS (PortSC[5:8]) to reach 0x4 before setting PDO for the port
+ for (XhciPlsTimeout = 0; XhciPlsTimeout < PORT_PLS_TIMEOUT; XhciPlsTimeout++) {
+ if ((MmioRead32 (XhciMmioBase + XhciUsb3PortScOffset) & B_PCH_XHCI_PORTSCXUSB3_PLS) == V_PCH_XHCI_PORTSCXUSB3_PLS_DISABLED) {
+ break;
+ }
+ MicroSecondDelay (10);
+ }
+
+ if (XhciPlsTimeout == PORT_PLS_TIMEOUT) {
+ DEBUG ((DEBUG_ERROR, "[xHCI PDO] PLS Polling for Disabled has timed out for port %d\n", Index + 1));
+ }
+
+ // A '1' in a bit position prevents the corresponding USB3 port from reporting a Device Connection to the XHC
+ XhciUsb3Pdo |= (UINT32) (B_PCH_XHCI_USB3PDO_DIS_PORT0 << Index);
+
+ // Put port back to RxDetect state
+ // Need to write LWS and PLS regs with same MMIO operation otherwise PLS write will be ignored
+ MmioOr32 (XhciMmioBase + XhciUsb3PortScOffset, (B_PCH_XHCI_PORTSCXUSB3_LWS | V_PCH_XHCI_PORTSCXUSB3_PLS_RXDETECT));
+ }
+ }
+ }
+
+ //
+ // USB2PDO and USB3PDO are Write-Once registers and bits in them are in the SUS Well.
+ //
+ MmioWrite32 (XhciMmioBase + R_PCH_XHCI_USB2PDO, XhciUsb2Pdo);
+ MmioWrite32 (XhciMmioBase + R_PCH_XHCI_USB3PDO, XhciUsb3Pdo);
+
+ XhciUsb2PdoRd = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB2PDO);
+ XhciUsb3PdoRd = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB3PDO);
+
+ //
+ // If USB2PDO and USB3PDO are not updated successfully perform Warm Reset to unlock RWO bits.
+ //
+ if ((XhciUsb2Pdo != XhciUsb2PdoRd) || (XhciUsb3Pdo != XhciUsb3PdoRd)) {
+ DEBUG ((DEBUG_ERROR, "UsbPdoProgramming: PDO register locked. Performing Warm Reset\n"));
+ return TRUE;
+ }
+
+ DEBUG ((DEBUG_INFO, "UsbPdoProgramming () end\n"));
+ return FALSE;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c
new file mode 100644
index 0000000000..77dd285430
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c
@@ -0,0 +1,127 @@
+/** @file
+ This file contains functions that configures PCI Express Root Ports function swapping.
+
+Copyright (c) 2017, 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 that 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 <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/PchInitCommonLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <Library/S3BootScriptLib.h>
+
+/**
+ Configure root port function number mapping
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+PchConfigureRpfnMapping (
+ VOID
+ )
+{
+ UINT8 PortIndex;
+ UINT8 OriginalFuncZeroRp;
+ UINT8 MaxPciePortNum;
+ UINT32 Data32;
+ UINTN DevNum;
+ UINTN FuncNum;
+ UINTN RpBase;
+ UINT32 ControllerPcd[PCH_MAX_PCIE_CONTROLLERS];
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGen;
+ UINT32 PcieControllers;
+ UINT32 ControllerIndex;
+ UINT32 FirstController;
+ PCH_SBI_PID ControllerPid;
+
+ DEBUG ((DEBUG_INFO,"PchConfigureRpfnMapping () Start\n"));
+
+ PchSeries = GetPchSeries ();
+ PchGen = GetPchGeneration ();
+ MaxPciePortNum = GetPchMaxPciePortNum ();
+
+ PcieControllers = GetPchMaxPcieControllerNum ();
+
+ for (ControllerIndex = 0; ControllerIndex < PcieControllers; ++ControllerIndex) {
+ PchPcrRead32 (PchGetPcieControllerSbiPid (ControllerIndex), R_PCH_PCR_SPX_PCD, &ControllerPcd[ControllerIndex]);
+ }
+
+ ///
+ /// Configure root port function number mapping
+ ///
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; ) {
+ GetPchPcieRpDevFun (PortIndex, &DevNum, &FuncNum);
+ RpBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) DevNum, (UINT32) FuncNum);
+ //
+ // Search for first enabled function
+ //
+ if (MmioRead16 (RpBase) != 0xFFFF) {
+ if (FuncNum != 0) {
+ //
+ // First enabled root port that is not function zero will be swapped with function zero on the same device
+ // RP PCD register must sync with PSF RP function config register
+ //
+ ControllerIndex = PortIndex / 4;
+ OriginalFuncZeroRp = (PortIndex / 8) * 8;
+ FirstController = OriginalFuncZeroRp / 4;
+
+ //
+ // The enabled root port becomes function zero
+ //
+ ControllerPcd[ControllerIndex] &= (UINT32) ~(B_PCH_PCR_SPX_PCD_RP1FN << ((PortIndex % 4) * S_PCH_PCR_SPX_PCD_RP_FIELD));
+ ControllerPcd[ControllerIndex] |= 0u;
+ //
+ // Origianl function zero on the same device takes the numer of the current port
+ //
+ ControllerPcd[FirstController] &= (UINT32) ~B_PCH_PCR_SPX_PCD_RP1FN;
+ ControllerPcd[FirstController] |= (UINT32) FuncNum;
+
+ //
+ // Program PSF1 RP function config register.
+ //
+ PsfSetPcieFunctionWithS3BootScript (OriginalFuncZeroRp, (UINT32) FuncNum);
+ PsfSetPcieFunctionWithS3BootScript (PortIndex, 0);
+ }
+ //
+ // Once enabled root port was found move to next PCI device
+ //
+ PortIndex = ((PortIndex / 8) + 1) * 8;
+ continue;
+ }
+ //
+ // Continue search for first enabled root port
+ //
+ PortIndex++;
+ }
+
+ //
+ // Write to PCD and lock the register
+ //
+ for (ControllerIndex = 0; ControllerIndex < PcieControllers; ++ControllerIndex) {
+ ControllerPid = PchGetPcieControllerSbiPid (ControllerIndex);
+ Data32 = ControllerPcd[ControllerIndex] | B_PCH_PCR_SPX_PCD_SRL;
+ PchPcrWrite32 (ControllerPid, R_PCH_PCR_SPX_PCD, Data32);
+ PCH_PCR_BOOT_SCRIPT_WRITE (
+ S3BootScriptWidthUint32,
+ ControllerPid, R_PCH_PCR_SPX_PCD,
+ 1,
+ &Data32
+ );
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf
new file mode 100644
index 0000000000..df4900d964
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf
@@ -0,0 +1,42 @@
+## @file
+# Component description file for the PchInitCommonLib
+#
+# Copyright (c) 2017, 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 = PeiDxeSmmPchInitCommonLib
+ FILE_GUID = E9C4FE04-8A79-43FA-B3E0-603359C31B43
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchInitCommonLib
+
+[Sources]
+ PchInitCommon.c
+ PchRpfn.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PchCycleDecodingLib
+ PchPcieRpLib
+ PchP2sbLib
+ PchSbiAccessLib
+ PchInfoLib
+ PchPsfPrivateLib
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c
new file mode 100644
index 0000000000..815b800db7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c
@@ -0,0 +1,1933 @@
+/** @file
+ This file contains routines that support PCI Express initialization
+
+Copyright (c) 2017, 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 that 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 "PchPciExpressHelpersLibrary.h"
+
+const UINT8 mPcieL1sTposMultiplier[] = {2, 10, 100};
+
+/*
+ Returns Tpower_on capability of device
+
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+*/
+T_POWER_ON GetTpoCapability (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset
+ )
+{
+ T_POWER_ON Tpo;
+ UINT32 L1ssCapabilities;
+
+ L1ssCapabilities = MmioRead32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ Tpo.Scale = (L1ssCapabilities & B_PCIE_EX_L1SCAP_PTPOS) >> N_PCIE_EX_L1SCAP_PTPOS;
+ Tpo.Value = (L1ssCapabilities & B_PCIE_EX_L1SCAP_PTV) >> N_PCIE_EX_L1SCAP_PTV;
+ return Tpo;
+}
+
+/*
+ Returns Tpower_on currently programed in a device
+
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+*/
+T_POWER_ON GetTpo (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset
+ )
+{
+ T_POWER_ON Tpo;
+ UINT32 L1ssControl2;
+
+ L1ssControl2 = MmioRead32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL2_OFFSET);
+ Tpo.Scale = L1ssControl2 & 0x3;
+ Tpo.Value = (L1ssControl2 & 0xF8) >> N_PCIE_EX_L1SCTL2_POWT;
+ return Tpo;
+}
+
+/*
+ Sets Tpower_on in a device
+ According to spec, Tpower_on can only be updated while L1.2 is disabled
+
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+ @param[in] Tpo value to be programmed into Tpower_on
+*/
+VOID SetTpo (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset,
+ T_POWER_ON Tpo
+ )
+{
+ UINT32 L1_2;
+
+ L1_2 = MmioRead32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL1_OFFSET) & (BIT2 | BIT0);
+ MmioAnd32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, (UINT32)(~ (BIT2 | BIT0)));
+ MmioAndThenOr32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL2_OFFSET, (UINT32)(~0xFB), (Tpo.Value << 3) + Tpo.Scale);
+ MmioOr32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, L1_2);
+}
+
+/*
+ Converts Tpower_on from value:scale notation to microseconds
+*/
+UINT32 TpoToUs (
+ T_POWER_ON Tpo
+ )
+{
+ static const UINT8 TpoScaleMultiplier[] = {2, 10, 100};
+
+ ASSERT (Tpo.Scale < TpoScaleMax);
+ if (Tpo.Scale >= TpoScaleMax) {
+ return 0;
+ }
+ return (TpoScaleMultiplier[Tpo.Scale] * Tpo.Value);
+}
+
+/**
+ Find the Offset to a given Capabilities ID
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId CAPID to search for
+
+ @retval 0 CAPID not found
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT8
+PcieFindCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ )
+{
+ UINT8 CapHeaderOffset;
+ UINT8 CapHeaderId;
+ UINTN DeviceBase;
+
+ DeviceBase = MmPciBase (Bus, Device, Function);
+
+ DEBUG ((DEBUG_INFO,"PcieFindCapId () BDF %0x: %0x :%0x, CapId = %0x \n", Bus, Device, Function, CapId));
+ if ((MmioRead8 (DeviceBase + PCI_PRIMARY_STATUS_OFFSET) & EFI_PCI_STATUS_CAPABILITY) == 0x00) {
+ ///
+ /// Function has no capability pointer
+ ///
+ return 0;
+ } else {
+ ///
+ /// Check the header layout to determine the Offset of Capabilities Pointer Register
+ ///
+ if ((MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) {
+ ///
+ /// If CardBus bridge, start at Offset 0x14
+ ///
+ CapHeaderOffset = EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR;
+ } else {
+ ///
+ /// Otherwise, start at Offset 0x34
+ ///
+ CapHeaderOffset = PCI_CAPBILITY_POINTER_OFFSET;
+ }
+ ///
+ /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
+ ///
+ CapHeaderId = 0;
+ CapHeaderOffset = MmioRead8 (DeviceBase + CapHeaderOffset) & ((UINT8) ~(BIT0 | BIT1));
+ while (CapHeaderOffset != 0 && CapHeaderId != 0xFF) {
+ CapHeaderId = MmioRead8 (DeviceBase + CapHeaderOffset);
+ if (CapHeaderId == CapId) {
+ if (CapHeaderOffset > PCI_MAXLAT_OFFSET) {
+ ///
+ /// Return valid capability offset
+ ///
+ return CapHeaderOffset;
+ } else {
+ ASSERT ((FALSE));
+ return 0;
+ }
+ }
+ ///
+ /// Each capability must be DWORD aligned.
+ /// The bottom two bits of all pointers (including the initial pointer at 34h) are reserved
+ /// and must be implemented as 00b although software must mask them to allow for future uses of these bits.
+ ///
+ CapHeaderOffset = MmioRead8 (DeviceBase + CapHeaderOffset + 1) & ((UINT8) ~(BIT0 | BIT1));
+ }
+ return 0;
+ }
+}
+
+/**
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Reporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId Extended CAPID to search for
+
+ @retval 0 CAPID not found, this includes situation where device doesn't exist
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT16
+PcieFindExtendedCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ )
+{
+ UINT16 CapHeaderOffset;
+ UINT16 CapHeaderId;
+ UINTN DeviceBase;
+
+ DeviceBase = MmPciBase (Bus, Device, Function);
+
+ ///
+ /// Start to search at Offset 0x100
+ /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
+ ///
+ CapHeaderId = 0;
+ CapHeaderOffset = R_PCH_PCIE_EXCAP_OFFSET;
+ while (CapHeaderOffset != 0 && CapHeaderId != MAX_UINT16) {
+ CapHeaderId = MmioRead16 (DeviceBase + CapHeaderOffset);
+ if (CapHeaderId == CapId) {
+ return CapHeaderOffset;
+ }
+ ///
+ /// Each capability must be DWORD aligned.
+ /// The bottom two bits of all pointers are reserved and must be implemented as 00b
+ /// although software must mask them to allow for future uses of these bits.
+ ///
+ CapHeaderOffset = (MmioRead16 (DeviceBase + CapHeaderOffset + 2) >> 4) & ((UINT16) ~(BIT0 | BIT1));
+ }
+
+ return 0;
+}
+
+/**
+ This returns ClkReq Number from Port Number
+
+ @param[in] PortIndex PCIe Port Number (Zero Base)
+
+ @retval ClkReq Number
+**/
+UINT8
+GetPortClkReqNumber (
+ IN UINT8 PortIndex
+ )
+{
+ UINT8 ClkReqNum;
+ PchPcrRead8 (PID_FIA, R_PCH_PCR_FIA_DRCRM1 + (PortIndex / 2), &ClkReqNum);
+ if (PortIndex % 2 == 0) {
+ ClkReqNum &= 0x0F;
+ } else {
+ ClkReqNum = ClkReqNum >> 4;
+ }
+ return ClkReqNum;
+}
+
+/**
+ Set Common clock to Root port and Endpoint PCI device
+
+ @param[in] Bus1 Root port Pci Bus Number
+ @param[in] Device1 Root port Pci Device Number
+ @param[in] Function1 Root port Pci Function Number
+ @param[in] Bus2 Endpoint Pci Bus Number
+ @param[in] Device2 Endpoint Pci Device Number
+
+ @exception EFI_UNSUPPORTED Unsupported operation.
+ @retval EFI_SUCCESS VC mapping correctly initialized
+**/
+EFI_STATUS
+PcieSetCommonClock (
+ IN UINT8 Bus1,
+ IN UINT8 Device1,
+ IN UINT8 Function1,
+ IN UINT8 Bus2,
+ IN UINT8 Device2
+ )
+{
+ UINT8 CapOffset1;
+ UINT8 CapOffset2;
+ BOOLEAN CommonClockSupport;
+ UINTN DeviceBase1;
+ UINTN DeviceBase2;
+ UINT16 RegData16;
+ UINT8 FunctionIndex;
+ UINT8 Function2;
+
+ DeviceBase1 = MmPciBase (Bus1, Device1, Function1);
+
+ ///
+ /// Get the pointer to the Port PCI Express Capability Structure.
+ ///
+ CommonClockSupport = FALSE;
+ CapOffset1 = PcieFindCapId (Bus1, Device1, Function1, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset1 == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Check the Port Slot Clock Configuration Bit.
+ ///
+ if ((MmioRead16 (DeviceBase1 + CapOffset1 + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_SCC) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DeviceBase2 = MmPciBase (Bus2, Device2, 0);
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase2 + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ Function2 = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ Function2 = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= Function2; FunctionIndex++) {
+ DeviceBase2 = MmPciBase (Bus2, Device2, FunctionIndex);
+ ///
+ /// Check the Endpoint Slot Clock Configuration Bit.
+ ///
+ CapOffset2 = PcieFindCapId (Bus2, Device2, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if ((CapOffset2 != 0) && ((MmioRead16 (DeviceBase2 + CapOffset2 + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_SCC) != 0)) {
+ ///
+ /// Common clock is supported, set common clock bit on root port
+ /// and the endpoint
+ ///
+ if (CommonClockSupport == FALSE) {
+ MmioOr8 (DeviceBase1 + CapOffset1 + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_CCC);
+ CommonClockSupport = TRUE;
+ }
+ MmioOr8 (DeviceBase2 + CapOffset2 + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_CCC);
+ }
+ }
+ ///
+ /// If common clock not supported on root port and endpoint, return EFI_UNSUPPORTED
+ ///
+ if (CommonClockSupport == FALSE) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Retrain the Link per PCI Express Specification.
+ ///
+ MmioOr8 (DeviceBase1 + CapOffset1 + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_RL);
+
+ ///
+ /// Wait until Re-Training has completed.
+ ///
+ do {
+ RegData16 = MmioRead16 (DeviceBase1 + CapOffset1 + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_LT;
+ } while (RegData16 != 0);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function enables the CLKREQ# PM on all the end point functions
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] RootDevice Rootport Device Number
+ @param[in] RootFunction Rootport Function Number
+
+ @retval None
+**/
+VOID
+PcieSetClkreq (
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction
+ )
+{
+ UINT8 CapOffset;
+ UINTN DeviceBase;
+ UINT8 FunctionIndex;
+ UINT8 Function;
+ BOOLEAN ClkreqPerPortSupported;
+
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, 0);
+ ClkreqPerPortSupported = TRUE;
+
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ Function = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ Function = 0;
+ }
+ ///
+ /// Parse thro all the functions of the endpoint and find the PCIe Cap ID (offset 10h) and if
+ /// exists then enable the CLKREQ# bit (BIT8) on that function
+ ///
+ for (FunctionIndex = 0; FunctionIndex <= Function; FunctionIndex++) {
+ ///
+ /// Find the PCIe Cap Id (10h)
+ ///
+ CapOffset = PcieFindCapId (EndPointBus, EndPointDevice, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset == 0) {
+ continue;
+ }
+
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ ///
+ /// Check if CLKREQ# is supported by the endpoints
+ ///
+ if ((MmioRead32 (DeviceBase + CapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_CPM) == 0) {
+ ///
+ /// CLKREQ# is not supported so dont do anything
+ ///
+ ClkreqPerPortSupported = FALSE;
+ break;
+ }
+ }
+
+ if (ClkreqPerPortSupported == FALSE) {
+ return;
+ }
+ ///
+ /// Now enable the CLKREQ#
+ ///
+ for (FunctionIndex = 0; FunctionIndex <= Function; FunctionIndex++) {
+ ///
+ /// Find the PCIe Cap Id (10h)
+ ///
+ CapOffset = PcieFindCapId (EndPointBus, EndPointDevice, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset == 0) {
+ continue;
+ }
+
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ MmioOr16 (DeviceBase + CapOffset + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_ECPM);
+ }
+}
+/**
+ This function get or set the Max Payload Size on all the end point functions
+
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] EndPointDevice The Device Number of the Endpoint
+ @param[in, out] MaxPayload The Max Payolad Size of the root port
+ @param[in] Operation True: Set the Max Payload Size on all the end point functions
+ False: Get the Max Payload Size on all the end point functions
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieMaxPayloadSize (
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN OUT UINT16 *MaxPayload,
+ IN BOOLEAN Operation
+ )
+{
+ UINTN DeviceBase;
+ UINT8 PcieCapOffset;
+ UINT16 EndPointMaxPayload;
+ UINT8 FunctionIndex;
+ UINT8 EndPointFunction;
+
+ ///
+ /// Obtain the Max Payload Size for all the end point functions
+ ///
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, 0);
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ EndPointFunction = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ EndPointFunction = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) {
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ if (MmioRead16 (DeviceBase + PCI_VENDOR_ID_OFFSET) != MAX_UINT16) {
+ ///
+ /// Get the pointer to the Endpoint PCI Express Capability Structure.
+ ///
+ PcieCapOffset = PcieFindCapId (EndPointBus, EndPointDevice, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (PcieCapOffset == 0) {
+ continue;
+ }
+
+ if (Operation == TRUE) {
+ ///
+ /// Set the Max Payload Size of the end point function
+ ///
+ MmioAndThenOr16 (
+ DeviceBase + PcieCapOffset + R_PCIE_DCTL_OFFSET,
+ (UINT16) ~(B_PCIE_DCTL_MPS),
+ *MaxPayload << N_PCIE_DCTL_MPS
+ );
+ } else {
+ ///
+ /// Get the end point function Max Payload Size support
+ ///
+ EndPointMaxPayload = MmioRead16 (DeviceBase + PcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_MPS;
+ ///
+ /// Obtain the minimum Max Payload Size between the PCIE root Port and the end point functions
+ ///
+ if (*MaxPayload > EndPointMaxPayload) {
+ *MaxPayload = EndPointMaxPayload;
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function disable the forwarding of EOI messages unless it discovers
+ an IOAPIC behind this root port.
+
+ @param[in] RootBus The Bus Number of the root port
+ @param[in] RootDevice The Device Number of the root port
+ @param[in] RootFunction The Function Number of the root port
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] EndPointDevice The Device Number of the Endpoint
+
+ @exception EFI_UNSUPPORTED Unsupported operation.
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieSetEoiFwdDisable (
+ IN UINT8 RootBus,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction,
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice
+ )
+{
+ BOOLEAN IoApicBehind;
+ UINTN RootDeviceBase;
+ UINTN DeviceBase;
+ UINT8 ProgInterface;
+ UINT8 SubClassCode;
+ UINT8 BaseClassCode;
+ UINT8 FunctionIndex;
+ UINT8 EndPointFunction;
+ UINTN RootPortIndex;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ IoApicBehind = FALSE;
+ RootDeviceBase = MmPciBase (RootBus, RootDevice, RootFunction);
+
+ ///
+ /// Check if an IOAPIC behind the root port
+ ///
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, 0);
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ EndPointFunction = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ EndPointFunction = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) {
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ BaseClassCode = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET + 2);
+ SubClassCode = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET + 1);
+ ProgInterface = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET);
+ if ((BaseClassCode == PCI_CLASS_SYSTEM_PERIPHERAL) &&
+ (SubClassCode == PCI_SUBCLASS_PIC) &&
+ ((ProgInterface == PCI_IF_APIC_CONTROLLER) ||
+ (ProgInterface == PCI_IF_APIC_CONTROLLER2))) {
+ IoApicBehind = TRUE;
+ }
+ }
+ ///
+ /// PCH BIOS Spec Section 8.15 Additional PCI Express* Programming Steps
+ /// Step 27
+ /// If there is no IOAPIC behind the root port, set EOI Forwarding Disable bit (PCIE RP PCI offset D4h[1]) to 1b.
+ ///
+ if (IoApicBehind == FALSE) {
+ MmioOr32 (RootDeviceBase + R_PCH_PCIE_MPC2, B_PCH_PCIE_MPC2_EOIFD);
+ } else {
+ ///
+ /// If there is an IOAPIC discovered behind root port program PSF Multicast registers
+ /// accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
+ ///
+ ///
+ ///
+ Status = GetPchPcieRpNumber ((UINTN) RootDevice, (UINTN) RootFunction, &RootPortIndex);
+ ASSERT_EFI_ERROR (Status);
+
+ PsfConfigurEoiForPciePort ((UINT32)RootPortIndex);
+ }
+
+ return Status;
+}
+
+typedef enum {
+ CalculateAspm,
+ ManualAspm,
+ SetAspm
+} OPERATION;
+
+/**
+ This function compares the actual latency in LatencyValue1
+ with actual latency in LatencyValue2 and stores the minimum
+ back to LatencyValue1, in the required format.
+ If this is the first call, then LatencyValue1 will be replaced by LatencyValue2.
+
+ @param[in, out] LatencyValue1 - Current latency value
+ @param[in] LatencyValue2 - Latency value from the Table
+
+ @retval None
+**/
+VOID
+DetermineLatencyValue (
+ IN OUT UINT16 *LatencyValue1,
+ IN UINT16 LatencyValue2
+ )
+{
+ ASSERT (LTR_SCALE_VALUE (*LatencyValue1) < 6);
+ ASSERT (LTR_SCALE_VALUE (LatencyValue2) < 6);
+ ///
+ /// If there are more than one device behind a bridge that are part of the override table,
+ /// store the lower latency value and corresponding scale bits back to LatencyValue1
+ ///
+ if ((LTR_LATENCY_NS (*LatencyValue1) == 0) || (LTR_LATENCY_NS (*LatencyValue1) > LTR_LATENCY_NS (LatencyValue2))) {
+ *LatencyValue1 = LatencyValue2;
+ }
+}
+
+/**
+ This function checks exit latency of L1 and L0s and disables the ASPM state if it is longer than
+ the acceptable latency
+
+ @param[in] EndPointBase End Point Base Address
+ @param[in] EndPointPcieCapOffset The pointer to the End Point PCI Express Capability Structure
+ @param[in] RootDeviceBase The Root Port PCI Express Base address
+ @param[in] RootPcieCapOffset The pointer to the Root Port PCI Express Capability Structure
+ @param[in, out] EndPointAspm End Point ASPM setting
+
+ @retval none
+**/
+VOID
+AspmCheckExitLatency (
+ IN UINTN EndPointBase,
+ IN UINT8 EndPointPcieCapOffset,
+ IN UINTN RootDeviceBase,
+ IN UINT32 RootPcieCapOffset,
+ IN OUT UINT16* EndPointAspm
+ )
+{
+
+ UINT32 PortLxLat;
+ UINT32 EndPointLxLat;
+ UINT32 LxLat;
+
+ ///
+ /// Check if L1 should be enabled based on port and endpoint L1 exit latency.
+ ///
+ if ((*EndPointAspm) & BIT1) {
+ PortLxLat = MmioRead32 (RootDeviceBase + RootPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL1;
+ EndPointLxLat = MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL1;
+
+ LxLat = PortLxLat;
+ if (PortLxLat < EndPointLxLat) {
+ LxLat = EndPointLxLat;
+ }
+ ///
+ /// check if the value is bigger than endpoint L1 acceptable exit latency, if it is
+ /// larger than accepted value, then we should disable L1
+ ///
+ LxLat >>= N_PCIE_LCAP_EL1;
+ if (LxLat > ((MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_E1AL) >> N_PCIE_DCAP_E1AL)) {
+ (*EndPointAspm) &= ~BIT1;
+ }
+ }
+ ///
+ /// Check if L0s should be enabled based on port and endpoint L0s exit latency.
+ ///
+ if ((*EndPointAspm) & BIT0) {
+ PortLxLat = MmioRead32 (RootDeviceBase + RootPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL0;
+ EndPointLxLat = MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL0;
+
+ LxLat = PortLxLat;
+ if (PortLxLat < EndPointLxLat) {
+ LxLat = EndPointLxLat;
+ }
+ ///
+ /// check if the value is bigger than endpoint L0s acceptable exit latency, if it is
+ /// larger than accepted value, then we should disable L0s
+ ///
+ LxLat >>= N_PCIE_LCAP_EL0;
+ if (LxLat > ((MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_E0AL) >> N_PCIE_DCAP_E0AL)) {
+ (*EndPointAspm) &= ~BIT0;
+ }
+ }
+ return;
+}
+/**
+ This function gets override Aspm values if the end point is found in the override look up table
+
+ @param[in] EndPointBase End Point Base Address
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in] EndPointVendorId End Point Vendor Id
+ @param[in] EndPointDeviceId End Point Device Id
+ @param[in] EndPointRevId End Point Revision Id
+ @param[in, out] EndPointAspm End Point ASPM setting
+
+ @retval none
+**/
+
+VOID
+GetOverrideAspm (
+ IN UINTN EndPointBase,
+ IN UINT32 NumOfDevAspmOverride,
+ IN const PCH_PCIE_DEVICE_OVERRIDE* DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ IN OUT UINT16 *EndPointAspm
+ )
+{
+ UINT8 EndPointBaseClassCode;
+ UINT8 EndPointSubClassCode;
+ UINT8 PcieDeviceIndex;
+ ///
+ /// Mask APMC with values from lookup table.
+ /// RevID of 0xFF applies to all steppings.
+ ///
+ EndPointBaseClassCode = MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET);
+ EndPointSubClassCode = MmioRead8 (EndPointBase + R_PCI_SCC_OFFSET);
+ for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) {
+ if (((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieL1L2Override) == PchPcieL1L2Override) &&
+ ((DevAspmOverride[PcieDeviceIndex].VendorId == EndPointVendorId) ||
+ (DevAspmOverride[PcieDeviceIndex].VendorId == 0xFFFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].DeviceId == EndPointDeviceId) ||
+ (DevAspmOverride[PcieDeviceIndex].DeviceId == 0xFFFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].RevId == EndPointRevId) ||
+ (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].BaseClassCode == EndPointBaseClassCode) ||
+ (DevAspmOverride[PcieDeviceIndex].BaseClassCode == 0xFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].SubClassCode == EndPointSubClassCode) ||
+ (DevAspmOverride[PcieDeviceIndex].SubClassCode == 0xFF))) {
+ ///
+ /// Override value of 0xFF applies to all.
+ ///
+ *EndPointAspm = DevAspmOverride[PcieDeviceIndex].EndPointAspm;
+ break;
+ }
+ }
+}
+
+/**
+ This function gets override L1 Substate Capability offset pointer
+ if the end point is found in the override look up table
+
+ @param[in] EndPointBase End Point Base Address
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in] EndPointVendorId End Point Vendor Id
+ @param[in] EndPointDeviceId End Point Device Id
+ @param[in] EndPointRevId End Point Revision Id
+ @param[out] EndPointL1SubStateCapOffset Pointer to L1 Substate Capability Structure
+ @param[out] EndPointL1SubStateCapMask L1 Substate Capability Mask
+ @param[out] EndPointL1sCommonModeRestoreTime L1 Substate Port Common Mode Restore Time
+ @param[out] EndPointL1sTpowerOnScale L1 Substate Port Tpower_on Scale
+ @param[out] EndPointL1sTpowerOnValue L1 Substate Port Tpower_on Value
+
+ @retval none
+**/
+
+VOID
+GetOverrideL1sCapOffsetAndValue (
+ IN UINTN EndPointBase,
+ IN UINT32 NumOfDevAspmOverride,
+ IN const PCH_PCIE_DEVICE_OVERRIDE* DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ OUT UINT16 *EndPointL1SubStateCapOffset,
+ OUT UINT8 *EndPointL1SubStateCapMask,
+ OUT UINT8 *EndPointL1sCommonModeRestoreTime,
+ OUT UINT8 *EndPointL1sTpowerOnScale,
+ OUT UINT8 *EndPointL1sTpowerOnValue
+ )
+{
+ UINT8 PcieDeviceIndex;
+ ///
+ /// Get the endpoint supports L1 Substates Capabilities from Override Table
+ ///
+ for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) {
+ if (((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieL1SubstatesOverride) == PchPcieL1SubstatesOverride) &&
+ (EndPointVendorId == DevAspmOverride[PcieDeviceIndex].VendorId) &&
+ (EndPointDeviceId == DevAspmOverride[PcieDeviceIndex].DeviceId) &&
+ ((EndPointRevId == DevAspmOverride[PcieDeviceIndex].RevId) ||
+ (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF))) {
+ if ((EndPointVendorId == V_PCH_INTEL_VENDOR_ID) &&
+ ((EndPointDeviceId == 0x08B1) || (EndPointDeviceId == 0x08B2) ||
+ (EndPointDeviceId == 0x08B3) || (EndPointDeviceId == 0x08B4))
+ && ((MmioRead32 (EndPointBase + DevAspmOverride[PcieDeviceIndex].L1SubstatesCapOffset) & 0xFFFF) != 0xCAFE)) {
+ continue;
+ }
+ *EndPointL1SubStateCapOffset = DevAspmOverride[PcieDeviceIndex].L1SubstatesCapOffset;
+ *EndPointL1SubStateCapMask = DevAspmOverride[PcieDeviceIndex].L1SubstatesCapMask & 0x0F;
+ *EndPointL1sCommonModeRestoreTime = DevAspmOverride[PcieDeviceIndex].L1sCommonModeRestoreTime & 0xFF;
+ *EndPointL1sTpowerOnScale = DevAspmOverride[PcieDeviceIndex].L1sTpowerOnScale & 0x03;
+ *EndPointL1sTpowerOnValue = DevAspmOverride[PcieDeviceIndex].L1sTpowerOnValue & 0x1F;
+
+ break;
+ }
+ }
+}
+
+/**
+ This function configures the L1 Substates.
+ It can be used for Rootport and endpoint devices.
+
+ @param[in] DownstreamPort Indicates if the device about to be programmed is a downstream port
+ @param[in] DeviceBase Device PCI configuration base address
+ @param[in] L1SubstateExtCapOffset Pointer to L1 Substate Capability Structure
+ @param[in] PortL1SubstateCapSupport L1 Substate capability setting
+ @param[in] PortCommonModeRestoreTime Common Mode Restore Time
+ @param[in] PortTpowerOnValue Tpower_on Power On Wait Time
+ @param[in] PortTpowerOnScale Tpower-on Scale
+
+ @retval none
+**/
+VOID
+ConfigureL1s (
+ IN BOOLEAN DownstreamPort,
+ IN UINTN DeviceBase,
+ IN UINT16 L1SubstateExtCapOffset,
+ IN UINT32 PortL1SubstateCapSupport,
+ IN UINT32 PortCommonModeRestoreTime,
+ IN UINT32 PortTpowerOnValue,
+ IN UINT32 PortTpowerOnScale
+ )
+{
+ //
+ // For downstream port only:
+ // Program Common Mode Restore Time, but disable L1.2 first
+ //
+ if (DownstreamPort) {
+ MmioAnd32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(BIT2 | BIT0)
+ );
+
+ ///
+ /// b. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and Set the highest value advertised
+ /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on both
+ /// Pcie root port and device.
+ ///
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(0xFF00),
+ (UINT32) PortCommonModeRestoreTime << 8
+ );
+ }
+
+ ///
+ /// PCH BIOS Spec Section 8.3 ASPM on DMI and the PCI Express* Root Ports
+ /// Step 6
+ /// a. Read L1 Sub-States Extended Capability Offset + 0x04[3:0], and set the smallest common subset supported
+ /// by both PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[3:0]
+ ///
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(BIT3 | BIT2 | BIT1 | BIT0),
+ PortL1SubstateCapSupport
+ );
+ ///
+ /// c. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and Set the highest value
+ /// advertised between PCIe root port and device to L1 Sub-States Extended Capability Offset + 0x0C [7:0] on
+ /// both Pcie root port and device.
+ ///
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL2_OFFSET,
+ 0xFFFFFF04,
+ (UINT32) ((PortTpowerOnValue << N_PCIE_EX_L1SCTL2_POWT) | PortTpowerOnScale)
+ );
+ ///
+ /// d. Set L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device
+ /// e. Set L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device
+ ///
+
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(0xE3FF0000),
+ (UINT32) (BIT30 | BIT23 | BIT21)
+ );
+}
+
+/**
+ This function gets the Latency Tolerance Reporting settings from override table
+ if the end point is found in the override look up table
+
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in] EndPointVendorId End Point Vendor Id
+ @param[in] EndPointDeviceId End Point Device Id
+ @param[in] EndPointRevId End Point Revision Id
+ @param[in, out] LtrOverrideVal Snoop and Non Snoop Latency Values
+ @param[out] ForceLtrOverride This endpoint needs LTR to be permanently overridden
+
+ @retval none
+**/
+VOID
+GetLtrOverride (
+ IN UINT32 NumOfDevAspmOverride,
+ IN const PCH_PCIE_DEVICE_OVERRIDE* DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ IN OUT UINT32* LtrOverrideVal,
+ OUT UINT8* ForceLtrOverride
+ )
+{
+ UINT8 PcieDeviceIndex;
+ UINT16 Data16;
+ UINT32 Data32;
+ ///
+ /// For each device detected, scan the LTR override table
+ /// If there are endpoints connected directly to the rootport then
+ /// LtrOverrideVal will be replaced by the value from the table for that endpoint
+ /// If there are endpoints that are behind a bridge and that are also part of the table then
+ /// LtrOverrideVal will maintain the minimum of all such values.
+ /// A non zero value of LtrOverrideVal will indicate:
+ /// i):That there is atleast one entry in the LTR override Table
+ /// ii):The final value to be programmed in offset 0x400. This value will be applied for all the devices
+ /// connected to this root port
+ ///
+ Data32 = *LtrOverrideVal;
+ for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) {
+ if (((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieLtrOverride) == PchPcieLtrOverride) &&
+ (DevAspmOverride[PcieDeviceIndex].VendorId == EndPointVendorId) &&
+ ((DevAspmOverride[PcieDeviceIndex].DeviceId == EndPointDeviceId) ||
+ (DevAspmOverride[PcieDeviceIndex].DeviceId == 0xFFFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].RevId == EndPointRevId) ||
+ (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF))) {
+ ///
+ /// Get the Non-Snoop latency value from the table, compare and store the minimum
+ ///
+ if (DevAspmOverride[PcieDeviceIndex].NonSnoopLatency & BIT15) {
+ Data16 = (UINT16) ((Data32 & 0xFFFF0000) >> 16);
+ DetermineLatencyValue (
+ &Data16,
+ DevAspmOverride[PcieDeviceIndex].NonSnoopLatency);
+ Data32 = (Data32 & 0xFFFF) | ((UINT32) (Data16 << 16));
+ }
+ ///
+ /// Get the Snoop latency value from the table, compare and store the minimum
+ ///
+ if (DevAspmOverride[PcieDeviceIndex].SnoopLatency & BIT15) {
+ Data16 = (UINT16) (Data32 & 0xFFFF);
+ DetermineLatencyValue (
+ &Data16,
+ DevAspmOverride[PcieDeviceIndex].SnoopLatency);
+ Data32 = (Data32 & 0xFFFF0000) | (UINT32) Data16;
+ }
+ *LtrOverrideVal = Data32;
+ //
+ // Get the ForceLtrOverride value from table
+ //
+ if (DevAspmOverride[PcieDeviceIndex].ForceLtrOverride == TRUE) {
+ *ForceLtrOverride = TRUE;
+ }
+ break;
+ }
+ }
+ return;
+}
+
+
+/**
+ This function configures the Latency Tolerance Reporting Settings for endpoint devices
+
+ @param[in] RootPortConfig Rootport PCI Express Configuration
+ @param[in] EndPointBus Endpoint Bus Number
+ @param[in] EndPointDevice Endpoint Device Number
+ @param[in] EndPointFunction Endpoint Function Number
+ @param[in] EndPointBase Endpoint PCI Express Address
+ @param[in] EndPointPcieCapOffset Pointer to Endpoint PCI Express Capability Structure
+ @param[in] DeviceCapabilities2 Endpoint Value of Device Capabilities 2 Register (PciE Cap offset + 0x24)
+ @param[in] PchSeries Pch Series
+ @param[in] LtrOverrideVal Snoop and Non Snoop Latency Values
+
+ @retval none
+**/
+VOID
+ConfigureLtr (
+ IN CONST PCH_PCIE_ROOT_PORT_CONFIG* RootPortConfig,
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN UINT8 EndPointFunction,
+ IN UINTN EndPointBase,
+ IN UINT8 EndPointPcieCapOffset,
+ IN UINT32 DeviceCapabilities2,
+ IN PCH_SERIES PchSeries,
+ IN UINT32* LtrOverrideVal
+ )
+{
+ UINT32 Data32;
+ UINT16 Data16;
+ UINT16 LtrExtendedCapOffset;
+ UINT16 DefaultMaxLatency;
+ DefaultMaxLatency = 0;
+ ///
+ /// PCH BIOS Spec Section 8.15.1 Power Optimizer Configuration
+ /// Step 3
+ /// If Endpoint device supports LTR, Device Capabilities 2 Register Offset 24h [11] = 1b,
+ ///
+ if ((DeviceCapabilities2 & B_PCIE_DCAP2_LTRMS) && (RootPortConfig->LtrEnable == TRUE)) {
+ ///
+ /// PCH BIOS Spec Section 8.15.1 Power Optimizer Configuration
+ /// Step 3.1
+ /// Program Endpoint LTR Mechanism Enable, Device Control 2 Register Offset 28h [10] = 1b
+ /// when device supports LTR but is not found in override table (table listing correct
+ /// latency requirements for devices that supports LTR and also for devices that do not
+ /// support LTR).
+ ///
+ MmioOr16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCTL2_OFFSET, B_PCIE_DCTL2_LTREN);
+ }
+ ///
+ /// Get the pointer to the Endpoint PCI Express Extended Capability Structure
+ /// and configure the Max Snoop and Max No-Snoop Latency for the endpoint
+ ///
+ LtrExtendedCapOffset = PcieFindExtendedCapId (EndPointBus,
+ EndPointDevice,
+ EndPointFunction,
+ R_PCH_PCIE_LTRECH_CID);
+ if (LtrExtendedCapOffset != 0) {
+ Data32 = *LtrOverrideVal;
+ ///
+ /// PCH BIOS Spec Section 8.14.1 Power Optimizer Configuration
+ /// Step 3.2
+ /// If B0:Dxx:Fn + 400h is not programmed with snoop latency override value,
+ /// program endpoint max snoop latency register, Latency Tolerance Reporting (LTR)
+ /// Capability Offset 04h [15:0] = 1003h
+
+ DefaultMaxLatency = RootPortConfig->LtrMaxSnoopLatency;
+ Data16 = (UINT16) (Data32 & 0xFFFF);
+ ///
+ /// Set the max snoop latency to either the default max snoop latency or to the snoop latency override value
+ /// that is being programmed for this root port
+ ///
+ DetermineLatencyValue (&Data16, DefaultMaxLatency);
+ MmioAndThenOr16 (EndPointBase + LtrExtendedCapOffset + R_PCH_PCIE_LTRECH_MSLR_OFFSET,
+ (UINT16) (~0x1FFF),
+ Data16);
+ ///
+ /// PCH BIOS Spec Section 8.14.1 Power Optimizer Configuration
+ /// Step 3.3
+ /// If B0:Dxx:Fn + 400h is not programmed with non-snoop latency override value,
+ /// program endpoint max non-snoop Latency Register, Latency Tolerance Reporting (LTR)
+ /// Capability Offset 06h [15:0] = 1003h
+
+ DefaultMaxLatency = RootPortConfig->LtrMaxNoSnoopLatency;
+ Data16 = (UINT16) ((Data32 & 0xFFFF0000) >> 16);
+ DetermineLatencyValue (&Data16, DefaultMaxLatency);
+ MmioAndThenOr16 (
+ EndPointBase + LtrExtendedCapOffset
+ + R_PCH_PCIE_LTRECH_MNSLR_OFFSET,
+ (UINT16) (~0x1FFF),
+ Data16);
+ ///
+ /// Step 4
+ /// If not all devices support LTR
+ /// Program PWRMBASE + 20h = 00010003h
+ /// (Note this register should be saved and restored during S3 transitions)
+ /// Done in PchPcieSmm.c PchPciePmIoTrapSmiCallback ()
+ ///
+ }
+}
+
+/**
+ Calculate/Set EndPoint device Power management settings
+
+ @param[in] RootDeviceBase The Root Port PCI Express address
+ @param[in] RootPcieCapOffset The pointer to the Root Port PCI Express Capability Structure
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in, out] LinkAspmVal Resulting Link ASPM value programmed
+ @param[in] Operation Operation Types
+ @param[in, out] LtrOverrideVal Resulting LTR override value to be programmed
+ @param[in] RootL1SubstateExtCapOffset The register offset of Root Port L1 Substates
+ @param[in, out] L1SubstatesSupported Input and return the result of L1 Substates support
+ @param[in, out] PortL1SubstateCapSupport Input and return Capability of L1 Substate setting
+ @param[in, out] PortCommonModeRestoreTime Input and return common mode restore time of L1 Substate setting
+ @param[in, out] PortTpowerOnValue Input and return power on value of L1 Substate setting
+ @param[in, out] PortTpowerOnScale Input and return power on scale of L1 Substate setting
+ @param[in] RootPortConfig Pcie Power Optimizer Configuration
+ @param[in, out] AspmOverride Input and return the Aspm Override enable for pre-1.1 devices
+ @param[in, out] ClkreqPerPortSupported Input to check if clkreq per port is supportted
+ @param[in, out] RpAndEndPointsLtrSupported Input to check if LTR per port is supportted
+ @param[out] ForceLtrOverride One of endpoints needs LTR to be permanently overridden
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device
+
+ @retval EFI_OUT_OF_RESOURCES The endpoint device is a bridge, but the Subordinate Bus Number of
+ the root port is not greater than its Secondary Bus Number. You may
+ get this error if PCI emulation is not done before this function gets
+ called and the Policy settings of "TempRootPortBusNumMax" and
+ "TempRootPortBusNumMin" do not provide enough resource for temp bus
+ number usage.
+**/
+EFI_STATUS
+PcieEndPointPm (
+ IN UINTN RootDeviceBase,
+ IN UINT32 RootPcieCapOffset,
+ IN UINT8 EndPointBus,
+ IN UINT32 NumOfDevAspmOverride,
+ IN CONST PCH_PCIE_DEVICE_OVERRIDE *DevAspmOverride,
+ IN OUT UINT16 *LinkAspmVal,
+ IN OPERATION Operation,
+ IN OUT UINT32 *LtrOverrideVal,
+ IN UINT16 RootL1SubstateExtCapOffset,
+ IN OUT BOOLEAN *L1SubstatesSupported,
+ IN OUT UINT32 *PortL1SubstateCapSupport,
+ IN OUT UINT32 *PortCommonModeRestoreTime,
+ IN OUT UINT32 *PortTpowerOnValue,
+ IN OUT UINT32 *PortTpowerOnScale,
+ IN CONST PCH_PCIE_ROOT_PORT_CONFIG *RootPortConfig,
+ IN OUT BOOLEAN *AspmOverride,
+ IN BOOLEAN *ClkreqPerPortSupported,
+ IN OUT BOOLEAN *RpAndEndPointsLtrSupported,
+ OUT UINT8 *ForceLtrOverride
+ )
+{
+ EFI_STATUS Status;
+ UINTN EndPointBase;
+ UINT8 EndPointFunction;
+ UINT8 EndPointPcieCapOffset;
+ UINT16 EndPointAspm;
+ UINT16 EndPointVendorId;
+ UINT16 EndPointDeviceId;
+ UINT8 EndPointRevId;
+ UINT8 DownStreamBusMin;
+ UINT8 ClassCode;
+ UINT8 RootDevSubBusNum;
+ BOOLEAN BusAssign;
+ UINT8 DeviceIndex;
+ UINT8 FunctionIndex;
+ UINT32 DeviceCapabilities2;
+ UINT16 EndPointL1SubStateCapOffset;
+ UINT32 EndPointL1Substates;
+ UINT8 EndPointL1sCommonModeRestoreTime;
+ UINT8 EndPointL1sTpowerOnScale;
+ UINT8 EndPointL1sTpowerOnValue;
+ UINT8 EndPointL1SubStateCapMask;
+ PCH_SERIES PchSeries;
+ BOOLEAN DownstreamPort;
+ UINT16 PcieEndCapOffset;
+ UINT16 PcieEndDeviceType;
+
+ PchSeries = GetPchSeries ();
+
+ DEBUG ((DEBUG_INFO, "PcieEndPointPm () Start EndPointBus %0x\n", EndPointBus));
+ for (DeviceIndex = 0; DeviceIndex <= PCI_MAX_DEVICE; DeviceIndex++) {
+ EndPointBase = MmPciBase (EndPointBus, DeviceIndex, 0);
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ continue;
+ }
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (EndPointBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ EndPointFunction = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ EndPointFunction = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) {
+ EndPointBase = MmPciBase (EndPointBus, DeviceIndex, FunctionIndex);
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ continue;
+ }
+
+ //
+ // Get the pointer to the Endpoint PCI Express Capability Structure.
+ //
+ EndPointPcieCapOffset = PcieFindCapId (EndPointBus, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (EndPointPcieCapOffset == 0) {
+ return EFI_NOT_FOUND;
+ }
+ EndPointVendorId = MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET);
+ EndPointDeviceId = MmioRead16 (EndPointBase + PCI_DEVICE_ID_OFFSET);
+ EndPointRevId = MmioRead8 (EndPointBase + PCI_REVISION_ID_OFFSET);
+
+ EndPointL1SubStateCapOffset = 0;
+ EndPointL1SubStateCapMask = 0;
+ EndPointL1sCommonModeRestoreTime = 0;
+ EndPointL1sTpowerOnScale = 0;
+ EndPointL1sTpowerOnValue = 0;
+ EndPointL1Substates = 0;
+
+ if (RootL1SubstateExtCapOffset != 0) {
+ ///
+ /// Get the endpoint supports L1 Substates Capabilities
+ ///
+ GetOverrideL1sCapOffsetAndValue (
+ EndPointBase,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ EndPointVendorId,
+ EndPointDeviceId,
+ EndPointRevId,
+ &EndPointL1SubStateCapOffset,
+ &EndPointL1SubStateCapMask,
+ &EndPointL1sCommonModeRestoreTime,
+ &EndPointL1sTpowerOnScale,
+ &EndPointL1sTpowerOnValue
+ );
+
+ if (EndPointL1SubStateCapOffset == 0) {
+ EndPointL1SubStateCapOffset = PcieFindExtendedCapId (
+ EndPointBus,
+ DeviceIndex,
+ FunctionIndex,
+ V_PCIE_EX_L1S_CID
+ );
+ }
+ if (EndPointL1SubStateCapOffset != 0) {
+ EndPointL1Substates = MmioRead32 (EndPointBase + EndPointL1SubStateCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ }
+ }
+
+ DeviceCapabilities2 = MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP2_OFFSET);
+ if (((DeviceCapabilities2 & B_PCIE_DCAP2_LTRMS) == 0) || (RootPortConfig->LtrEnable != TRUE)) {
+ *RpAndEndPointsLtrSupported = FALSE;
+ }
+ ///
+ /// Configure downstream device if present.
+ ///
+ if (Operation == CalculateAspm || Operation == ManualAspm) {
+ if ((MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_CPM) != B_PCIE_LCAP_CPM) {
+ *ClkreqPerPortSupported = FALSE;
+ }
+ EndPointAspm = (MmioRead16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) >> N_PCIE_LCAP_APMS) & 3;
+ DEBUG ((DEBUG_INFO, "Endpoint Device %0x Capability ASPM: %0x\n", DeviceIndex, EndPointAspm));
+ if (Operation == CalculateAspm) {
+ ///
+ /// Check endpoint for pre-1.1 devices based on the Role based Error Reporting Capability bit
+ /// and enable Aspm Override
+ ///
+ if (!(MmioRead16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP_OFFSET) & BIT15)) {
+ DEBUG ((DEBUG_INFO, "Override root port ASPM to L1 for pre-1.1 devices\n"));
+ *AspmOverride = TRUE;
+ }
+ GetOverrideAspm (
+ EndPointBase,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ EndPointVendorId,
+ EndPointDeviceId,
+ EndPointRevId,
+ &EndPointAspm
+ );
+ AspmCheckExitLatency (
+ EndPointBase,
+ EndPointPcieCapOffset,
+ RootDeviceBase,
+ RootPcieCapOffset,
+ &EndPointAspm
+ );
+ }
+
+ *LinkAspmVal &= EndPointAspm;
+ DEBUG ((DEBUG_INFO, "Calculate Endpoint Device %0x Aspm Value: %0x\n", DeviceIndex, EndPointAspm));
+ ///
+ /// Check if the endpoint supports L1 Substates Capabilities
+ ///
+ if ((EndPointL1SubStateCapOffset != 0) && (RootL1SubstateExtCapOffset != 0)) {
+ ///
+ /// a. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and program the highest value advertised
+ /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on
+ /// Pcie root port.
+ /// b. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and program the highest value
+ /// advertised between PCIe root port and device.to L1 Sub-States Extended Capability Offset + 0x08 [7:0] on
+ /// both Pcie root port and device.
+ /// c. Program L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device
+ /// d. Program L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device
+ /// e. Program the L1 PM Sub-States Control 1 Register bits 3:0 to the smallest common subset supported by both sides.
+ ///
+ if (((UINT8) EndPointL1Substates & EndPointL1SubStateCapMask) == EndPointL1SubStateCapMask) {
+ *L1SubstatesSupported = TRUE;
+ if (EndPointL1sTpowerOnValue == 0) {
+ EndPointL1sCommonModeRestoreTime = (EndPointL1Substates >> 8) & 0xFF;
+ EndPointL1sTpowerOnScale = (EndPointL1Substates >> 16) & 0x3;
+ EndPointL1sTpowerOnValue = (EndPointL1Substates >> 19) & 0x1F;
+ }
+
+ if (EndPointL1SubStateCapMask == 0) {
+ *PortL1SubstateCapSupport &= (UINT32) (EndPointL1Substates & 0x0F);
+ } else {
+ *PortL1SubstateCapSupport &= (UINT32) EndPointL1SubStateCapMask;
+ }
+
+ if (EndPointL1sCommonModeRestoreTime > *PortCommonModeRestoreTime) {
+ *PortCommonModeRestoreTime = EndPointL1sCommonModeRestoreTime;
+ }
+
+ if (((UINT32) EndPointL1sTpowerOnValue * mPcieL1sTposMultiplier[EndPointL1sTpowerOnScale]) >
+ (*PortTpowerOnValue * mPcieL1sTposMultiplier[*PortTpowerOnScale])) {
+ *PortTpowerOnValue = EndPointL1sTpowerOnValue;
+ *PortTpowerOnScale = EndPointL1sTpowerOnScale;
+ }
+ }
+ }
+ ///
+ /// For each device detected, scan the LTR override table
+ /// If there are endpoints connected directly to the rootport then
+ /// LtrOverrideVal will be replaced by the value from the table for that endpoint
+ /// If there are endpoints that are behind a bridge and that are also part of the table then
+ /// LtrOverrideVal will maintain the minimum of all such values.
+ /// A non zero value of LtrOverrideVal will indicate:
+ /// i):That there is atleast one entry in the LTR override Table
+ /// ii):The final value to be programmed in offset 0x400. This value will be applied for all the devices
+ /// connected to this root port
+ ///
+ GetLtrOverride (
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ EndPointVendorId,
+ EndPointDeviceId,
+ EndPointRevId,
+ LtrOverrideVal,
+ ForceLtrOverride
+ );
+ } else if (Operation == SetAspm) {
+ if ((EndPointL1SubStateCapOffset != 0) && (*L1SubstatesSupported)) {
+ ///
+ /// a. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and program the highest value advertised
+ /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on
+ /// Pcie root port.
+ /// b. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and program the highest value
+ /// advertised between PCIe root port and device.to L1 Sub-States Extended Capability Offset + 0x08 [7:0] on
+ /// both Pcie root port and device.
+ /// c. Program L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device
+ /// d. Program L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device
+ /// e. Program the L1 PM Sub-States Control 1 Register bits 3:0 to the smallest common subset supported by both sides.
+ ///
+ if ((((UINT8) EndPointL1Substates & EndPointL1SubStateCapMask) == EndPointL1SubStateCapMask)) {
+
+ //
+ // Check if current device is a downstream port
+ //
+ DownstreamPort = FALSE;
+ PcieEndCapOffset = PcieFindCapId (EndPointBus, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if ((MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET) == PCI_CLASS_BRIDGE) && (PcieEndCapOffset != 0)) {
+ PcieEndDeviceType = (MmioRead16 (EndPointBase + PcieEndCapOffset + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT;
+ if (PcieEndDeviceType == 0x06) {
+ DownstreamPort = TRUE;
+ }
+ }
+ ConfigureL1s (
+ DownstreamPort,
+ EndPointBase,
+ EndPointL1SubStateCapOffset,
+ *PortL1SubstateCapSupport,
+ *PortCommonModeRestoreTime,
+ *PortTpowerOnValue,
+ *PortTpowerOnScale
+ );
+ }
+ }
+ ///
+ /// Write it to the Link Control register
+ ///
+ DEBUG ((DEBUG_INFO, "Program Endpoint Device %0x Aspm Value: %0x\n", DeviceIndex, *LinkAspmVal));
+ MmioAndThenOr16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCTL_OFFSET, (UINT16) ~B_PCIE_LCTL_ASPM, *LinkAspmVal);
+ ///
+ /// PCH BIOS Spec Section 8.14.1 Power Optimizer Configuration
+ /// Step 3
+ ///
+ ConfigureLtr (
+ RootPortConfig,
+ EndPointBus,
+ DeviceIndex,
+ FunctionIndex,
+ EndPointBase,
+ EndPointPcieCapOffset,
+ DeviceCapabilities2,
+ PchSeries,
+ LtrOverrideVal
+ );
+ }
+ ///
+ /// Check if this device is a bridge
+ ///
+ ClassCode = MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET);
+
+ if (ClassCode == PCI_CLASS_BRIDGE) {
+ ///
+ /// Get the downstream Bus number
+ ///
+ DownStreamBusMin = MmioRead8 (EndPointBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ ///
+ /// If the Secondary Bus Number of endpoint device is not assigned
+ ///
+ if (DownStreamBusMin == 0) {
+ RootDevSubBusNum = MmioRead8 (RootDeviceBase + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ ///
+ /// If the endpoint device is a bridge, the Subordinate Bus Number of the root port will need to be greater
+ /// than the Secondary Bus Number of the root port (the Bus Number of endpoint device).
+ ///
+ if (RootDevSubBusNum > EndPointBus) {
+ ///
+ /// Assign the Primary, Secondary and Subordinate Bus Number to endpoint device
+ ///
+ MmioAndThenOr32 (
+ EndPointBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ 0xFF000000,
+ EndPointBus | (((UINT32) (EndPointBus + 1) << 8)) | ((UINT32) (RootDevSubBusNum << 16))
+ );
+ DownStreamBusMin = EndPointBus + 1;
+ } else {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BusAssign = FALSE;
+ } else {
+ BusAssign = TRUE;
+ }
+
+ if (DownStreamBusMin > EndPointBus) {
+ Status = PcieEndPointPm (
+ RootDeviceBase,
+ RootPcieCapOffset,
+ DownStreamBusMin,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ LinkAspmVal,
+ Operation,
+ LtrOverrideVal,
+ RootL1SubstateExtCapOffset,
+ L1SubstatesSupported,
+ PortL1SubstateCapSupport,
+ PortCommonModeRestoreTime,
+ PortTpowerOnValue,
+ PortTpowerOnScale,
+ RootPortConfig,
+ AspmOverride,
+ ClkreqPerPortSupported,
+ RpAndEndPointsLtrSupported,
+ ForceLtrOverride
+ );
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_INFO, "Check DownStreamBus:%d and no device found!\n", DownStreamBusMin));
+ }
+
+ if (BusAssign == FALSE) {
+ ///
+ /// Clear Bus Numbers.
+ ///
+ MmioAnd32 (EndPointBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000);
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initializes the root port and its down stream devices
+
+ @param[in] RootPortBus Pci Bus Number of the root port
+ @param[in] RootPortDevice Pci Device Number of the root port
+ @param[in] RootPortFunc Pci Function Number of the root port
+ @param[in] CurrentPortBus Pci Bus Number of the current port. Can be a root port or Switch Upstream/Downstream port
+ @param[in] CurrentPortDevice Pci Device Number of the current port. Can be a root port or Switch Upstream/Downstream port
+ @param[in] CurrentPortFunc Pci Function Number of the current port. Can be a root port or Switch Upstream/Downstream port
+ @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary
+ bus number) and its down stream switches
+ @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate
+ bus number) and its down stream switches
+ @param[in, out] MaxPayload The Max Payolad Size of the root port
+ @param[in] SetConfig FALSE to Get information or TRUE to set configuration
+ @param[in] EnableCpm Enables Clock Power Management; even if disabled, CLKREQ# can still be used by L1 PM substates mechanism
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device.
+**/
+EFI_STATUS
+PchPcieInitDownstreamDevices (
+ IN UINT8 RootPortBus,
+ IN UINT8 RootPortDevice,
+ IN UINT8 RootPortFunc,
+ IN UINT8 CurrentPortBus,
+ IN UINT8 CurrentPortDevice,
+ IN UINT8 CurrentPortFunc,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax,
+ IN OUT UINT16 *MaxPayload,
+ IN BOOLEAN SetConfig,
+ IN BOOLEAN EnableCpm
+ )
+{
+ UINT32 Index;
+ UINTN CurrentDeviceBase;
+ UINTN EndPointBase;
+ UINT8 EndPointBus;
+ UINT8 PcieCapOffset;
+ UINT8 PcieDeviceType;
+ UINT8 PcieEndCapOffset;
+ UINT8 PcieEndDeviceType;
+ UINT16 SlotStatus;
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices RootBDF %0x : %0x :%0x\n",RootPortBus, RootPortDevice, RootPortFunc));
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices CurrentBDF %0x : %0x :%0x\n",CurrentPortBus, CurrentPortDevice, CurrentPortFunc));
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices TempBusMin %0x , TempBusMax %0x\n",TempBusNumberMin, TempBusNumberMax));
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices MaxPayLoad %0x\n", *MaxPayload));
+ CurrentDeviceBase = MmPciBase (CurrentPortBus, CurrentPortDevice, CurrentPortFunc);
+ ///
+ /// Get the downstream Bus number
+ ///
+ EndPointBus = MmioRead8 (CurrentDeviceBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ ///
+ /// If the Secondary Bus Number of the root port is not assigned,
+ /// then temporarily Hardcode the Root Port Bridge Number to TempBusNumberMin,
+ /// otherwise use the assigned Bus Number
+ ///
+ if (EndPointBus == 0) {
+ MmioAndThenOr32 (
+ CurrentDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ 0xFF000000,
+ CurrentPortBus | ((UINT32) (TempBusNumberMin << 8)) | ((UINT32) (TempBusNumberMax << 16))
+ );
+ } else {
+ TempBusNumberMin = EndPointBus;
+ TempBusNumberMax = MmioRead8 (CurrentDeviceBase + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ }
+ PcieCapOffset = PcieFindCapId (
+ CurrentPortBus,
+ CurrentPortDevice,
+ CurrentPortFunc,
+ EFI_PCI_CAPABILITY_ID_PCIEXP
+ );
+ PcieDeviceType = (UINT8) ((MmioRead16 (CurrentDeviceBase + PcieCapOffset + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT);
+
+ ///
+ /// Skip this section if Upstream device
+ ///
+ if ((PcieDeviceType != 0x05) ||
+ ((MmioRead8 (CurrentDeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE)) {
+ ///
+ /// This Endpoint check should immediately pass.
+ /// Completion Retry Status Replay Enable is set in PchRootPorts.c PchInitRootPorts ()
+ /// to bypass the timing requirements of the PCI Express Base
+ /// Specification, Revision 1.0A, Section 6.6 ("...software must allow 1.0s
+ /// after a reset of a device, before it may determine that a device which
+ /// fails to return a Successful Completion status for a valid Configuration
+ /// Request is a broken device").
+ ///
+ EndPointBase = MmPciBase (TempBusNumberMin, 0, 0);
+ ///
+ /// A config write is required in order for the device to re-capture the Bus number,
+ /// according to PCI Express Base Specification, 2.2.6.2 ("Note that the Bus Number
+ /// and Device Number may be changed at run time, and so it is necessary to re-capture
+ /// this information with each and every Configuration Write Request")
+ ///
+ MmioWrite8 (EndPointBase + 0x0, 0);
+
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ ///
+ /// Clear Bus Numbers.
+ ///
+ if (EndPointBus == 0) {
+ MmioAnd32 (CurrentDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000);
+ }
+ return EFI_NOT_FOUND;
+ }
+ }
+ for (Index = 0; Index <= PCI_MAX_DEVICE; Index++) {
+ EndPointBase = MmPciBase (TempBusNumberMin, Index, 0);
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ continue;
+ }
+
+ if (!SetConfig) {
+ ///
+ /// Get the Max Payload Size on all the end point functions
+ ///
+ PcieMaxPayloadSize (TempBusNumberMin, (UINT8) Index, MaxPayload, FALSE);
+ }
+
+ PcieEndCapOffset = PcieFindCapId (
+ TempBusNumberMin,
+ (UINT8) Index,
+ 0,
+ EFI_PCI_CAPABILITY_ID_PCIEXP
+ );
+
+ ///
+ /// Check if this device is a bridge
+ /// Pcie to Pci/PciX bridges are skipped
+ ///
+ if ((MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET) == PCI_CLASS_BRIDGE) && (PcieEndCapOffset != 0)) {
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices Bridge Detected\n"));
+ PcieEndDeviceType = (UINT8) ((MmioRead16 (EndPointBase + PcieEndCapOffset + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT);
+ SlotStatus = MmioRead16 (EndPointBase + PcieEndCapOffset + R_PCIE_SLSTS_OFFSET);
+
+ ///
+ /// Initialize the downstream device in following conditions:
+ /// PcieDeviceType is 5 (endpoint is an upstream device).
+ /// PcieDeviceType is 6 (endpoint is a downstream device). And the slot has a device.
+ ///
+ if ((PcieEndDeviceType == 0x05) || ((PcieEndDeviceType == 0x06) && ((SlotStatus & B_PCIE_SLSTS_PDS) != 0))) {
+ ///
+ /// Initialize downstream devices
+ ///
+ if (TempBusNumberMax > TempBusNumberMin) {
+ PchPcieInitDownstreamDevices (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ TempBusNumberMin,
+ (UINT8) Index,
+ 0,
+ TempBusNumberMin + 1,
+ TempBusNumberMax,
+ MaxPayload,
+ SetConfig,
+ EnableCpm
+ );
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ }
+
+ if (SetConfig) {
+ ///
+ /// Disable the forwarding of EOI messages unless it discovers an IOAPIC behind this root port
+ ///
+ if (CurrentPortBus == DEFAULT_PCI_BUS_NUMBER_PCH) {
+ PcieSetEoiFwdDisable (CurrentPortBus, CurrentPortDevice, CurrentPortFunc, TempBusNumberMin, (UINT8) Index);
+ }
+
+ ///
+ /// Set Common Clock for inserted cards
+ ///
+ ///
+ /// PCH BIOS Spec Section 8.3 ASPM on DMI and the PCI Express* Root Ports
+ /// Before determining whether ASPM can be enabled or not,
+ /// the System BIOS must perform the following steps:
+ ///
+ /// For PCH H
+ /// 1. Update the Link Capabilities of the DMI link to indicate L0s/L1 is
+ /// supported by programming the LCAP Register,
+ /// PCR[DMI] + 21A4h[11:10] = 11b. (for PCH with DMI ONLY)
+ /// (Done in PchDmiPei.c)
+ ///
+ /// 2. Enable L0s on DMI for Desktop platforms by setting the APMC field,
+ /// PCR[DMI] + 21A8h[1:0] to 01b.
+ /// Enable L0s/L1 on DMI by setting PCR[DMI] + 21A8h[1:0] to 11b. (for PCH with DMI ONLY)
+ /// (Done in PchDmiPei.c)
+ ///
+ /// 3. For each root port, read the Slot Clock Configuration bit, Dxx:Fn:52h[12],
+ /// of the root port and the endpoint device connected to the port (i.e., D0:F0 on the
+ /// secondary bus behind the root port). If both components have this bit set, then the
+ /// System BIOS should set the Common Clock Configuration (CCC) bit, Dxx:Fn:50h[6],
+ /// for both components at both sides of the link to indicate that components at both ends
+ /// of the link use a common clock source.
+ ///
+ /// 4. If the CCC bit was changed by the System BIOS in step 3, System BIOS should initiate
+ /// a link training by setting the Retrain Link (RL) bit, Dxx:Fn:50h[5], and then poll the Link
+ /// Training (LT) bit, Dxx:Fn:52h[11], until it is clear.
+ /// Note that System BIOS should save and restore CCC bit on S3.
+ ///
+ PcieSetCommonClock (CurrentPortBus, CurrentPortDevice, CurrentPortFunc, TempBusNumberMin, (UINT8) Index);
+
+ ///
+ /// Enable the PCIe CLKREQ#
+ ///
+ if (EnableCpm) {
+ PcieSetClkreq (TempBusNumberMin, (UINT8) Index, RootPortDevice, RootPortFunc);
+ }
+
+ ///
+ /// Set the Max Payload Size on all the end point functions
+ ///
+ PcieMaxPayloadSize (TempBusNumberMin, (UINT8) Index, MaxPayload, TRUE);
+ }
+ }
+
+ ///
+ /// Clear Bus Numbers if it's not assigned yet
+ ///
+ if (EndPointBus == 0) {
+ MmioAnd32 (CurrentDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Initializes the root port and its down stream devices
+
+ @param[in] RootPortBus Pci Bus Number of the root port
+ @param[in] RootPortDevice Pci Device Number of the root port
+ @param[in] RootPortFunc Pci Function Number of the root port
+ @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary
+ bus number) and its down stream switches
+ @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate
+ bus number) and its down stream switches
+ @param[in] EnableCpm Enables Clock Power Management; even if disabled, CLKREQ# can still be used by L1 PM substates mechanism
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device.
+**/
+EFI_STATUS
+PchPcieInitRootPortDownstreamDevices (
+ IN UINT8 RootPortBus,
+ IN UINT8 RootPortDevice,
+ IN UINT8 RootPortFunc,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax,
+ IN BOOLEAN EnableCpm
+ )
+{
+ UINT16 SlotStatus;
+ UINTN RpBase;
+ UINT16 MaxPayload;
+ UINT8 PcieCapOffset;
+ EFI_STATUS Status;
+ UINT8 CurrentPortBus;
+ UINT8 CurrentPortDevice;
+ UINT8 CurrentPortFunc;
+ UINT32 Timeout;
+
+
+ RpBase = MmPciBase (RootPortBus, RootPortDevice, RootPortFunc);
+ ///
+ /// Check for a Presence Detect Change.
+ ///
+ SlotStatus = MmioRead16 (RpBase + R_PCH_PCIE_SLSTS);
+
+ ///
+ /// Check whether the slot has a device connected
+ ///
+ if ((SlotStatus & B_PCIE_SLSTS_PDS) == 0) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Make sure the link is active before trying to talk to device behind it
+ /// Wait up to 100ms, according to PCIE spec chapter 6.7.3.3
+ ///
+ Timeout = 100 * 1000;
+ while ((MmioRead16 (RpBase + R_PCH_PCIE_LSTS) & B_PCIE_LSTS_LA) == 0 ) {
+ MicroSecondDelay (10);
+ Timeout-=10;
+ if (Timeout == 0) {
+ return EFI_NOT_FOUND;
+ }
+ }
+ ///
+ /// Get the pointer to the Endpoint PCI Express Capability Structure.
+ ///
+ PcieCapOffset = PcieFindCapId (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ EFI_PCI_CAPABILITY_ID_PCIEXP
+ );
+ if (PcieCapOffset == 0) {
+ DEBUG ((DEBUG_INFO,"PcieCapOffset Not Found"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the root port Max Payload Size support
+ //
+ MaxPayload = MmioRead16 (RpBase + PcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_MPS;
+
+ ///
+ /// Initialize downstream devices
+ ///
+ CurrentPortBus = RootPortBus;
+ CurrentPortDevice = RootPortDevice;
+ CurrentPortFunc = RootPortFunc;
+
+ //
+ // Get configuration from all downstreams
+ //
+ // In current implementation, only the MaxPayloadSize need to be calculated.
+ // Therefore, for performance, skip the calculation if the MaxPayloadSize is already minimum.
+ //
+ if (MaxPayload != 0) {
+ Status = PchPcieInitDownstreamDevices (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ CurrentPortBus,
+ CurrentPortDevice,
+ CurrentPortFunc,
+ TempBusNumberMin,
+ TempBusNumberMax,
+ &MaxPayload,
+ FALSE,
+ EnableCpm
+ );
+ }
+ //
+ // Set configuration to all downstreams
+ //
+ Status = PchPcieInitDownstreamDevices (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ CurrentPortBus,
+ CurrentPortDevice,
+ CurrentPortFunc,
+ TempBusNumberMin,
+ TempBusNumberMax,
+ &MaxPayload,
+ TRUE,
+ EnableCpm
+ );
+ return Status;
+}
+
+/**
+ Get current PCIe link speed.
+
+ @param[in] RpBase Root Port base address
+ @return Link speed
+**/
+UINT32
+GetLinkSpeed (
+ UINTN RpBase
+ )
+{
+ return MmioRead16 (RpBase + R_PCH_PCIE_LSTS) & B_PCIE_LSTS_CLS;
+}
+
+/**
+ Get max PCIe link speed supported by the root port.
+
+ @param[in] RpBase Root Port base address
+ @return Max link speed
+**/
+UINT32
+GetMaxLinkSpeed (
+ UINTN RpBase
+ )
+{
+ return MmioRead32 (RpBase + R_PCH_PCIE_LCAP) & B_PCIE_LCAP_MLS;
+}
+
+/**
+ Get Pch Maximum Pcie Controller Number
+
+ @retval Pch Maximum Pcie Controller Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPcieControllerNum (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return PCH_LP_PCIE_MAX_CONTROLLERS;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ return KBL_PCH_H_PCIE_MAX_CONTROLLERS;
+ } else {
+ return SKL_PCH_H_PCIE_MAX_CONTROLLERS;
+ }
+ }
+}
+
+/**
+ PCIe controller configuration strings.
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8* mPcieControllerConfigName[] = {
+ "4x1",
+ "1x2-2x1",
+ "2x2",
+ "1x4"
+};
+
+/**
+ Returns the PCIe controller configuration (4x1, 1x2-2x1, 2x2, 1x4)
+
+ @param[in] ControllerIndex Number of PCIe controller (0 based)
+
+ @retval PCIe controller configuration
+**/
+PCIE_CONTROLLER_CONFIG
+GetPcieControllerConfig (
+ IN UINT32 ControllerIndex
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+ PCIE_CONTROLLER_CONFIG Config;
+ UINT32 FirstRp;
+
+ FirstRp = ControllerIndex * PCH_PCIE_CONTROLLER_PORTS;
+
+ Status = PchSbiRpPciRead32 (FirstRp, R_PCH_PCIE_STRPFUSECFG, &Data32);
+ ASSERT_EFI_ERROR (Status);
+
+ Config = ((Data32 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ DEBUG ((DEBUG_INFO, "PCIe SP%c is %a\n", (UINTN) ('A' + ControllerIndex), mPcieControllerConfigName[Config]));
+ return Config;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h
new file mode 100644
index 0000000000..bd59b5346e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h
@@ -0,0 +1,45 @@
+/** @file
+ Header file for PCH Pci Express helps library implementation.
+
+Copyright (c) 2017, 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 that 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 _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_
+#define _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchPolicyCommon.h>
+#include <PchAccess.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <Library/PchInitCommonLib.h>
+
+#define LTR_VALUE_MASK (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7 + BIT8 + BIT9)
+#define LTR_SCALE_MASK (BIT10 + BIT11 + BIT12)
+
+ #define CONFIG_WRITE_LOOP_COUNT 100000
+
+//
+// LTR related macros
+//
+#define LTR_LATENCY_VALUE(x) ((x) & LTR_VALUE_MASK)
+#define LTR_SCALE_VALUE(x) (((x) & LTR_SCALE_MASK) >> 10)
+#define LTR_LATENCY_NS(x) (LTR_LATENCY_VALUE(x) * (1 << (5 * LTR_SCALE_VALUE(x))))
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf
new file mode 100644
index 0000000000..b02f311f02
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf
@@ -0,0 +1,52 @@
+## @file
+# Component description file for the PeiDxeSmmPchPciExpressHelpersLib
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchPciExpressHelpersLib
+FILE_GUID = 07E3F76D-6D26-419d-9053-58696A15B519
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPciExpressHelpersLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+IoLib
+DebugLib
+PchPcieRpLib
+PchPcrLib
+PchInfoLib
+GpioLib
+TimerLib
+PchPsfPrivateLib
+PchInitCommonLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+PchPciExpressHelpersLibrary.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c
new file mode 100644
index 0000000000..ef579c825d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c
@@ -0,0 +1,1169 @@
+/** @file
+ This file contains PSF routines for RC usage
+
+Copyright (c) 2017, 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 that 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/S3BootScriptLib.h>
+
+/**
+ This procedure will disable CIO2 device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableCio2Device (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ R_PCH_LP_PCR_PSF1_T0_SHDW_CAM_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ 0xFFFFFFFF,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Hide CIO2 devices PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideCio2Device (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ R_PCH_LP_PCR_PSF1_T0_SHDW_CAM_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ Disable HDAudio device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableHdaDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_AUD_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable xDCI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableXdciDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+
+ if (GetPchSeries () == PchLp) {
+ RegOffset = R_PCH_LP_PCR_PSF2_T0_SHDW_OTG_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ RegOffset = R_PCH_H_PCR_PSF2_T0_SHDW_OTG_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable xHCI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableXhciDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+
+ if (GetPchSeries () == PchLp) {
+ RegOffset = R_PCH_LP_PCR_PSF2_T0_SHDW_XHCI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ RegOffset = R_PCH_H_PCR_PSF2_T0_SHDW_XHCI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable SATA device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableSataDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+
+ if (GetPchSeries () == PchLp) {
+ RegOffset = R_PCH_LP_PCR_PSF1_T0_SHDW_SATA_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ RegOffset = R_PCH_H_PCR_PSF1_T0_SHDW_SATA_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable ISH device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIshDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_ISH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable ISH BAR1 at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIshBar1 (
+ VOID
+ )
+{
+ //
+ // Set AGNT_T0_SHDW_PCIEN[19:18] = 11b
+ // ISH device BAR is 64bit wide so to disable BAR1
+ // at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be disabled
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_ISH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ (B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS)
+ );
+}
+
+/**
+ Disable GbE device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableGbeDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+ PCH_SBI_PID PortId;
+
+ if (GetPchSeries () == PchLp) {
+ PortId = PID_PSF1;
+ RegOffset = R_PCH_LP_PCR_PSF1_T0_SHDW_GBE_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ PortId = PID_PSF3;
+ RegOffset = R_PCH_H_PCR_PSF3_T0_SHDW_GBE_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PortId,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable SMBUS device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableSmbusDevice (
+ VOID
+ )
+{
+ ///
+ /// Hide SMBUS device
+ /// Set PCR[PSF_3] + "AGNT_T0_SHDW_CFG_DIS"[SMBUS][0]
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_SMBUS_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+
+ ///
+ /// Function disable SMBUS device
+ /// Set PCR[PSF_3] + "AGNT_T0_SHDW_PCIEN"[SMBUS][8]
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_SMBUS_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable Thermal device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableThermalDevice (
+ VOID
+ )
+{
+ ///
+ /// Set PCR[PSF2] TRH PCIEN[8] to 1
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF2, R_PCH_PCR_PSF2_T0_SHDW_TRH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Hide Thermal device PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideThermalDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF2, R_PCH_PCR_PSF2_T0_SHDW_TRH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpScsDevicePsfRegBase[] =
+{
+ R_PCH_LP_PCR_PSF2_T0_SHDW_EMMC_REG_BASE,
+ R_PCH_LP_PCR_PSF2_T0_SHDW_SDIO_REG_BASE,
+ R_PCH_LP_PCR_PSF2_T0_SHDW_SDCARD_REG_BASE,
+ R_PCH_LP_PCR_PSF2_T0_SHDW_UFS_REG_BASE
+};
+
+/**
+ Disable SCS device at PSF level
+
+ @param[in] ScsDevNum SCS Device
+
+ @retval None
+**/
+VOID
+PsfDisableScsDevice (
+ IN PCH_PSF_SCS_DEV_NUM ScsDevNum
+ )
+{
+ if (ScsDevNum >= PchPsfMaxScsDevNum) {
+ ASSERT (FALSE);
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ mPchLpScsDevicePsfRegBase[ScsDevNum] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable SCS devices BAR1 PSF level
+
+ @param[in] ScsDevNum SCS Device
+
+ @retval None
+**/
+VOID
+PsfDisableScsBar1 (
+ IN PCH_PSF_SCS_DEV_NUM ScsDevNum
+ )
+{
+ if (ScsDevNum >= PchPsfMaxScsDevNum) {
+ ASSERT (FALSE);
+ }
+
+ //
+ // Set AGNT_T0_SHDW_PCIEN[19:18] = 11b
+ // SCS device BAR is 64bit wide so to disable BAR1
+ // at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be disabled
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ mPchLpScsDevicePsfRegBase[ScsDevNum] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ (B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS)
+ );
+}
+
+/**
+ Hide TraceHub ACPI devices PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideTraceHubAcpiDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_ACPI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ This procedure will hide TraceHub PciCfgSpace at PSF level
+
+ @retval None
+**/
+VOID
+PsfHideTraceHubDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ This procedure will reveal TraceHub PciCfgSpace at PSF level
+
+ @retval None
+**/
+VOID
+PsfRevealTraceHubDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS),
+ 0
+ );
+}
+
+/**
+ This procedure will disable and hide TraceHub device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableTraceHubDevice (
+ VOID
+ )
+{
+ PsfHideTraceHubDevice ();
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ 0xFFFFFFFF,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Calculates offset of PCR register where given rootport can be enabled/disabled
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval Offset
+**/
+static UINT16
+GetPsfPcieRootPortOffset (
+ IN UINT32 RpIndex
+ )
+{
+ UINT16 RootPortReg;
+
+ if (GetPchSeries () == PchLp) {
+ RootPortReg = R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ RootPortReg = R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ RootPortReg = R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ }
+ }
+ return (RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN);
+}
+
+/**
+ Re-enable PCIe Root Port at PSF level after it was disabled
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfEnablePcieRootPort (
+ IN UINT32 RpIndex
+ )
+{
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ PchPcrAndThenOr32 (PID_PSF1, GetPsfPcieRootPortOffset (RpIndex), (UINT32)(~B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS), 0);
+}
+
+/**
+ Disable PCIe Root Port at PSF level
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfDisablePcieRootPort (
+ IN UINT32 RpIndex
+ )
+{
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ PchPcrAndThenOr32 (PID_PSF1, GetPsfPcieRootPortOffset (RpIndex), ~0u, B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS);
+}
+
+/**
+ Disable PCIe Root Port at PSF level.
+ This function will also perform S3 boot script programming
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfDisablePcieRootPortWithS3BootScript (
+ IN UINT32 RpIndex
+ )
+{
+ UINT16 RootPortReg;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ if (GetPchSeries () == PchLp) {
+ if (RpIndex >= PCH_LP_PCIE_MAX_ROOT_PORTS) {
+ ASSERT (FALSE);
+ return;
+ }
+ RootPortReg = R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ if (RpIndex >= KBL_PCH_H_PCIE_MAX_ROOT_PORTS) {
+ ASSERT (FALSE);
+ return;
+ }
+ RootPortReg = R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ if (RpIndex >= SKL_PCH_H_PCIE_MAX_ROOT_PORTS) {
+ ASSERT (FALSE);
+ return;
+ }
+ RootPortReg = R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ }
+ }
+
+ Data32And = ~0u;
+ Data32Or = B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS;
+
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN,
+ Data32And,
+ Data32Or
+ );
+
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_PSF1, (RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN),
+ &Data32Or,
+ &Data32And
+ );
+}
+
+/**
+ Program PSF grant counts for PCI express depending on controllers configuration
+
+ @param[in] Controller PCIe controller index
+ @param[in] ControllerConfig Port configuration of controller
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurePcieGrantCounts (
+ UINT8 Controller,
+ UINT8 ControllerConfig
+ )
+{
+ static CONST UINT8 DgcrPairsLp [PCH_LP_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS][2] = {
+ { { 5, 6 }, { 8, 9 }, { 11, 12 }, { 14, 15 } }, //SPA
+ { { 19, 20 }, { 22, 23 }, { 25, 26 }, { 28, 29 } }, //SPB
+ { { 33, 34 }, { 36, 37 }, { 39, 40 }, { 42, 43 } }, //SPC
+ };
+
+ static CONST UINT8 PgTgtLp [PCH_LP_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS] = {
+ { 4, 5, 6, 7 }, //SPA
+ { 12, 13, 14, 15 }, //SPB
+ { 20, 21, 22, 23 } //SPC
+ };
+
+ static CONST UINT8 DgcrPairsH [KBL_PCH_H_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS][2] = {
+ { { 11, 12 }, { 14, 15 }, { 17, 18 }, { 20, 21 } }, //SPA
+ { { 24, 25 }, { 27, 28 }, { 30, 31 }, { 33, 34 } }, //SPB
+ { { 37, 38 }, { 40, 41 }, { 43, 44 }, { 46, 47 } }, //SPC
+ { { 50, 51 }, { 53, 54 }, { 56, 57 }, { 59, 60 } }, //SPD
+ { { 63, 64 }, { 66, 67 }, { 69, 70 }, { 72, 73 } }, //SPE
+ { {182,183 }, {185,186 }, {188,189 }, {191,192 } } //SPF, only for KBL-H
+ };
+
+ static CONST UINT8 PgTgtH [KBL_PCH_H_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS] = {
+ { 0, 1, 2, 3 }, //SPA
+ { 4, 5, 6, 7 }, //SPB
+ { 12, 13, 14, 15 }, //SPC
+ { 20, 21, 22, 23 }, //SPD
+ { 28, 29, 30, 31 }, //SPE
+ { 32, 33, 34, 35 } //SPF, only for KBL-H
+ };
+
+ static CONST UINT8 DefaultGrantCount = 4;
+
+ PCH_SERIES PchSeries;
+ UINT32 Dgcr0Addr;
+ UINT32 PgTgt0Addr;
+ UINT32 DgcrNo0;
+ UINT32 DgcrNo1;
+ UINT32 PgTgtNo;
+ UINT32 Channel;
+ UINT32 ChannelGrant[PCH_PCIE_CONTROLLER_PORTS];
+
+ DEBUG ((DEBUG_INFO, "PsfConfigurePcieGrantCounts(%d) Start\n", Controller));
+
+ PchSeries = GetPchSeries ();
+ if (PchSeries == PchLp) {
+ Dgcr0Addr = R_PCH_LP_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
+ PgTgt0Addr = R_PCH_LP_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ Dgcr0Addr = R_KBL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
+ PgTgt0Addr = R_KBL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
+ } else {
+ Dgcr0Addr = R_SKL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
+ PgTgt0Addr = R_SKL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
+ }
+ }
+
+
+ switch (ControllerConfig) {
+ case V_PCH_PCIE_STRPFUSECFG_RPC_1_1_1_1: //Pcie4x1
+ ChannelGrant[0] = 1;
+ ChannelGrant[1] = 1;
+ ChannelGrant[2] = 1;
+ ChannelGrant[3] = 1;
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1: //Pcie1x2_2x1
+ ChannelGrant[0] = 2;
+ ChannelGrant[1] = DefaultGrantCount;
+ ChannelGrant[2] = 1;
+ ChannelGrant[3] = 1;
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_2: //Pcie2x2
+ ChannelGrant[0] = 2;
+ ChannelGrant[1] = DefaultGrantCount;
+ ChannelGrant[2] = 2;
+ ChannelGrant[3] = DefaultGrantCount;
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_4: //Pcie1x4
+ ChannelGrant[0] = 4;
+ ChannelGrant[1] = DefaultGrantCount;
+ ChannelGrant[2] = DefaultGrantCount;
+ ChannelGrant[3] = DefaultGrantCount;
+ break;
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Channel = 0; Channel < PCH_PCIE_CONTROLLER_PORTS; ++Channel) {
+ if (PchSeries == PchLp) {
+ DgcrNo0 = DgcrPairsLp[Controller][Channel][0];
+ DgcrNo1 = DgcrPairsLp[Controller][Channel][1];
+ PgTgtNo = PgTgtLp[Controller][Channel];
+ } else {
+ DgcrNo0 = DgcrPairsH[Controller][Channel][0];
+ DgcrNo1 = DgcrPairsH[Controller][Channel][1];
+ PgTgtNo = PgTgtH[Controller][Channel];
+ }
+
+ DEBUG ((DEBUG_INFO, "DGCR%d = %d\n", DgcrNo0, ChannelGrant[Channel]));
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ (UINT16) (Dgcr0Addr + (DgcrNo0 * S_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR)),
+ (UINT32) ~B_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR_GNT_CNT_RELOAD,
+ ChannelGrant[Channel]
+ );
+ DEBUG ((DEBUG_INFO, "DGCR%d = %d\n", DgcrNo1, ChannelGrant[Channel]));
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ (UINT16) (Dgcr0Addr + (DgcrNo1 * S_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR)),
+ (UINT32) ~B_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR_GNT_CNT_RELOAD,
+ ChannelGrant[Channel]
+ );
+ DEBUG ((DEBUG_INFO, "PG1_TGT%d = %d\n", PgTgtNo, ChannelGrant[Channel]));
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ (UINT16) (PgTgt0Addr + (PgTgtNo * S_PCH_PSF_TARGET_GNTCNT_RELOAD)),
+ (UINT32) ~B_PCH_PSF_TARGET_GNTCNT_RELOAD_GNT_CNT_RELOAD,
+ ChannelGrant[Channel]
+ );
+ }
+
+ DEBUG ((DEBUG_INFO, "PsfConfigurePcieGrantCounts() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable ISM NP Completion Tracking for GbE PSF port
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIsmNpCompletionTrackForGbe (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+ PCH_SBI_PID PortId;
+
+ if (GetPchSeries () == PchLp) {
+ PortId = PID_PSF1;
+ RegOffset = R_PCH_LP_PCR_PSF1_PSF_PORT_CONFIG_PG1_PORT7;
+ } else {
+ PortId = PID_PSF3;
+ RegOffset = R_PCH_H_PCR_PSF3_PSF_PORT_CONFIG_PG1_PORT1;
+ }
+ ///
+ /// Clear PCR PSF_x_PSF_PORT_CONFIG_PGx_PORTx[5] = 0b
+ ///
+ PchPcrAndThenOr8 (
+ PortId,
+ RegOffset,
+ (UINT8) ~(BIT5),
+ 0
+ );
+}
+
+/**
+ Program PSF EOI Multicast configuration
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfSetEoiMulticastConfiguration (
+ VOID
+ )
+{
+ UINT32 McastTarget;
+
+ ///
+ /// Program PSF Multicast registers accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
+ ///
+ if (GetPchSeries () == PchLp) {
+ McastTarget = V_PCH_LP_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB;
+ ///
+ /// Set PCR[PSF1] + 4060h = 38A00h
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF1] + 4050h[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+ } else {
+ McastTarget = V_PCH_H_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB;
+ if (GetPchGeneration () == KblPch) {
+ ///
+ /// Set PCR[PSF1] + 405Ch = 38B00h
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF1] + 404Ch[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+ } else {
+ ///
+ /// Set PCR[PSF1] + 4058h = 38B00h
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF1] + 4048h[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+ }
+ }
+ ///
+ /// Set PCR[PSF1] + 4054h to P2SB target
+ ///
+ PchPcrWrite32 (
+ PID_PSF3, R_PCH_PCR_PSF3_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF3] + 404Ch[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF3, R_PCH_PCR_PSF3_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+}
+
+/**
+ This function enables EOI message forwarding in PSF for PCIe ports
+ for cases where IOAPIC is present behind this root port.
+
+ @param[in] RpIndex Root port index (0 based)
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurEoiForPciePort (
+ IN UINT32 RpIndex
+ )
+{
+
+ UINT32 Data32;
+ UINT8 NumMcVal;
+ UINT32 RpDestId;
+ ///
+ /// PCH-LP:
+ /// RP Destination ID RP Destination ID
+ /// 1 0x18100 7 0x18302
+ /// 2 0x18101 8 0x18303
+ /// 3 0x18102 9 0x18500
+ /// 4 0x18103 10 0x18501
+ /// 5 0x18300 11 0x18502
+ /// 6 0x18301 12 0x18503
+ ///
+ static UINT32 PchSklLpRpDestId[PCH_LP_PCIE_MAX_ROOT_PORTS] =
+ {
+ 0x18100, 0x18101, 0x18102, 0x18103, 0x18300,
+ 0x18301, 0x18302, 0x18303, 0x18500, 0x18501,
+ 0x18502, 0x18503
+ };
+ ///
+ /// PCH-H:
+ /// RP Destination ID RP Destination ID
+ /// 1 0x18000 11 0x18302
+ /// 2 0x18001 12 0x18303
+ /// 3 0x18002 13 0x18500
+ /// 4 0x18003 14 0x18501
+ /// 5 0x18100 15 0x18502
+ /// 6 0x18101 16 0x18503
+ /// 7 0x18102 17 0x18700
+ /// 8 0x18103 18 0x18701
+ /// 9 0x18300 19 0x18702
+ /// 10 0x18301 20 0x18703
+ ///
+ /// KBL-H: same as SKL-H plus the following 4 ports
+ /// 21 0x18800 23 0x18802
+ /// 22 0x18801 24 0x18803
+ ///
+ static UINT32 PchHRpDestId[KBL_PCH_H_PCIE_MAX_ROOT_PORTS] =
+ {
+ 0x18000, 0x18001, 0x18002, 0x18003,
+ 0x18100, 0x18101, 0x18102, 0x18103,
+ 0x18300, 0x18301, 0x18302, 0x18303,
+ 0x18500, 0x18501, 0x18502, 0x18503,
+ 0x18700, 0x18701, 0x18702, 0x18703,
+ 0x18800, 0x18801, 0x18802, 0x18803
+ };
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGen;
+ UINT16 PsfReg;
+
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ PchSeries = GetPchSeries ();
+ PchGen = GetPchGeneration ();
+
+ ///
+ /// If there is an IOAPIC discovered behind root port program PSF Multicast registers
+ /// accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
+ ///
+ ///
+ ///
+ ///
+ /// Read PSF_1_PSF_MC_CONTROL_MCAST0_RS0_EOI bit [7:1], increase it by 1, write back
+ ///
+ if (PchSeries == PchLp) {
+ PsfReg = R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
+ } else {
+ if (PchGen == KblPch) {
+ PsfReg = R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
+ } else {
+ PsfReg = R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
+ }
+ }
+ PchPcrRead32 (PID_PSF1, PsfReg, &Data32);
+ NumMcVal = (UINT8) (Data32 >> 1);
+ Data32 += 0x2;
+ PchPcrWrite32 (PID_PSF1, PsfReg, Data32);
+
+ ///
+ /// Program PSF_1_PSF_MC_AGENT_MCAST0_RS0_TGT<x>_EOI, the next empty register,
+ /// where x is the same as the value read in step 1 before the increment.
+ /// Program this register according to the RP# and the table below
+ ///
+ if (PchSeries == PchLp) {
+ PsfReg = R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ RpDestId = PchSklLpRpDestId[RpIndex];
+ } else {
+ if (PchGen == KblPch) {
+ PsfReg = R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ } else {
+ PsfReg = R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ }
+ RpDestId = PchHRpDestId[RpIndex];
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, PsfReg + (NumMcVal * 4),
+ (UINT32) ~0,
+ RpDestId
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reload default RP PSF device number and function number.
+ The PSF register doesn't got reset after system reset, which will result in mismatch between
+ PSF register setting and PCIE PCR PCD register setting. Reset PSF register in early phase
+ to avoid cycle decoding confusing.
+
+ @param[in] None
+
+ @retval Status
+**/
+VOID
+PsfReloadDefaultPcieRpDevFunc (
+ VOID
+ )
+{
+ UINT16 Psf1RpFuncCfgBase;
+ UINTN PortIndex;
+ UINTN MaxPciePorts;
+
+ PortIndex = 0;
+ MaxPciePorts = GetPchMaxPciePortNum ();
+
+ if (GetPchSeries () == PchLp) {
+ Psf1RpFuncCfgBase = R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ Psf1RpFuncCfgBase = R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ Psf1RpFuncCfgBase = R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ }
+ }
+ //
+ // Reload D28 registers
+ //
+ for (; PortIndex < 8; PortIndex++) {
+ PchPcrWrite32 (
+ PID_PSF1,
+ Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
+ (PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
+ ((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+ }
+ //
+ // Reload D29 registers
+ //
+ for (; PortIndex < 16 && PortIndex < MaxPciePorts; PortIndex++) {
+ PchPcrWrite32 (
+ PID_PSF1,
+ Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
+ (PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
+ ((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+ }
+ //
+ // Reload D27 registers
+ //
+ for (; PortIndex < MaxPciePorts; PortIndex++) {
+ PchPcrWrite32 (
+ PID_PSF1,
+ Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
+ (PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
+ ((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+ }
+}
+
+
+/**
+ Assign new function number for PCIe Port Number.
+ This function will also perform S3 boot script programming
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+ @param[in] NewFunction New Function number
+
+ @retval None
+**/
+VOID
+PsfSetPcieFunctionWithS3BootScript (
+ IN UINT32 RpIndex,
+ IN UINT32 NewFunction
+ )
+{
+ UINT16 PsfRpFuncCfgBase;
+ UINT16 PsfD28F0FuncCfgBase;
+ UINT32 Data32;
+
+ if (GetPchSeries () == PchLp) {
+ PsfD28F0FuncCfgBase = R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ PsfD28F0FuncCfgBase = R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ PsfD28F0FuncCfgBase = R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ }
+ }
+
+ PsfRpFuncCfgBase = PsfD28F0FuncCfgBase + 4 * (UINT16)RpIndex;
+
+ //
+ // Program PSF1 RP function config register.
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ PsfRpFuncCfgBase,
+ (UINT32) ~B_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION,
+ (UINT32) (NewFunction << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+
+ PchPcrRead32 (PID_PSF1, PsfRpFuncCfgBase, &Data32);
+ PCH_PCR_BOOT_SCRIPT_WRITE (
+ S3BootScriptWidthUint32,
+ PID_PSF1,
+ PsfRpFuncCfgBase,
+ 1,
+ &Data32
+ );
+}
+
+/**
+ This function enables PCIe Relaxed Order in PSF
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfEnablePcieRelaxedOrder (
+ VOID
+ )
+{
+ ///
+ /// PCH BIOS Spec Section 8.2.9
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ R_PCH_PCR_PSF_PORT_CONFIG_PG0_PORT0,
+ ~0u,
+ BIT1
+ );
+}
+
+/**
+ Configure PSF power management.
+ Must be called after all PSF configuration is completed.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfConfigurePowerManagement (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (PID_PSF1, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF2, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF3, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF4, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_CSME_PSF, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF2, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+ PchPcrAndThenOr32 (PID_PSF3, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+ PchPcrAndThenOr32 (PID_PSF4, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+ PchPcrAndThenOr32 (PID_CSME_PSF, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+}
+
+/**
+ Enable VTd support in PSF.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PchPsfEnableVtd (
+ VOID
+ )
+{
+ STATIC PCH_SBI_PID PsfPidTable[] = {PID_PSF1, PID_PSF2, PID_PSF3, PID_PSF4};
+ UINTN PsfPidIndex;
+
+ for (PsfPidIndex = 0; PsfPidIndex < (sizeof (PsfPidTable) / sizeof (PsfPidTable[0])); PsfPidIndex++) {
+ PchPcrAndThenOr32 (
+ PsfPidTable[PsfPidIndex],
+ R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS0,
+ ~0u,
+ B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_VTDEN
+ );
+ }
+}
+
+/**
+ Disable PSF address-based peer-to-peer decoding.
+**/
+VOID
+PchPsfDisableP2pDecoding (
+ VOID
+ )
+{
+ STATIC PCH_SBI_PID PsfPidTable[] = {PID_PSF1, PID_PSF2, PID_PSF3, PID_PSF4};
+ UINTN PsfPidIndex;
+
+ for (PsfPidIndex = 0; PsfPidIndex < (sizeof (PsfPidTable) / sizeof (PsfPidTable[0])); PsfPidIndex++) {
+ PchPcrAndThenOr32 (
+ PsfPidTable[PsfPidIndex],
+ R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS0,
+ (UINT32)~B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_ENADDRP2P,
+ 0
+ );
+
+ PchPcrAndThenOr32 (
+ PsfPidTable[PsfPidIndex],
+ R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS1,
+ (UINT32)~B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_ENADDRP2P,
+ 0
+ );
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf
new file mode 100644
index 0000000000..6995171b10
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf
@@ -0,0 +1,47 @@
+## @file
+# Component description file for the PeiDxeSmmPchPsfPrivateLib
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmPchPsfPrivateLib
+FILE_GUID = 7A6C18CA-0353-433E-885D-DD68BFAD38BE
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPsfPrivateLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+ PchInfoLib
+ PchPcrLib
+ PchPcieRpLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+ PchPsfPrivateLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c
new file mode 100644
index 0000000000..ad5c784bff
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c
@@ -0,0 +1,652 @@
+/** @file
+ PCH Smbus Executive Code (common PEI/DXE/SMM code)
+
+Copyright (c) 2017, 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 that 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 <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+#include <IndustryStandard/SmBus.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchSmbusCommonLib.h>
+
+/**
+ Get SMBUS IO Base address
+
+
+ @retval UINT32 The SMBUS IO Base Address
+**/
+UINT32
+SmbusGetIoBase (
+ VOID
+ )
+{
+ UINT32 SmbusIoBase;
+
+ SmbusIoBase = MmioRead32 (
+ MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS)
+ + R_PCH_SMBUS_BASE) & B_PCH_SMBUS_BASE_BAR;
+
+ ASSERT (SmbusIoBase != B_PCH_SMBUS_BASE_BAR && SmbusIoBase != 0);
+
+ return SmbusIoBase;
+}
+
+/**
+ This function provides a standard way to read PCH Smbus IO registers.
+
+ @param[in] Offset Register offset from Smbus base IO address.
+
+ @retval UINT8 Returns data read from IO.
+**/
+UINT8
+EFIAPI
+SmbusIoRead (
+ IN UINT8 Offset
+ )
+{
+ return IoRead8 (SmbusGetIoBase () + Offset);
+}
+
+/**
+ This function provides a standard way to write PCH Smbus IO registers.
+
+ @param[in] Offset Register offset from Smbus base IO address.
+ @param[in] Data Data to write to register.
+
+**/
+VOID
+EFIAPI
+SmbusIoWrite (
+ IN UINT8 Offset,
+ IN UINT8 Data
+ )
+{
+ ///
+ /// Write New Value
+ ///
+ IoWrite8 (SmbusGetIoBase () + Offset, Data);
+ return;
+}
+
+/**
+ This function provides a standard way to check if an SMBus transaction has
+ completed.
+
+ @param[in] StsReg Not used for input. On return, contains the
+ value of the SMBus status register.
+
+ @retval TRUE Transaction is complete
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+IoDone (
+ IN UINT8 *StsReg
+ )
+{
+ ///
+ /// Wait for IO to complete
+ ///
+ UINTN StallIndex;
+ UINTN StallTries;
+
+ StallTries = STALL_TIME / STALL_PERIOD;
+
+ for (StallIndex = 0; StallIndex < StallTries; StallIndex++) {
+ *StsReg = SmbusIoRead (R_PCH_SMBUS_HSTS);
+ if (*StsReg & (B_PCH_SMBUS_INTR | B_PCH_SMBUS_BYTE_DONE_STS | B_PCH_SMBUS_DERR | B_PCH_SMBUS_BERR)) {
+ return TRUE;
+ } else {
+ MicroSecondDelay (STALL_PERIOD);
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Check if it's ok to use the bus.
+
+
+ @retval EFI_SUCCESS SmBus is acquired and it's safe to send commands.
+ @retval EFI_TIMEOUT SmBus is busy, it's not safe to send commands.
+**/
+EFI_STATUS
+AcquireBus (
+ VOID
+ )
+{
+ UINT8 StsReg;
+
+ StsReg = 0;
+ StsReg = SmbusIoRead (R_PCH_SMBUS_HSTS);
+ if (StsReg & B_PCH_SMBUS_IUS) {
+ return EFI_TIMEOUT;
+ } else if (StsReg & B_PCH_SMBUS_HBSY) {
+ ///
+ /// Clear Status Register and exit
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ return EFI_TIMEOUT;
+ } else {
+ ///
+ /// Clear out any odd status information (Will Not Clear In Use)
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, StsReg);
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ This function provides a standard way to execute Smbus protocols
+ as defined in the SMBus Specification. The data can either be of
+ the Length byte, word, or a block of data. The resulting transaction will be
+ either the SMBus Slave Device accepts this transaction or this function
+ returns with an error
+
+ @param[in] SlaveAddress Smbus Slave device the command is directed at
+ @param[in] Command Slave Device dependent
+ @param[in] Operation Which SMBus protocol will be used
+ @param[in] PecCheck Defines if Packet Error Code Checking is to be used
+ @param[in, out] Length How many bytes to read. Must be 0 <= Length <= 32 depending on Operation
+ It will contain the actual number of bytes read/written.
+ @param[in, out] Buffer Contain the data read/written.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @exception EFI_UNSUPPORTED The operation is unsupported.
+
+ @retval EFI_INVALID_PARAMETER Length or Buffer is NULL for any operation besides
+ quick read or quick write.
+ @retval EFI_TIMEOUT The transaction did not complete within an internally
+ specified timeout period, or the controller is not
+ available for use.
+ @retval EFI_DEVICE_ERROR There was an Smbus error (NACK) during the operation.
+ This could indicate the slave device is not present
+ or is in a hung condition.
+**/
+EFI_STATUS
+SmbusExec (
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 AuxcReg;
+ UINT8 AuxStsReg;
+ UINT8 SmbusOperation;
+ UINT8 StsReg;
+ UINT8 SlvAddrReg;
+ UINT8 HostCmdReg;
+ UINT8 BlockCount;
+ BOOLEAN BufferTooSmall;
+ UINTN Index;
+ UINTN BusIndex;
+ UINT8 *CallBuffer;
+ UINT8 SmbusHctl;
+ UINT32 Timeout;
+
+ CallBuffer = Buffer;
+ BlockCount = 0;
+
+ ///
+ /// For any operations besides quick read & write, the pointers to
+ /// Length and Buffer must not be NULL.
+ ///
+ if ((Operation != EfiSmbusQuickRead) && (Operation != EfiSmbusQuickWrite)) {
+ if ((Length == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ ///
+ /// See if its ok to use the bus based upon INUSE_STS bit.
+ ///
+ Status = AcquireBus ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// This is the main operation loop. If the operation results in a Smbus
+ /// collision with another master on the bus, it attempts the requested
+ /// transaction again at least BUS_TRIES attempts.
+ ///
+ for (BusIndex = 0; BusIndex < BUS_TRIES; BusIndex++) {
+ ///
+ /// Operation Specifics (pre-execution)
+ ///
+ Status = EFI_SUCCESS;
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_QUICK;
+ SlvAddrReg = (UINT8) ((SlaveAddress.SmbusDeviceAddress << 1) | 1);
+ HostCmdReg = (UINT8) Command;
+ AuxcReg = 0;
+
+ switch (Operation) {
+
+ case EfiSmbusQuickWrite:
+ SlvAddrReg--;
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusQuickRead:
+ if (PecCheck == TRUE) {
+ Status = EFI_UNSUPPORTED;
+ }
+ break;
+
+ case EfiSmbusSendByte:
+ HostCmdReg = CallBuffer[0];
+ SlvAddrReg--;
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusReceiveByte:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE;
+ if (*Length < 1) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 1;
+ break;
+
+ case EfiSmbusWriteByte:
+ SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
+ SlvAddrReg--;
+ *Length = 1;
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusReadByte:
+ if (*Length < 1) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ } else if (*Length == 1) {
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA;
+ } else if (*Length <= 256) {
+ if (PecCheck == TRUE) {
+ ///
+ /// The I2C Read command with either PEC_EN or AAC bit set
+ /// produces undefined results.
+ ///
+ Status = EFI_UNSUPPORTED;
+ }
+
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_IIC_READ;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ break;
+
+ case EfiSmbusReadWord:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_WORD_DATA;
+ if (*Length < 2) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 2;
+ break;
+
+ case EfiSmbusWriteWord:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_WORD_DATA;
+ SlvAddrReg--;
+ SmbusIoWrite (R_PCH_SMBUS_HD1, CallBuffer[1]);
+ SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
+ if (*Length < 2) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 2;
+ break;
+
+ case EfiSmbusWriteBlock:
+ SmbusIoWrite (R_PCH_SMBUS_HD0, *(UINT8 *) Length);
+ SlvAddrReg--;
+ BlockCount = (UINT8) (*Length);
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusReadBlock:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK;
+ if ((*Length < 1) || (*Length > 32)) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ AuxcReg |= B_PCH_SMBUS_E32B;
+ break;
+
+ case EfiSmbusProcessCall:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_PROCESS_CALL;
+ SmbusIoWrite (R_PCH_SMBUS_HD1, CallBuffer[1]);
+ SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
+ if (*Length < 2) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 2;
+ break;
+
+ case EfiSmbusBWBRProcessCall:
+ ///
+ /// The write byte count cannot be zero or more than
+ /// 32 bytes.
+ ///
+ if ((*Length < 1) || (*Length > 32)) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ SmbusIoWrite (R_PCH_SMBUS_HD0, *(UINT8 *) Length);
+ BlockCount = (UINT8) (*Length);
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS;
+
+ AuxcReg |= B_PCH_SMBUS_E32B;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (PecCheck == TRUE) {
+ AuxcReg |= B_PCH_SMBUS_AAC;
+ }
+ ///
+ /// Set Auxiliary Control register
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_AUXC, AuxcReg);
+
+ ///
+ /// Reset the pointer of the internal buffer
+ ///
+ SmbusIoRead (R_PCH_SMBUS_HCTL);
+
+ ///
+ /// Now that the 32 byte buffer is turned on, we can write th block data
+ /// into it
+ ///
+ if ((Operation == EfiSmbusWriteBlock) || (Operation == EfiSmbusBWBRProcessCall)) {
+ for (Index = 0; Index < BlockCount; Index++) {
+ ///
+ /// Write next byte
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HBD, CallBuffer[Index]);
+ }
+ }
+ ///
+ /// Set SMBus slave address for the device to send/receive from
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_TSA, SlvAddrReg);
+
+ ///
+ /// For I2C read, send DATA1 register for the offset (address)
+ /// within the serial memory chips
+ ///
+ if ((Operation == EfiSmbusReadByte) && (*Length > 1)) {
+ SmbusIoWrite (R_PCH_SMBUS_HD1, HostCmdReg);
+ } else {
+ ///
+ /// Set Command register
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HCMD, HostCmdReg);
+ }
+ ///
+ /// Set Control Register (Initiate Operation, Interrupt disabled)
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HCTL, (UINT8) (SmbusOperation + B_PCH_SMBUS_START));
+
+ ///
+ /// Wait for IO to complete
+ ///
+ if (!IoDone (&StsReg)) {
+ Status = EFI_TIMEOUT;
+ break;
+ } else if (StsReg & B_PCH_SMBUS_DERR) {
+ AuxStsReg = SmbusIoRead (R_PCH_SMBUS_AUXS);
+ if (AuxStsReg & B_PCH_SMBUS_CRCE) {
+ Status = EFI_CRC_ERROR;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ break;
+ } else if (StsReg & B_PCH_SMBUS_BERR) {
+ ///
+ /// Clear the Bus Error for another try
+ ///
+ Status = EFI_DEVICE_ERROR;
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
+ ///
+ /// Clear Status Registers
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ SmbusIoWrite (R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
+ ///
+ /// If bus collision happens, stall some time, then try again
+ /// Here we choose 10 milliseconds to avoid MTCP transfer.
+ ///
+ MicroSecondDelay (STALL_PERIOD);
+ continue;
+ }
+ ///
+ /// successfull completion
+ /// Operation Specifics (post-execution)
+ ///
+ switch (Operation) {
+
+ case EfiSmbusReadWord:
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusProcessCall:
+ CallBuffer[1] = SmbusIoRead (R_PCH_SMBUS_HD1);
+ CallBuffer[0] = SmbusIoRead (R_PCH_SMBUS_HD0);
+ break;
+
+ case EfiSmbusReadByte:
+ if (*Length > 1) {
+ for (Index = 0; Index < *Length; Index++) {
+ ///
+ /// Read the byte
+ ///
+ CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
+ ///
+ /// After receiving byte n-1 (1-base) of the message, the
+ /// software will then set the LAST BYTE bit. The software
+ /// will then clear the BYTE_DONE_STS bit.
+ ///
+ if (Index == ((*Length - 1) - 1)) {
+ SmbusHctl = SmbusIoRead (R_PCH_SMBUS_HCTL) | (UINT8) B_PCH_SMBUS_LAST_BYTE;
+ SmbusIoWrite (R_PCH_SMBUS_HCTL, SmbusHctl);
+ } else if (Index == (*Length - 1)) {
+ ///
+ /// Clear the LAST BYTE bit after receiving byte n (1-base) of the message
+ ///
+ SmbusHctl = SmbusIoRead (R_PCH_SMBUS_HCTL) & (UINT8) ~B_PCH_SMBUS_LAST_BYTE;
+ SmbusIoWrite (R_PCH_SMBUS_HCTL, SmbusHctl);
+ }
+ ///
+ /// Clear the BYTE_DONE_STS bit
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS);
+ ///
+ /// Check BYTE_DONE_STS bit to know if it has completed transmission
+ /// of a byte. No need to check it for the last byte.
+ ///
+ if (Index < (*Length - 1)) {
+ ///
+ /// If somehow board operates at 10Khz, it will take 0.9 ms (9/10Khz) for another byte.
+ /// Add 10 us delay for a loop of 100 that the total timeout is 1 ms to take care of
+ /// the slowest case.
+ ///
+ for (Timeout = 0; Timeout < 100; Timeout++) {
+ if ((SmbusIoRead (R_PCH_SMBUS_HSTS) & (UINT8) B_PCH_SMBUS_BYTE_DONE_STS) != 0) {
+ break;
+ }
+ ///
+ /// Delay 10 us
+ ///
+ MicroSecondDelay (STALL_PERIOD);
+ }
+
+ if (Timeout >= 100) {
+ Status = EFI_TIMEOUT;
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case EfiSmbusReceiveByte:
+ CallBuffer[0] = SmbusIoRead (R_PCH_SMBUS_HD0);
+ break;
+
+ case EfiSmbusWriteBlock:
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS);
+ break;
+
+ case EfiSmbusReadBlock:
+ BufferTooSmall = FALSE;
+ ///
+ /// Find out how many bytes will be in the block
+ ///
+ BlockCount = SmbusIoRead (R_PCH_SMBUS_HD0);
+ if (*Length < BlockCount) {
+ BufferTooSmall = TRUE;
+ } else {
+ for (Index = 0; Index < BlockCount; Index++) {
+ ///
+ /// Read the byte
+ ///
+ CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
+ }
+ }
+
+ *Length = BlockCount;
+ if (BufferTooSmall) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+ break;
+
+ case EfiSmbusBWBRProcessCall:
+ ///
+ /// Find out how many bytes will be in the block
+ ///
+ BlockCount = SmbusIoRead (R_PCH_SMBUS_HD0);
+ ///
+ /// The read byte count cannot be zero.
+ ///
+ if (BlockCount < 1) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ break;
+ }
+ ///
+ /// The combined data payload (the write byte count + the read byte count)
+ /// must not exceed 32 bytes
+ ///
+ if (((UINT8) (*Length) + BlockCount) > 32) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ for (Index = 0; Index < BlockCount; Index++) {
+ ///
+ /// Read the byte
+ ///
+ CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
+ }
+
+ *Length = BlockCount;
+ break;
+
+ default:
+ break;
+ };
+
+ if ((StsReg & B_PCH_SMBUS_BERR) && (Status != EFI_BUFFER_TOO_SMALL)) {
+ ///
+ /// Clear the Bus Error for another try
+ ///
+ Status = EFI_DEVICE_ERROR;
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
+ ///
+ /// If bus collision happens, stall some time, then try again
+ /// Here we choose 10 milliseconds to avoid MTCP transfer.
+ ///
+ MicroSecondDelay (STALL_PERIOD);
+ continue;
+ } else {
+ break;
+ }
+ }
+ ///
+ /// Clear Status Registers and exit
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ SmbusIoWrite (R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
+ SmbusIoWrite (R_PCH_SMBUS_AUXC, 0);
+ return Status;
+}
+
+/**
+ This function initializes the Smbus Registers.
+
+**/
+VOID
+InitializeSmbusRegisters (
+ VOID
+ )
+{
+ UINTN SmbusRegBase;
+
+ SmbusRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+ ///
+ /// Enable the Smbus I/O Enable
+ ///
+ MmioOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, (UINT8) EFI_PCI_COMMAND_IO_SPACE);
+
+ ///
+ /// Enable the Smbus host controller
+ ///
+ MmioAndThenOr8 (
+ SmbusRegBase + R_PCH_SMBUS_HOSTC,
+ (UINT8) (~(B_PCH_SMBUS_HOSTC_SMI_EN | B_PCH_SMBUS_HOSTC_I2C_EN)),
+ B_PCH_SMBUS_HOSTC_HST_EN
+ );
+
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf
new file mode 100644
index 0000000000..54a67614af
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the PchSmbusCommonLib
+#
+# Copyright (c) 2017, 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 = PeiDxeSmmPchSmbusCommonLib
+ FILE_GUID = 490CEB45-F3A8-41CD-89CB-C47BF7F7A4B4
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchSmbusCommonLib
+
+[Sources]
+ PchSmbusExec.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ MmPciLib
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c
new file mode 100644
index 0000000000..7436a76ec1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c
@@ -0,0 +1,216 @@
+/** @file
+ Routines for Rst remapping
+
+Copyright (c) 2017, 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 that 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 <Library/RstPrivateLib.h>
+#include <PchPcieStorageDetectHob.h>
+
+/**
+ Checks whether device on given Root Port is remap capable
+
+ @param[in] RpNumber Root Port Number
+ @param[in] TempPciBus Temporary Pci Bus
+
+ @retval UINT8 Device Programming Interface
+**/
+UINT8
+RstGetProgInterfaceForRemapDevice (
+ IN UINT32 RpNumber,
+ IN UINT32 TempPciBus
+)
+{
+ UINTN RpDevice;
+ UINTN RpFunction;
+ UINT8 BusNumber;
+ UINTN EpBase;
+ UINT8 PiInterface;
+ UINTN RpBase;
+ UINT8 ClassCode;
+ UINT8 SubClassCode;
+
+
+ DEBUG ((DEBUG_INFO, "Detect storage device on Rp: %d\n", RpNumber));
+
+ GetPchPcieRpDevFun (RpNumber, &RpDevice, &RpFunction);
+ BusNumber = DEFAULT_PCI_BUS_NUMBER_PCH;
+ PiInterface = RST_PCIE_STORAGE_INTERFACE_NONE;
+ RpBase = MmPciBase (BusNumber, (UINT32) RpDevice, (UINT32) RpFunction);
+
+ if (MmioRead16 (RpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ DEBUG((DEBUG_INFO, "RstGetProgInterfaceForRemapDevices: RootPort does not exists Rp = %d\n", RpNumber));
+
+ return PiInterface;
+ }
+
+ //
+ // Assign Temporary Bus Number
+ //
+ MmioAndThenOr32 (
+ RpBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ (UINT32) ~B_PCI_BRIDGE_BNUM_SBBN_SCBN,
+ ((UINT32) (TempPciBus << 8)) | ((UINT32) (TempPciBus << 16))
+ );
+
+ //
+ // A config write is required in order for the device to re-capture the Bus number,
+ // according to PCI Express Base Specification, 2.2.6.2
+ // Write to a read-only register VendorID to not cause any side effects.
+ //
+ EpBase = MmPciBase (TempPciBus, 0, 0);
+ MmioWrite16 (EpBase + PCI_VENDOR_ID_OFFSET, 0);
+
+ //
+ // Read Vendor Id to check if device exists
+ // if not clear bus number and return RST_PCIE_STORAGE_INTERFACE_NONE
+ //
+ if (MmioRead16 (EpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ MmioAnd32 (RpBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, (UINT32) ~B_PCI_BRIDGE_BNUM_SBBN_SCBN);
+ return PiInterface;
+ }
+
+ ClassCode = MmioRead8 (EpBase + R_PCI_BCC_OFFSET);
+ SubClassCode = MmioRead8 (EpBase + R_PCI_SCC_OFFSET);
+ PiInterface = MmioRead8 (EpBase + R_PCI_PI_OFFSET);
+
+ if ( ClassCode == PCI_CLASS_MASS_STORAGE) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: ClassCode = %X, SubClassCode = %X, PiInterface = %X\n", ClassCode, SubClassCode, PiInterface));
+
+ if (SubClassCode == PCI_CLASS_MASS_STORAGE_AHCI) {
+ if (PiInterface == RST_PCIE_STORAGE_INTERFACE_AHCI) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: AHCI Card found on Rp: %d\n", RpNumber));
+
+ }
+ } else if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVME) {
+ if (PiInterface == RST_PCIE_STORAGE_INTERFACE_NVME) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: NVMe Card found on Rp: %d\n", RpNumber));
+
+ }
+ } else if (SubClassCode == PCI_CLASS_MASS_STORAGE_RAID) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: RAID Card found on Rp: %d\n", RpNumber));
+
+ PiInterface = RST_PCIE_STORAGE_INTERFACE_NVME;
+ }
+ }
+ //
+ // Clear temporary bus number
+ //
+ MmioAnd32 (RpBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, (UINT32) ~B_PCI_BRIDGE_BNUM_SBBN_SCBN);
+
+ return PiInterface;
+
+}
+
+/**
+ Check the lane occupied by certain root port according to the root port number and configuration strap
+ Return 8-bit bitmap where each bit represents the lane number (e.g.: return 00000011b means the root port owns 2 lane)
+
+ @param[in] RootPortNum Root Port Number
+
+ @retval UINT8 Lane Occupied by the Root Port (bitmap)
+**/
+UINT8
+RstGetRpLaneOccupyMask (
+ IN UINT32 RootPortNum
+ )
+{
+ EFI_STATUS Status;
+ UINT32 CtrlNum;
+ UINT32 CtrlFirstRpNum;
+ UINT32 Data32;
+ UINT8 LaneOccupied;
+
+ LaneOccupied = 0;
+
+ CtrlNum = RootPortNum / PCH_PCIE_CONTROLLER_PORTS;
+ CtrlFirstRpNum = CtrlNum * PCH_PCIE_CONTROLLER_PORTS;
+
+ //
+ // Read the Root Port Configuration Straps for the link width, and return LaneOccupied by the Root Port accordingly
+ //
+ Status = PchSbiRpPciRead32 (CtrlFirstRpNum, R_PCH_PCIE_STRPFUSECFG, &Data32);
+ ASSERT_EFI_ERROR (Status);
+
+ switch ((Data32 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC) {
+ case V_PCH_PCIE_STRPFUSECFG_RPC_4:
+ if (RootPortNum % 4 == 0) {
+ LaneOccupied = (BIT3|BIT2|BIT1|BIT0);
+ }
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_2:
+ if ((RootPortNum % 2 == 0)) {
+ LaneOccupied = (BIT1|BIT0);
+ }
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1:
+ if (RootPortNum % 4 == 0) {
+ LaneOccupied = (BIT1|BIT0);
+ } else if (RootPortNum % 4 != 1) {
+ LaneOccupied = BIT0;
+ }
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_1_1_1_1:
+ LaneOccupied = BIT0;
+ break;
+ default:
+ break;
+ }
+
+ return LaneOccupied;
+}
+
+/**
+ Checks PCH generation and returns SATA's GCR.PLS bit number according to root port number with a PCIe storage device
+ connected to.
+
+ @param[in] RootPortNum Root port number which PCIe storage device is connected to
+
+ @retval UINT32 Number of GCR.PLS bit representing root port
+**/
+UINT32
+RstPlsBitNumber (
+ IN UINT32 RootPortNum
+ )
+{
+ if ((GetPchGeneration () == KblPch) && (RstGetCycleRouterNumber (RootPortNum) == RST_PCIE_STORAGE_CR_2)) {
+ return RootPortNum - 2 * PCH_PCIE_CONTROLLER_PORTS;
+ } else {
+ return RootPortNum;
+ }
+}
+
+/**
+ Checks if device with given PCI config space address is Intel's Stony Beach.
+
+ @param[in] EndPointPciBase Address of device's PCI config space
+
+ @retval BOOLEAN TRUE if device is Intel's Stony Beach, FALSE othrwise
+**/
+BOOLEAN
+RstIsStonyBeach (
+ IN UINTN EndPointPciBase
+ )
+{
+ UINT16 DeviceVendorId;
+ UINT16 DeviceDeviceId;
+
+ DeviceVendorId = MmioRead16 (EndPointPciBase + PCI_VENDOR_ID_OFFSET);
+ DeviceDeviceId = MmioRead16 (EndPointPciBase + PCI_DEVICE_ID_OFFSET);
+
+ if (DeviceVendorId == RST_STONY_BEACH_VENDOR_ID && DeviceDeviceId == RST_STONY_BEACH_DEVICE_ID) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf
new file mode 100644
index 0000000000..1bbcc7eda7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf
@@ -0,0 +1,42 @@
+## @file
+# PCH Rst Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PeiDxeSmmRstPrivateLib
+FILE_GUID = FD2B63E7-FBBF-4D77-8A52-6702112EFDC1
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = RstPrivateLib
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcieRpLib
+PchInitCommonLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[Sources]
+PeiDxeSmmRstPrivateLib.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c
new file mode 100644
index 0000000000..789b61170d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c
@@ -0,0 +1,465 @@
+/** @file
+ This is the driver that initializes the Intel PCH.
+
+Copyright (c) 2017, 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 that 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 "PchInit.h"
+#include <Library/PchSerialIoLib.h>
+
+//
+// Module variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA_PROTOCOL mPchNvsAreaProtocol;
+
+extern PCH_RST_PCIE_STORAGE_DETECTION mRstPcieStorageDetection[];
+
+/**
+ Retrieve interrupt information about a PCH device from policy
+
+ @param[in] Device PCI device number
+
+ @retval PCH_DEVICE_INTERRUPT_CONFIG structure with device's interrupt information
+**/
+PCH_DEVICE_INTERRUPT_CONFIG
+GetInterruptPolicy (
+ IN PCH_SERIAL_IO_CONTROLLER Device
+ )
+{
+ PCH_DEVICE_INTERRUPT_CONFIG EmptyRecord;
+ UINT8 DevNum;
+ UINT8 FuncNum;
+ UINT8 Index;
+
+ ZeroMem (&EmptyRecord, sizeof (PCH_DEVICE_INTERRUPT_CONFIG));
+ DevNum = GetSerialIoDeviceNumber (Device);
+ FuncNum = GetSerialIoFunctionNumber (Device);
+
+ for (Index = 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig; Index++) {
+ if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device == DevNum) &&
+ (mPchConfigHob->Interrupt.DevIntConfig[Index].Function == FuncNum)) {
+ return mPchConfigHob->Interrupt.DevIntConfig[Index];
+ }
+ }
+ return EmptyRecord;
+}
+
+/**
+ Update ASL definitions for SerialIo devices.
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+UpdateSerialIoAcpiData (
+ VOID
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER Index;
+
+ for (Index = 0; Index < PCH_SERIALIO_MAX_CONTROLLERS; Index++) {
+ mPchNvsAreaProtocol.Area->SMD[Index] = mPchConfigHob->SerialIo.DevMode[Index];
+ mPchNvsAreaProtocol.Area->SIR[Index] = (GetInterruptPolicy (Index)).Irq;
+ mPchNvsAreaProtocol.Area->SB0[Index] = FindSerialIoBar (Index, 0);
+ mPchNvsAreaProtocol.Area->SB1[Index] = FindSerialIoBar (Index, 1);
+ }
+ if (GetPchSeries () == PchH) {
+ mPchNvsAreaProtocol.Area->SMD[PchSerialIoIndexI2C4] = PchSerialIoDisabled;
+ mPchNvsAreaProtocol.Area->SMD[PchSerialIoIndexI2C5] = PchSerialIoDisabled;
+ }
+
+ //
+ // Update GPIO device ACPI variables
+ //
+ mPchNvsAreaProtocol.Area->GPEN = mPchConfigHob->SerialIo.Gpio;
+ mPchNvsAreaProtocol.Area->SGIR = mPchConfigHob->Interrupt.GpioIrqRoute;
+
+
+ DEBUG ((DEBUG_INFO, "UpdateSerialIoAcpiData() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update NVS Area after RST PCIe Storage Remapping and before Boot
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+PchUpdateNvsAreaAfterRemapping (
+ VOID
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ mPchNvsAreaProtocol.Area->RstPcieStorageInterfaceType[Index] = mRstPcieStorageDetection[Index].DeviceInterface;
+ mPchNvsAreaProtocol.Area->RstPcieStoragePmCapPtr[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.PmCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStoragePcieCapPtr[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.PcieCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStorageL1ssCapPtr[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.L1ssCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl2[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointL1ssControl2;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl1[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointL1ssControl1;
+ mPchNvsAreaProtocol.Area->RstPcieStorageLtrCapPtr[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.LtrCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpLtrData[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointLtrData;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpLctlData16[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointLctlData16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpDctlData16[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointDctlData16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpDctl2Data16[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointDctl2Data16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageRpDctl2Data16[Index] = mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.RootPortDctl2Data16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBar[Index] = mRstPcieStorageDetection[Index].EndPointUniqueMsixTableBar;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBarValue[Index] = mRstPcieStorageDetection[Index].EndPointUniqueMsixTableBarValue;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBar[Index] = mRstPcieStorageDetection[Index].EndPointUniqueMsixPbaBar;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBarValue[Index] = mRstPcieStorageDetection[Index].EndPointUniqueMsixPbaBarValue;
+ mPchNvsAreaProtocol.Area->RstPcieStorageRootPortNum[Index] = mRstPcieStorageDetection[Index].RootPortNum;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ PCH ACPI initialization before Boot Sript Table is closed
+ It update ACPI table and ACPI NVS area.
+
+ @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
+PchAcpiOnEndOfDxe (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+
+ PCH_SERIES PchSeries;
+
+ DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() Start\n"));
+
+ PchSeries = GetPchSeries ();
+
+ ///
+ /// Closed the event to avoid call twice when launch shell
+ ///
+ gBS->CloseEvent (Event);
+
+ //
+ // Init HDA Audio ACPI tables
+ //
+ PchHdAudioAcpiInit ();
+ //
+ // Update ASL definitions for SerialIo devices.
+ //
+ UpdateSerialIoAcpiData ();
+ //
+ // Define and update ASL definitions for Cio2 device (only on PCH-LP).
+ //
+ if (PchSeries >= PchLp) {
+ UpdateCio2AcpiData ();
+ }
+
+ //
+ // Update Pch Nvs Area
+ //
+ PchUpdateNvsArea ();
+
+ //
+ // Patch PchNvsArea Address
+ //
+ PatchPchNvsAreaAddress ();
+
+ DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() End\n"));
+
+ return;
+}
+
+/**
+ Initialize Pch acpi
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiInit (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT EndOfDxeEvent;
+
+ DEBUG ((DEBUG_INFO, "Install PCH NVS protocol\n"));
+
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (PCH_NVS_AREA), (VOID **) &mPchNvsAreaProtocol.Area);
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem ((VOID *) mPchNvsAreaProtocol.Area, sizeof (PCH_NVS_AREA));
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gPchNvsAreaProtocolGuid,
+ &mPchNvsAreaProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Update the NVS Area after RST PCIe Storage Remapping
+ ///
+ PchUpdateNvsAreaAfterRemapping ();
+ //
+ // Register an end of DXE event for PCH ACPI to do tasks before invoking any UEFI drivers,
+ // applications, or connecting consoles,...
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ PchAcpiOnEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ PCH Update NvsArea ExitBootServicesFlag on ExitBootService. This event is used if only ExitBootService is used
+ and not in legacy boot
+
+ @retval None
+**/
+VOID
+EFIAPI
+PchUpdateNvsOnExitBootServices (
+ VOID
+ )
+{
+ mPchNvsAreaProtocol.Area->ExitBootServicesFlag = 1;
+
+ return;
+}
+
+/**
+ Update ASL object before Boot
+
+ @retval EFI_STATUS
+ @retval EFI_NOT_READY The Acpi protocols are not ready.
+**/
+EFI_STATUS
+PchUpdateNvsArea (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PCH_SERIES PchSeries;
+ UINTN Index;
+ UINT32 HpetBaseAdress;
+ GPIO_GROUP GroupToGpeDw0;
+ GPIO_GROUP GroupToGpeDw1;
+ GPIO_GROUP GroupToGpeDw2;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ GPIO_PAD GpioPad;
+ GPIO_PAD_OWN PadOwnVal;
+ GPIO_CONFIG GpioData;
+ UINTN RpDev;
+ UINTN RpFun;
+ UINT32 Data32;
+ UINT16 Data16;
+
+ Status = EFI_SUCCESS;
+ PchSeries = GetPchSeries ();
+
+ //
+ // Update ASL PCIE port address according to root port device and function
+ //
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ Status = GetPchPcieRpDevFun (Index, &RpDev, &RpFun);
+ ASSERT_EFI_ERROR (Status);
+
+ Data32 = ((UINT8) RpDev << 16) | (UINT8) RpFun;
+ mPchNvsAreaProtocol.Area->RpAddress[Index] = Data32;
+
+ //
+ // Update Maximum Snoop Latency and Maximum No-Snoop Latency values for PCIE
+ //
+ mPchNvsAreaProtocol.Area->PcieLtrMaxSnoopLatency[Index] = mPchConfigHob->PcieRp.RootPort[Index].LtrMaxSnoopLatency;
+ mPchNvsAreaProtocol.Area->PcieLtrMaxNoSnoopLatency[Index] = mPchConfigHob->PcieRp.RootPort[Index].LtrMaxNoSnoopLatency;
+ }
+
+ //
+ // Update PCHS.
+ //
+ mPchNvsAreaProtocol.Area->PchSeries = (UINT16) PchSeries;
+ //
+ // Update PCHG.
+ //
+ mPchNvsAreaProtocol.Area->PchGeneration = (UINT16) GetPchGeneration ();
+ //
+ // Update HPET base address.
+ //
+ PchHpetBaseGet (&HpetBaseAdress);
+ mPchNvsAreaProtocol.Area->HPTE = TRUE; // @todo remove the NVS, since it's always enabled.
+ mPchNvsAreaProtocol.Area->HPTB = HpetBaseAdress;
+ //
+ // Update SBREG_BAR.
+ //
+ mPchNvsAreaProtocol.Area->SBRG = PCH_PCR_BASE_ADDRESS;
+
+ //
+ // Update PMC ACPIBASE and PWRMBASE
+ //
+ PchAcpiBaseGet (&Data16);
+ mPchNvsAreaProtocol.Area->PMBS = Data16;
+
+ PchPwrmBaseGet (&Data32);
+ mPchNvsAreaProtocol.Area->PWRM = Data32;
+
+ //
+ // Update GPP_X to GPE_DWX mapping.
+ //
+ GpioGetGroupToGpeDwX (&GroupToGpeDw0, &GroupToGpeDw1, &GroupToGpeDw2);
+
+ //
+ // GPEM is an object for informing how GPIO groups are mapped to GPE.
+ // Mapping for GPP_x is evaluated from (GPEM >> (GroupNumber*2)) & 0x3
+ // Here GroupNumber does not match xxx_GPIO_GROUP type and is always
+ // 0 based (GPP_A = 0, both for LP and H)
+ // Possible values for each group:
+ // 00b - 2-tier
+ // 01b - 1-tier, GPE_DW0
+ // 10b - 1-tier, GPE_DW1
+ // 11b - 1-tier, GPE_DW2
+ //
+ mPchNvsAreaProtocol.Area->GPEM = (0x1 << (GpioGetGroupIndexFromGroup (GroupToGpeDw0) * 2)) |
+ (0x2 << (GpioGetGroupIndexFromGroup (GroupToGpeDw1) * 2)) |
+ (0x3 << (GpioGetGroupIndexFromGroup (GroupToGpeDw2) * 2));
+
+ //
+ // GP2T[GroupIndex] is an object for storing information about GPIO pads which are
+ // enabled for 2-tier GPE event and their interrupt is configured for level
+ // 0b - Gpio Pad which is not 2-tier event or hasn't got level interrupt
+ // 1b - Gpio Pad enabled for 2-tier event and having level interrupt
+ //
+ for (Group = GpioGetLowestGroup (); Group <= GpioGetHighestGroup (); Group++) {
+ Index = GpioGetGroupIndexFromGroup (Group);
+ if (Index >= sizeof (mPchNvsAreaProtocol.Area->GP2T) / sizeof (mPchNvsAreaProtocol.Area->GP2T[0])) {
+ DEBUG ((DEBUG_ERROR, "GpioGetGroupIndexFromGroup (%x) = %x out of GP2T table range\n", Group, GpioGetGroupIndexFromGroup (Group)));
+ continue;
+ }
+ mPchNvsAreaProtocol.Area->GP2T[Index] = 0x0;
+
+ if ((Group == GroupToGpeDw0) ||
+ (Group == GroupToGpeDw1) ||
+ (Group == GroupToGpeDw2)) {
+ //
+ // not 2-tier GPE
+ //
+ continue;
+ }
+
+ for (PadNumber = 0; PadNumber < GpioGetPadPerGroup (Group); PadNumber++) {
+
+ GpioPad = GpioGetGpioPadFromGroupAndPadNumber (Group, PadNumber);
+
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ continue;
+ }
+
+ GpioGetPadConfig (GpioPad, &GpioData);
+
+ if (((GpioData.InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) == GpioIntSci) &&
+ ((GpioData.InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) == GpioIntLevel)) {
+ //
+ // This pad is enabled for GPE and has level interrupt
+ //
+ mPchNvsAreaProtocol.Area->GP2T[Index] |= 1 << PadNumber;
+ }
+ }
+ }
+
+ //
+ // Thermal device in ACPI mode
+ //
+ mPchNvsAreaProtocol.Area->ThermalDeviceAcpiEnabled = mPchConfigHob->Thermal.ThermalDeviceEnable == 2 ? 1 : 0;
+ //
+ // Get Thermal Device interrupt line number
+ //
+ for (Index = 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig; Index++) {
+ if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device == PCI_DEVICE_NUMBER_PCH_THERMAL) &&
+ (mPchConfigHob->Interrupt.DevIntConfig[Index].Function == PCI_FUNCTION_NUMBER_PCH_THERMAL)) {
+ mPchNvsAreaProtocol.Area->ThermalDeviceInterruptLine = mPchConfigHob->Interrupt.DevIntConfig[Index].Irq;
+ }
+ }
+
+ //
+ // SCS Configuration
+ //
+ // Update eMMC HS400 mode enablement
+ //
+ mPchNvsAreaProtocol.Area->EMH4 = (UINT8) mPchConfigHob->Scs.ScsEmmcHs400Enabled;
+
+ //
+ // Update eMMC Driver Strength
+ // Per eMMC 5.01 JEDEC Specification (JESD84-B50.1, Table 186)
+ // Nominal Impedance - Driver Type Values:
+ // 50 Ohm 0x0
+ // 33 Ohm 0x1
+ // 40 Ohm 0x4
+ //
+ switch (mPchConfigHob->Scs.ScsEmmcHs400DriverStrength) {
+ case DriverStrength33Ohm:
+ mPchNvsAreaProtocol.Area->EMDS = 0x1;
+ break;
+ case DriverStrength40Ohm:
+ mPchNvsAreaProtocol.Area->EMDS = 0x4;
+ break;
+ case DriverStrength50Ohm:
+ default:
+ mPchNvsAreaProtocol.Area->EMDS = 0x0;
+ }
+
+ //
+ // CPU SKU
+ //
+ mPchNvsAreaProtocol.Area->CpuSku = GetCpuSku ();
+
+ return Status;
+}
+
+/**
+ Initialize PCH Nvs Area opeartion region.
+
+ @retval EFI_SUCCESS initialized successfully
+ @retval EFI_NOT_FOUND Nvs Area operation region is not found
+**/
+EFI_STATUS
+PatchPchNvsAreaAddress (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Address;
+ UINT16 Length;
+
+ Status = InitializeAslUpdateLib ();
+ ASSERT_EFI_ERROR (Status);
+
+ Address = (UINT32) (UINTN) mPchNvsAreaProtocol.Area;
+ Length = (UINT16) sizeof (PCH_NVS_AREA);
+ DEBUG ((DEBUG_INFO, "PatchPchNvsAreaAddress: PCH NVS Address %x Length %x\n", Address, Length));
+ Status = UpdateNameAslCode (SIGNATURE_32 ('P','N','V','B'), &Address, sizeof (Address));
+ ASSERT_EFI_ERROR (Status);
+ Status = UpdateNameAslCode (SIGNATURE_32 ('P','N','V','L'), &Length, sizeof (Length));
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchCio2Acpi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchCio2Acpi.c
new file mode 100644
index 0000000000..f0abea1323
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchCio2Acpi.c
@@ -0,0 +1,57 @@
+/** @file
+ Initializes PCH CIO2 device ACPI data.
+
+Copyright (c) 2017, 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 that 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 <PchInit.h>
+
+/**
+ Update ASL definitions for CIO2 device.
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+UpdateCio2AcpiData (
+ VOID
+ )
+{
+ UINT32 Index;
+ PCH_STEPPING PchStep;
+
+ DEBUG ((DEBUG_INFO, "UpdateCio2AcpiData() Start\n"));
+ PchStep = PchStepping ();
+
+ //if CIO2 is enabled as ACPI device then update its ACPI data
+ if (PchStep >= PchLpC0) {
+ mPchNvsAreaProtocol.Area->Cio2EnabledAsAcpiDevice = 0;
+ DEBUG ((DEBUG_INFO, "UpdateCio2AcpiData() Cio2 has not been enabled as ACPI device\n"));
+ } else {
+ mPchNvsAreaProtocol.Area->Cio2EnabledAsAcpiDevice = 0;
+ if (mPchConfigHob->Cio2.DeviceEnable == 1) {
+ mPchNvsAreaProtocol.Area->Cio2EnabledAsAcpiDevice = 1;
+ for (Index = 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig; Index++) {
+ if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device == PCI_DEVICE_NUMBER_PCH_CIO2) &&
+ (mPchConfigHob->Interrupt.DevIntConfig[Index].Function == PCI_FUNCTION_NUMBER_PCH_CIO2)) {
+ mPchNvsAreaProtocol.Area->Cio2IrqNumber = mPchConfigHob->Interrupt.DevIntConfig[Index].Irq;
+ DEBUG ((DEBUG_INFO, "UpdateCio2AcpiData() Cio2 has been enabled as ACPI device. Irq number = 0x%x\n", mPchConfigHob->Interrupt.DevIntConfig[Index].Irq));
+ break;
+ }
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "UpdateCio2AcpiData() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c
new file mode 100644
index 0000000000..732dc8905d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c
@@ -0,0 +1,247 @@
+/** @file
+ Initializes the PCH HD Audio ACPI Tables.
+
+Copyright (c) 2017, 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 that 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 <PchInit.h>
+#include <Guid/Acpi.h>
+#include <Library/PcdLib.h>
+#include <Library/PchHdaLib.h>
+
+PCH_HDA_NHLT_ENDPOINTS mPchHdaNhltEndpoints[HdaEndpointMax] =
+{
+ {HdaDmicX1, B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT, FALSE},
+ {HdaDmicX2, (B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT | B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT), FALSE},
+ {HdaDmicX4, (B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT | B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT), FALSE},
+ {HdaBtRender, (B_HDA_BT_NARROWBAND_FORMAT | B_HDA_BT_WIDEBAND_FORMAT | B_HDA_BT_A2DP_FORMAT), FALSE},
+ {HdaBtCapture, (B_HDA_BT_NARROWBAND_FORMAT | B_HDA_BT_WIDEBAND_FORMAT), FALSE},
+ {HdaI2sRender1, (B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT), FALSE},
+ {HdaI2sRender2, (B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT), FALSE},
+ {HdaI2sCapture, (B_HDA_I2S_RTK298_CAPTURE_4CH_48KHZ_24BIT_FORMAT), 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;
+ UINT64 Data64;
+ 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 (UINT64)) {
+ Data64 = *(UINT64 *) ((UINT8 *) Xsdt + Index);
+ Nhlt = (NHLT_ACPI_TABLE *) (UINTN) Data64;
+ 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%016x\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 (mPchHdaNhltEndpoints, &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
+ @param[in] NhltAcpiTableLength
+ @param[in] DspFeatureMask
+**/
+VOID
+UpdateHdaAcpiData (
+ IN UINT64 NhltAcpiTableAddress,
+ IN UINT32 NhltAcpiTableLength,
+ IN UINT32 DspFeatureMask
+ )
+{
+ DEBUG ((DEBUG_INFO, "UpdateHdaAcpiData():\n NHLT Address = 0x%016x, Length = 0x%08x\n", NhltAcpiTableAddress, NhltAcpiTableLength));
+ DEBUG ((DEBUG_INFO, " FeatureMask = 0x%08x\n", DspFeatureMask));
+
+ mPchNvsAreaProtocol.Area->NHLA = NhltAcpiTableAddress;
+ mPchNvsAreaProtocol.Area->NHLL = NhltAcpiTableLength;
+ mPchNvsAreaProtocol.Area->ADFM = DspFeatureMask;
+}
+
+/**
+ Initialize and publish NHLT (Non-HDA Link Table), update NVS variables.
+
+ @param[in] *HdaConfig
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+SetHdaAcpiTable (
+ IN CONST HDAUDIO_HOB *HdaConfig
+ )
+{
+ NHLT_ACPI_TABLE *NhltTable;
+ EFI_STATUS Status;
+ NhltTable = NULL;
+
+
+ switch (HdaConfig->DspEndpointDmic) {
+ case PchHdaDmic1chArray:
+ mPchHdaNhltEndpoints[HdaDmicX1].Enable = TRUE;
+ break;
+ case PchHdaDmic2chArray:
+ mPchHdaNhltEndpoints[HdaDmicX2].Enable = TRUE;
+ break;
+ case PchHdaDmic4chArray:
+ mPchHdaNhltEndpoints[HdaDmicX4].Enable = TRUE;
+ break;
+ case PchHdaDmicDisabled:
+ default:
+ mPchHdaNhltEndpoints[HdaDmicX2].Enable = FALSE;
+ mPchHdaNhltEndpoints[HdaDmicX4].Enable = FALSE;
+ }
+
+ if (HdaConfig->DspEndpointBluetooth) {
+ mPchHdaNhltEndpoints[HdaBtRender].Enable = TRUE;
+ mPchHdaNhltEndpoints[HdaBtCapture].Enable = TRUE;
+ }
+
+ if (HdaConfig->DspEndpointI2s) {
+ mPchHdaNhltEndpoints[HdaI2sRender1].Enable = TRUE;
+ mPchHdaNhltEndpoints[HdaI2sRender2].Enable = TRUE;
+ mPchHdaNhltEndpoints[HdaI2sCapture].Enable = TRUE;
+ }
+
+ Status = PublishNhltAcpiTable ();
+ NhltTable = LocateNhltAcpiTable ();
+ if (NhltTable == NULL) {
+ return EFI_LOAD_ERROR;
+ }
+
+ UpdateHdaAcpiData ((UINT64) (UINTN) NhltTable, (UINT32) (NhltTable->Header.Length), HdaConfig->DspFeatureMask);
+
+ DEBUG_CODE ( NhltAcpiTableDump (NhltTable); );
+ return Status;
+}
+
+/**
+ Initialize Intel High Definition Audio ACPI Tables
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_LOAD_ERROR ACPI table cannot be installed
+ @retval EFI_UNSUPPORTED ACPI table not set because DSP is disabled
+**/
+EFI_STATUS
+PchHdAudioAcpiInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CONST HDAUDIO_HOB *HdaConfig;
+ UINTN HdaPciBase;
+
+ DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() Start\n"));
+
+ HdaConfig = &mPchConfigHob->HdAudio;
+
+ HdaPciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_HDA,
+ PCI_FUNCTION_NUMBER_PCH_HDA
+ );
+
+ if ((MmioRead16 (HdaPciBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) || (HdaConfig->DspEnable == FALSE)) {
+ // Do not set ACPI tables if HDAudio is Function disabled or DSP is disabled
+ DEBUG ((DEBUG_INFO, "AudioDSP: Non-HDAudio ACPI Table (NHLT) not set!\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = SetHdaAcpiTable (HdaConfig);
+
+ DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() End - Status = %r\n", Status));
+ return Status;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c
new file mode 100644
index 0000000000..0428479b50
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c
@@ -0,0 +1,504 @@
+/** @file
+ This is the Common driver that initializes the Intel PCH.
+
+Copyright (c) 2017, 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 that 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 "PchInit.h"
+
+//
+// Module variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_CONFIG_HOB *mPchConfigHob;
+GLOBAL_REMOVE_IF_UNREFERENCED SI_CONFIG_HOB *mSiConfigHob;
+
+/**
+ Common PchInit Module Entry Point
+**/
+VOID
+PchInitEntryPointCommon (
+ VOID
+ )
+{
+ EFI_PEI_HOB_POINTERS HobPtr;
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointCommon() Start\n"));
+
+ //
+ // Get PCH Config HOB.
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gPchConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mPchConfigHob = (PCH_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ //
+ // Get Silicon Config data HOB
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gSiConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mSiConfigHob = (SI_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointCommon() End\n"));
+
+ return;
+}
+
+/**
+ Lock USB registers before boot
+
+ @param[in] PchConfigHob The PCH Config HOB
+**/
+VOID
+LockXhciConfiguration (
+ IN CONST PCH_CONFIG_HOB *PchConfigHob
+ )
+{
+ UINTN XhciPciMmBase;
+ UINT32 XhccCfg;
+
+ DEBUG ((DEBUG_INFO, "LockXhciConfiguration () - Start\n"));
+
+ XhciPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PCI_FUNCTION_NUMBER_PCH_XHCI
+ );
+
+ ///
+ /// PCH BIOS Spec Section 13.2.4 Locking xHCI Register Settings
+ /// PCH BIOS Spec Locking xHCI Register settings
+ /// After xHCI is initialized, BIOS should lock the xHCI configuration registers to RO.
+ /// This prevent any unintended changes. There is also a lockdown feature for OverCurrent
+ /// registers. BIOS should set these bits to lock down the settings prior to end of POST.
+ /// 1. Set Access Control bit at XHCI PCI offset 40h[31] to 1b to lock xHCI register settings.
+ /// 2. Set OC Configuration Done bit at XHCI PCI offset 44h[31] to lock overcurrent mappings from
+ /// further changes.
+ ///
+ MmioOr32 (XhciPciMmBase + R_PCH_XHCI_XHCC2, (UINT32) (BIT31));
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (XhciPciMmBase + R_PCH_XHCI_XHCC2),
+ 1,
+ (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_XHCC2)
+ );
+
+ ///
+ /// PCH BIOS Spec xHCI controller setup
+ /// Note:
+ /// XHCI PCI offset 40h is write once register.
+ /// Unsupported Request Detected bit is write clear
+ ///
+ XhccCfg = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_XHCC1);
+ XhccCfg &= (UINT32) ~(B_PCH_XHCI_XHCC1_URD);
+ XhccCfg |= (UINT32) (B_PCH_XHCI_XHCC1_ACCTRL);
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_XHCC1, XhccCfg);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (XhciPciMmBase + R_PCH_XHCI_XHCC1),
+ 1,
+ (VOID *) (UINTN) (XhciPciMmBase + R_PCH_XHCI_XHCC1)
+ );
+
+ DEBUG ((DEBUG_INFO, "LockXhciConfiguration () - End\n"));
+}
+
+/**
+ Process all the lock downs
+**/
+VOID
+ProcessAllLocks (
+ VOID
+ )
+{
+ UINTN Index;
+ UINT8 Data8;
+ UINT16 Data16And;
+ UINT16 Data16Or;
+ UINT32 Data32;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT32 DlockValue;
+ UINTN PciLpcRegBase;
+ UINTN PciSpiRegBase;
+ UINTN PciPmcRegBase;
+ UINT16 TcoBase;
+ UINT32 PchPwrmBase;
+ UINTN PchSpiBar0;
+
+ PciLpcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ PciPmcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ PciSpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ PchSpiBar0 = MmioRead32 (PciSpiRegBase + R_PCH_SPI_BAR0) &~(B_PCH_SPI_BAR0_MASK);
+
+ PchTcoBaseGet (&TcoBase);
+
+ //
+ // Lock XHCI configuration
+ //
+ LockXhciConfiguration (mPchConfigHob);
+
+ ///
+ /// Set PWRMBASE + 620h [31] to lock the ST and NST PG register fields.
+ ///
+ ConfigurePmcStaticFunctionDisableLock ();
+
+ ///
+ /// SKL PCH BWG 7.2.4 Additional PCH DMI and OP-DMI Programming Steps
+ /// Step 9.2
+ /// Set PCR[DMI] + 2234h [31] = 1b.
+ /// Leave this in DXE since setting it in PEI would break the ActiveBIOS module.
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_PCR_DMI_DMIC_SRL;
+ PchPcrAndThenOr32 (
+ PID_DMI, R_PCH_PCR_DMI_DMIC,
+ Data32And,
+ Data32Or
+ );
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_DMI, R_PCH_PCR_DMI_DMIC,
+ &Data32Or,
+ &Data32And
+ );
+
+
+ ///
+ /// Program the Flash Protection Range Register based on policy
+ ///
+ DlockValue = MmioRead32 (PchSpiBar0 + R_PCH_SPI_DLOCK);
+ for (Index = 0; Index < PCH_FLASH_PROTECTED_RANGES; ++Index) {
+ if ((mPchConfigHob->ProtectRange[Index].WriteProtectionEnable ||
+ mPchConfigHob->ProtectRange[Index].ReadProtectionEnable) != TRUE) {
+ continue;
+ }
+
+ ///
+ /// Proceed to program the register after ensure it is enabled
+ ///
+ Data32 = 0;
+ Data32 |= (mPchConfigHob->ProtectRange[Index].WriteProtectionEnable == TRUE) ? B_PCH_SPI_PRX_WPE : 0;
+ Data32 |= (mPchConfigHob->ProtectRange[Index].ReadProtectionEnable == TRUE) ? B_PCH_SPI_PRX_RPE : 0;
+ Data32 |= ((UINT32) mPchConfigHob->ProtectRange[Index].ProtectedRangeLimit << N_PCH_SPI_PRX_PRL) & B_PCH_SPI_PRX_PRL_MASK;
+ Data32 |= ((UINT32) mPchConfigHob->ProtectRange[Index].ProtectedRangeBase << N_PCH_SPI_PRX_PRB) & B_PCH_SPI_PRX_PRB_MASK;
+ DEBUG ((DEBUG_INFO, "Protected range %d: 0x%08x \n", Index, Data32));
+
+ DlockValue |= (UINT32) (B_PCH_SPI_DLOCK_PR0LOCKDN << Index);
+ MmioWrite32 ((UINTN) (PchSpiBar0 + (R_PCH_SPI_PR0 + (Index * S_PCH_SPI_PRX))), Data32);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + (R_PCH_SPI_PR0 + (Index * S_PCH_SPI_PRX))),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + (R_PCH_SPI_PR0 + (Index * S_PCH_SPI_PRX)))
+ );
+ }
+ //
+ // Program DLOCK register
+ //
+ MmioWrite32 ((UINTN) (PchSpiBar0 + R_PCH_SPI_DLOCK), DlockValue);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + R_PCH_SPI_DLOCK),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + R_PCH_SPI_DLOCK)
+ );
+
+ ///
+ /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
+ /// In PCH 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.
+ /// Please refer to the EDS for which program registers are impacted.
+ ///
+ MmioOr32 ((UINTN) (PchSpiBar0 + R_PCH_SPI_HSFSC), (UINT32) (B_PCH_SPI_HSFSC_FLOCKDN));
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + R_PCH_SPI_HSFSC),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + R_PCH_SPI_HSFSC)
+ );
+
+ ///
+ /// SPI Flash Programming Guide Section 5.5.2 Vendor Component Lock
+ /// It is strongly recommended that BIOS sets the Vendor Component Lock (VCL) bits. VCL applies
+ /// the lock to both VSCC0 and VSCC1 even if VSCC0 is not used. Without the VCL bits set, it is
+ /// possible to make Host/GbE VSCC register(s) changes in that can cause undesired host and
+ /// integrated GbE Serial Flash functionality.
+ ///
+ MmioOr32 ((UINTN) (PchSpiBar0 + R_PCH_SPI_SFDP0_VSCC0), B_PCH_SPI_SFDP0_VSCC0_VCL);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + R_PCH_SPI_SFDP0_VSCC0),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + R_PCH_SPI_SFDP0_VSCC0)
+ );
+
+ ///
+ /// Additional Power Management Programming
+ /// Step 3
+ /// Set GEN_PMCON_LOCK register, PMC PCI offset A6h = 06h, after stretch and ACPI base programming completed.
+ ///
+ MmioOr8 (
+ (UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_B + 2),
+ (UINT8) ((B_PCH_PMC_GEN_PMCON_B_SLPSX_STR_POL_LOCK | B_PCH_PMC_GEN_PMCON_B_ACPI_BASE_LOCK) >> 16)
+ );
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_B + 2),
+ 1,
+ (VOID *) (UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_B + 2)
+ );
+
+ ///
+ /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
+ /// BIOS needs to enable the BIOS Lock Enable (BLE) feature of the PCH by setting
+ /// SPI/eSPI/LPC PCI offset DCh[1] = 1b.
+ /// When this bit is set, attempts to write the BIOS Write Enable (BIOSWE) bit
+ /// in PCH will cause a SMI which will allow the BIOS to verify that the write is
+ /// from a valid source.
+ /// Remember that BIOS needs to set SPI/LPC/eSPI PCI Offset DC [0] = 0b to enable
+ /// BIOS region protection before exiting the SMI handler.
+ /// Also, TCO_EN bit needs to be set (SMI_EN Register, ABASE + 30h[13] = 1b) to keep
+ /// BLE feature enabled after booting to the OS.
+ /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH to
+ /// ensure SMM protection of flash.
+ /// Left to platform code to register a callback function to handle BiosWp SMI
+ ///
+ if (mPchConfigHob->LockDown.BiosLock == TRUE) {
+ //
+ // eSPI/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_PCH_SPI_BC) & B_PCH_SPI_BC_LE)) {
+ DEBUG ((DEBUG_INFO, "Set SPI bios lock\n"));
+ MmioOr8 ((UINTN) (PciSpiRegBase + R_PCH_SPI_BC), (UINT8) B_PCH_SPI_BC_LE);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciSpiRegBase + R_PCH_SPI_BC),
+ 1,
+ (VOID *) (UINTN) (PciSpiRegBase + R_PCH_SPI_BC)
+ );
+ }
+ }
+
+ ///
+ /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
+ /// BIOS also needs to set the BIOS Interface Lock Down bit in multiple locations
+ /// (PCR[DMI] + 274Ch[0], LPC/eSPI PCI offset DCh[7] and SPI PCI offset DCh[7]).
+ /// Setting these bits will prevent writes to the Top Swap bit (under their respective locations)
+ /// and the Boot BIOS Straps. Enabling this bit will mitigate malicious software
+ /// attempts to replace the system BIOS option ROM with its own code.
+ ///
+ if (mPchConfigHob->LockDown.BiosInterface == TRUE) {
+ ///
+ /// LPC
+ ///
+ MmioOr8 ((UINTN) (PciLpcRegBase + R_PCH_LPC_BC), (UINT32) 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_PCH_SPI_BC), (UINT32) B_PCH_SPI_BC_BILD);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciSpiRegBase + R_PCH_SPI_BC),
+ 1,
+ (VOID *) (UINTN) (PciSpiRegBase + R_PCH_SPI_BC)
+ );
+
+ ///
+ /// Reads back for posted write to take effect
+ ///
+ Data8 = MmioRead8 ((UINTN) (PciSpiRegBase + R_PCH_SPI_BC));
+ S3BootScriptSaveMemPoll (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciSpiRegBase + R_PCH_SPI_BC),
+ &Data8, // BitMask
+ &Data8, // BitValue
+ 1, // Duration
+ 1 // LoopTimes
+ );
+
+ ///
+ /// Set PCR[DMI] + 274C[0] = 1b
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_PCR_DMI_BILD;
+ PchPcrAndThenOr32 (PID_DMI, R_PCH_PCR_DMI_GCS, Data32And, Data32Or);
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_DMI, R_PCH_PCR_DMI_GCS,
+ &Data32Or,
+ &Data32And
+ );
+ }
+
+ ///
+ /// PCH BIOS Spec Section 5.13 BIOS guide on using RTC RAM
+ /// For Data integrity protection, set RTC Memory locks (Upper 128 Byte Lock and
+ /// Lower 128 Byte Lock) at SBCR[RTC] + 3400h[4] and SBCR[RTC] + 3400h[3]. Note once locked
+ /// bytes 0x38 - 0x3F in each of the Upper and Lower Byte blocks, respectively,
+ /// cannot be unlocked until next reset.
+ ///
+ if (mPchConfigHob->LockDown.RtcLock == TRUE) {
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (B_PCH_PCR_RTC_CONF_UCMOS_LOCK | B_PCH_PCR_RTC_CONF_LCMOS_LOCK | B_PCH_PCR_RTC_CONF_RESERVED);
+ PchPcrAndThenOr32 (
+ PID_RTC, R_PCH_PCR_RTC_CONF,
+ Data32And,
+ Data32Or
+ );
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_RTC, R_PCH_PCR_RTC_CONF,
+ &Data32Or,
+ &Data32And
+ );
+ }
+
+ ///
+ /// Lock Down TCO
+ ///
+ Data16And = 0xFFFF;
+ Data16Or = B_PCH_TCO_CNT_LOCK;
+ IoOr16 (TcoBase + R_PCH_TCO1_CNT, Data16Or);
+ S3BootScriptSaveIoReadWrite (
+ S3BootScriptWidthUint16,
+ (UINTN) (TcoBase + R_PCH_TCO1_CNT),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+
+ ///
+ /// PCH BIOS Spec Section 5.15.1 Additional Chipset Initialization
+ /// Step 1
+ /// Set SPIBAR0 + F0h [0] to 1b
+ ///
+ MmioOr8 ((UINTN) (PchSpiBar0 + R_PCH_SPI_SSML), B_PCH_SPI_SSML_SSL);
+
+ //
+ // Lock Down PMC
+ // Set PWRM + 0x18 [27, 22] prior to OS.
+ //
+ PchPwrmBaseGet (&PchPwrmBase);
+ Data32Or = BIT27;
+ if (mPchConfigHob->Pm.PmcReadDisable) {
+ Data32Or |= BIT22;
+ }
+ MmioOr32 (PchPwrmBase + R_PCH_PWRM_CFG, Data32Or);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchPwrmBase + R_PCH_PWRM_CFG),
+ 1,
+ (VOID *) (UINTN) (PchPwrmBase + R_PCH_PWRM_CFG)
+ );
+}
+
+/**
+ Set eSPI BME bit
+**/
+VOID
+ConfigureEspiBme (
+ VOID
+ )
+{
+}
+
+/**
+ Common PCH initialization before Boot Sript Table is closed
+
+**/
+VOID
+PchOnPciEnumCompleteCommon (
+ VOID
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteCommon() Start\n"));
+
+ ProcessAllLocks ();
+
+ ///
+ /// Perform remaining configuration for PCH SATA on End of DXE
+ ///
+ ConfigurePchSataOnEndOfDxe ();
+
+ ///
+ /// PSTHCTL (0xD00h[2]) = 1, PSTH IOSF Primary Trunk Clock Gating Enable (PSTHIOSFPTCGE)
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_PCR_PSTH_PSTHIOSFPTCGE;
+ PchPcrAndThenOr32 (PID_PSTH, R_PCH_PCR_PSTH_PSTHCTL, Data32And, Data32Or);
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_PSTH, R_PCH_PCR_PSTH_PSTHCTL,
+ &Data32Or,
+ &Data32And
+ );
+
+ //
+ // Set eSPI BME after PCI enumeration
+ //
+ ConfigureEspiBme ();
+
+ //
+ // This function process P2SB configuration
+ // This MUST be executed in very end of End Of Dxe
+ // All PSF access after this function will not acceptable
+ //
+ ConfigureP2sbSbiLock ((BOOLEAN) mPchConfigHob->P2sb.SbiUnlock);
+
+ DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteCommon() End\n"));
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h
new file mode 100644
index 0000000000..a05697d337
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h
@@ -0,0 +1,320 @@
+/** @file
+ Header file for PCH Initialization Driver.
+
+Copyright (c) 2017, 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 that 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 _PCH_INITIALIZATION_DRIVER_H_
+#define _PCH_INITIALIZATION_DRIVER_H_
+
+typedef UINT16 STRING_REF;
+#ifdef FSP_FLAG
+#include <Library/PeiServicesLib.h>
+#include <Uefi/UefiSpec.h>
+#endif
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchEspiLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/TraceHubInitLib.h>
+#include <Guid/EventGroup.h>
+#include <Library/S3BootScriptLib.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciPlatform.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#ifndef FSP_FLAG
+#include <Library/DxeServicesTableLib.h>
+#endif
+
+#include <PchAccess.h>
+#include <SiConfigHob.h>
+#include <Protocol/PchInfo.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/AslUpdateLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/CpuPlatformLib.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/PchEmmcTuning.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Protocol/PchNvs.h>
+#include <Protocol/PcieIoTrap.h>
+#include <Library/PchInitCommonLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/PchPsfLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <PchConfigHob.h>
+
+typedef struct {
+ PCH_INFO_PROTOCOL PchInfo;
+} PCH_INSTANCE_PRIVATE_DATA;
+
+//
+// This struct is used to record the fields that is required to be saved and restored during RST PCIe Storage Remapping Configuration
+//
+typedef struct {
+ UINT8 PmCapPtr;
+ UINT8 PcieCapPtr;
+ UINT16 L1ssCapPtr;
+ UINT8 EndpointL1ssControl2;
+ UINT32 EndpointL1ssControl1;
+ UINT16 LtrCapPtr;
+ UINT32 EndpointLtrData;
+ UINT16 EndpointLctlData16;
+ UINT16 EndpointDctlData16;
+ UINT16 EndpointDctl2Data16;
+ UINT16 RootPortDctl2Data16;
+} PCH_RST_PCIE_STORAGE_SAVE_RESTORE;
+
+//
+// This struct is used to record the result of RST PCIe Storage detection for each RST PCIe Storage Cycle Router supported on the platform
+//
+typedef struct {
+ BOOLEAN SupportRstPcieStoragRemapping; // Indicates if RST PCIe Storage Remapping is supported and PCIe storage device is found under a Cycle Router
+ UINT8 RootPortNum; // Indicates the root port number with RST PCIe Storage Remapping remapping supported and PCIe storage device plugged on, numbering is 0-based
+ UINT8 RootPortLane; // Indicates the root port lanes occupied by the PCIe storage device with 4-bit mask
+ UINT8 DeviceInterface; // Indicates the interface of the PCIe storage device (AHCI or NVMe)
+ UINT8 IsMsixSupported; // Indicates if the PCIe storage device support MSI-X cap
+ UINT16 MsixStartingVector; // Records the starting vector of PCIe storage device's MSI-X (if supported)
+ UINT16 MsixEndingVector; // Records the ending vector of PCIe storage device's MSI-X (if supported)
+ UINT32 EndPointBarSize; // Records the PCIe storage device's BAR size
+ UINT32 EndPointUniqueMsixTableBar; // Records the PCIe storage device's MSI-X Table BAR if it supports unique MSI-X Table BAR
+ UINT32 EndPointUniqueMsixTableBarValue; // Records the PCIe storage device's MSI-X Table BAR value if it supports unique MSI-X Table BAR
+ UINT32 EndPointUniqueMsixPbaBar; // Records the PCIe storage device's MSI-X PBA BAR if it supports unique MSI-X PBA BAR
+ UINT32 EndPointUniqueMsixPbaBarValue; // Records the PCIe storage device's MSI-X PBA BAR value if it supports unique MSI-X PBA BAR
+ UINT8 EndPointBcc; // Records the PCIe storage device's Base Class Code
+ UINT8 EndPointScc; // Records the PCIe storage device's Sub Class Code
+ UINT8 EndPointPi; // Records the PCIe storage device's Programming Interface
+ PCH_RST_PCIE_STORAGE_SAVE_RESTORE PchRstPcieStorageSaveRestore; // Records the fields that is required to be saved and restored
+} PCH_RST_PCIE_STORAGE_DETECTION;
+
+//
+// Data definitions
+//
+extern EFI_HANDLE mImageHandle;
+
+//
+// Pch NVS area definition
+//
+extern PCH_NVS_AREA_PROTOCOL mPchNvsAreaProtocol;
+
+extern PCH_CONFIG_HOB *mPchConfigHob;
+extern SI_CONFIG_HOB *mSiConfigHob;
+
+//
+// Function Prototype
+//
+
+//
+// Local function prototypes
+//
+/**
+ Initialize the PCH device according to the PCH Policy HOB
+ and install PCH info instance.
+
+**/
+VOID
+InitializePchDevice (
+ VOID
+ );
+
+/**
+ Common PchInit Module Entry Point
+**/
+VOID
+PchInitEntryPointCommon (
+ VOID
+ );
+
+/**
+ Common PCH initialization on PCI enumeration complete.
+**/
+VOID
+PchOnPciEnumCompleteCommon (
+ VOID
+ );
+
+/**
+ Configures Serial IO Controllers
+
+**/
+EFI_STATUS
+ConfigureSerialIoAtBoot (
+ VOID
+ );
+
+/**
+ Creates device handles for SerialIo devices in ACPI mode
+
+**/
+VOID
+CreateSerialIoHandles (
+ VOID
+ );
+
+/**
+ Mark memory used by SerialIo devices in ACPI mode as allocated
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+AllocateSerialIoMemory (
+ VOID
+ );
+
+/**
+ Update ASL definitions for SerialIo devices.
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+UpdateSerialIoAcpiData (
+ VOID
+ );
+
+/**
+ Initialize PCIE SRC clocks in ICC subsystem
+
+ @param[in] GbePortNumber Number of PCIE rootport assigned to GbE adapter
+
+**/
+VOID
+ConfigurePchPcieClocks (
+ IN UINTN GbePortNumber
+ );
+
+/**
+ Initialize Intel High Definition Audio ACPI Tables
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_LOAD_ERROR ACPI table cannot be installed
+ @retval EFI_UNSUPPORTED ACPI table not set because DSP is disabled
+**/
+EFI_STATUS
+PchHdAudioAcpiInit (
+ VOID
+ );
+
+/**
+ Configure eMMC in HS400 Mode
+
+ @param[in] This A pointer to PCH_EMMC_TUNING_PROTOCOL structure
+ @param[in] Revision Revision parameter used to verify the layout of EMMC_INFO and TUNINGDATA.
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[out] EmmcTuningData A pointer to EMMC_TUNING_DATA structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND The item was not found
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+**/
+EFI_STATUS
+EFIAPI
+ConfigureEmmcHs400Mode (
+ IN PCH_EMMC_TUNING_PROTOCOL *This,
+ IN UINT8 Revision,
+ IN EMMC_INFO *EmmcInfo,
+ OUT EMMC_TUNING_DATA *EmmcTuningData
+ );
+
+/**
+ Install PCH EMMC TUNING PROTOCOL
+
+**/
+VOID
+InstallPchEmmcTuningProtocol (
+ VOID
+ );
+
+/**
+ Perform the remaining configuration on PCH SATA to perform device detection,
+ then set the SATA SPD and PxE corresponding, and set the Register Lock on PCH SATA
+
+ @retval None
+**/
+VOID
+ConfigurePchSataOnEndOfDxe (
+ VOID
+ );
+
+/**
+ Update ASL data for CIO2 Device.
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+UpdateCio2AcpiData (
+ VOID
+ );
+
+/**
+ Initialize Pch acpi
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiInit (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ Update ASL object before Boot
+
+ @retval EFI_STATUS
+ @retval EFI_NOT_READY The Acpi protocols are not ready.
+**/
+EFI_STATUS
+PchUpdateNvsArea (
+ VOID
+ );
+
+/**
+ Initialize PCH Nvs Area opeartion region.
+
+ @retval EFI_SUCCESS initialized successfully
+ @retval EFI_NOT_FOUND Nvs Area operation region is not found
+**/
+EFI_STATUS
+PatchPchNvsAreaAddress (
+ VOID
+ );
+
+/**
+ PCH Update NvsArea ExitBootServicesFlag on ExitBootService. This event is used if only ExitBootService is used
+ and not in legacy boot
+
+ @retval None
+**/
+VOID
+EFIAPI
+PchUpdateNvsOnExitBootServices (
+ VOID
+ );
+#endif // _PCH_INITIALIZATION_DRIVER_H_
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c
new file mode 100644
index 0000000000..1857b7f3c5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c
@@ -0,0 +1,699 @@
+/** @file
+ This is the Uefi driver that initializes the Intel PCH.
+
+Copyright (c) 2017, 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 that 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 "PchInit.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mImageHandle;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPcieIoTrapAddress;
+
+
+VOID
+EFIAPI
+PchOnBootToOs (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+VOID
+EFIAPI
+PchOnExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+VOID
+EFIAPI
+PchOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+/**
+ BIOS W/A for Si bug on PCH stepping LpA0, LpA1, LpA2, LpB0:
+ allocates 1MB memory space for ISH BAR,
+ overrides 4KB memory allocation done by standard PCI enumarator.
+
+ @retval EFI_STATUS
+ @retval EFI_SUCCESS Allocation successful or stepping other that A0/A1/A2 (W/A not required)
+ @retval EFI_OUT_OF_RESOURCES Memory could not be allocated.
+**/
+EFI_STATUS
+AllocateIshMemorySpace (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN PciIshRegBase;
+ EFI_PHYSICAL_ADDRESS IshMemBaseAddress;
+
+ PciIshRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_ISH,
+ PCI_FUNCTION_NUMBER_PCH_ISH
+ );
+
+ if ((MmioRead16 (PciIshRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) ||
+ (GetPchSeries () == PchH) ||
+ (PchStepping () > PchLpB1)) {
+ return EFI_SUCCESS;
+ }
+
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ IshMemBaseAddress = 0xffffffff;
+ }
+ Status = gDS->AllocateMemorySpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdMemoryTypeMemoryMappedIo,
+ N_PCH_ISH_BAR0_ALIGNMENT,
+ V_PCH_ISH_BAR0_SIZE,
+ &IshMemBaseAddress,
+ mImageHandle,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ MmioAnd16 (PciIshRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (PciIshRegBase + R_PCH_ISH_BAR0_LOW, (UINT32) IshMemBaseAddress);
+ MmioWrite32 (PciIshRegBase + R_PCH_ISH_BAR0_HIGH, 0);
+ MmioOr16 (PciIshRegBase + PCI_COMMAND_OFFSET, (UINT16) EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ DEBUG ((DEBUG_INFO, "ISH W/A: Allocated 1MB MMIO, BAR0 = 0x%08x\n", (UINT32) IshMemBaseAddress));
+ return Status;
+}
+
+
+/**
+ Process all the lock downs
+**/
+VOID
+ProcessSmiLocks (
+ VOID
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT16 ABase;
+ UINTN PciPmcRegBase;
+
+ PciPmcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+
+ ///
+ /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
+ /// BIOS needs to enables SMI_LOCK (PMC PCI offset A0h[4] = 1b) which prevent writes
+ /// to the Global SMI Enable bit (GLB_SMI_EN ABASE + 30h[0]). Enabling this bit will
+ /// mitigate malicious software attempts to gain system management mode privileges.
+ ///
+ if (mPchConfigHob->LockDown.GlobalSmi == TRUE) {
+ PchAcpiBaseGet (&ABase);
+ ///
+ /// Save Global SMI Enable bit setting before BIOS enables SMI_LOCK during S3 resume
+ ///
+ Data32Or = IoRead32 ((UINTN) (ABase + R_PCH_SMI_EN));
+ if ((Data32Or & B_PCH_SMI_EN_GBL_SMI) != 0) {
+ Data32And = 0xFFFFFFFF;
+ Data32Or |= B_PCH_SMI_EN_GBL_SMI;
+ S3BootScriptSaveIoReadWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (ABase + R_PCH_SMI_EN),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ }
+ MmioOr8 ((UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_A), B_PCH_PMC_GEN_PMCON_A_SMI_LOCK);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_A),
+ 1,
+ (VOID *) (UINTN) (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_A)
+ );
+ }
+}
+
+/**
+ Do PCIE power management while resume from S3
+**/
+VOID
+ReconfigurePciePowerManagementForS3 (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+ PCH_PCIE_IOTRAP_PROTOCOL *PchPcieIoTrapProtocol;
+
+ Status = gBS->LocateProtocol (&gPchPcieIoTrapProtocolGuid, NULL, (VOID **) &PchPcieIoTrapProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mPcieIoTrapAddress = PchPcieIoTrapProtocol->PcieTrapAddress;
+ DEBUG ((DEBUG_INFO, "PcieIoTrapAddress: %0x\n", mPcieIoTrapAddress));
+
+ if (mPcieIoTrapAddress != 0) {
+ //
+ // Save PCH PCIE IoTrap address to re-config PCIE power management setting after resume from S3
+ //
+ Data32 = PciePmTrap;
+ S3BootScriptSaveIoWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (mPcieIoTrapAddress),
+ 1,
+ &Data32
+ );
+ } else {
+ ASSERT (FALSE);
+ }
+}
+
+/**
+ This is the callback function for PCI ENUMERATION COMPLETE.
+**/
+VOID
+EFIAPI
+PchOnPciEnumComplete (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ UINTN ThermalPciBase;
+ UINT32 PchPwrmBase;
+
+ ///
+ /// 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);
+
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ //
+ // Allocate BAR for ISH - workaround for Si bug on stepping LpA0/A1/A2
+ //
+ AllocateIshMemorySpace ();
+
+ //
+ // Enable Thermal MSE
+ //
+ ThermalPciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_THERMAL,
+ PCI_FUNCTION_NUMBER_PCH_THERMAL
+ );
+ if (MmioRead16 (ThermalPciBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF) {
+ if (((MmioRead32 (ThermalPciBase + R_PCH_THERMAL_TBAR) & B_PCH_THERMAL_TBAR_MASK) != 0) ||
+ ((MmioRead32 (ThermalPciBase + R_PCH_THERMAL_TBARH) != 0))) {
+ MmioOr8 (ThermalPciBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+ }
+
+ ReconfigurePciePowerManagementForS3 ();
+ ProcessSmiLocks ();
+#ifndef FSP_WRAPPER_FLAG
+ PchOnPciEnumCompleteCommon ();
+#endif
+}
+
+/**
+ Register callback functions for PCH DXE.
+**/
+VOID
+PchRegisterNotifications (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT ReadyToBoot;
+ EFI_EVENT LegacyBootEvent;
+ EFI_EVENT ExitBootServicesEvent;
+ VOID *Registration;
+
+ ///
+ /// Create PCI Enumeration Completed callback for PCH
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ TPL_CALLBACK,
+ PchOnPciEnumComplete,
+ NULL,
+ &Registration
+ );
+
+ //
+ // Register a Ready to boot event to config PCIE power management setting after OPROM executed
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ PchOnReadyToBoot,
+ NULL,
+ &ReadyToBoot
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create events for PCH 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,
+ PchOnExitBootServices,
+ NULL,
+ &ExitBootServicesEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = EfiCreateEventLegacyBootEx (
+ TPL_CALLBACK,
+ PchOnBootToOs,
+ NULL,
+ &LegacyBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Updates PCIe configuration in PCH Info Protocol.
+
+ @param[in,out] PchInfo Pointer to PCH info protocol instance to be updated
+**/
+VOID
+UpdatePcieConfigInfo (
+ IN OUT PCH_INFO_PROTOCOL *PchInfo
+ )
+{
+ EFI_STATUS Status;
+ PCH_SERIES PchSeries;
+ UINT32 StrapFuseCfg1;
+ UINT32 StrapFuseCfg5;
+ UINT32 StrapFuseCfg9;
+ UINT32 StrapFuseCfg13;
+ UINT32 StrapFuseCfg17;
+ UINT32 StrapFuseCfg21;
+
+ PchSeries = GetPchSeries ();
+
+ Status = PchSbiRpPciRead32 (
+ 0,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg1
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PchSbiRpPciRead32 (
+ 4,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg5
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PchSbiRpPciRead32 (
+ 8,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg9
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ PchInfo->PcieControllerCfg1 = (UINT8) ((StrapFuseCfg1 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ PchInfo->PcieControllerCfg2 = (UINT8) ((StrapFuseCfg5 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ PchInfo->PcieControllerCfg3 = (UINT8) ((StrapFuseCfg9 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+
+ if (PchSeries == PchH) {
+ Status = PchSbiRpPciRead32 (
+ 12,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg13
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = PchSbiRpPciRead32 (
+ 16,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg17
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ PchInfo->PcieControllerCfg4 = (UINT8) ((StrapFuseCfg13 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ PchInfo->PcieControllerCfg5 = (UINT8) ((StrapFuseCfg17 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+
+ if (GetPchGeneration () == KblPch) {
+ Status = PchSbiRpPciRead32 (
+ 20,
+ R_PCH_PCIE_STRPFUSECFG,
+ &StrapFuseCfg21
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ PchInfo->PcieControllerCfg6 = (UINT8) ((StrapFuseCfg21 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ }
+
+ }
+}
+
+/**
+ Stores PCIE Gen3 software equalization settings in bootscript to accelerate S3 resume
+**/
+VOID
+SavePcieGen3Eq (
+ VOID
+ )
+{
+ UINT8 RpIndex;
+ UINTN RpBase;
+ UINT8 EqMethod;
+ UINT32 Data32;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ for (RpIndex = 0; RpIndex < GetPchMaxPciePortNum (); ++RpIndex) {
+ RpBase = PchPcieBase (RpIndex);
+ //
+ // Before trying to save it, make sure software gen3 equalization did actually happen
+ //
+ if (MmioRead32 (RpBase) == 0xFFFFFFFF) {
+ continue;
+ }
+ if (GetMaxLinkSpeed (RpBase) < 3) {
+ continue;
+ }
+ EqMethod = mPchConfigHob->PcieRp.RootPort[RpIndex].Gen3EqPh3Method;
+ if (EqMethod != PchPcieEqDefault && EqMethod != PchPcieEqSoftware) {
+ continue;
+ }
+ //
+ // Can't check current link speed due to some nonconformant devices
+ // Instead we verify B_PCH_PCIE_EQCFG1_RTLEPCEB bit which together with policy check above
+ // guarantees that software gen3 eq was performed
+ //
+ if (!(MmioRead32 (RpBase + R_PCH_PCIE_EQCFG1) & B_PCH_PCIE_EQCFG1_RTLEPCEB)) {
+ continue;
+ }
+
+ //
+ // Restore PCIE Gen3 equalization coefficients
+ //
+ Data32 = MmioRead32 (RpBase + R_PCH_PCIE_RTPCL1);
+ S3BootScriptSaveMemWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_RTPCL1, 1, &Data32);
+ Data32 = MmioRead32 (RpBase + R_PCH_PCIE_RTPCL2);
+ S3BootScriptSaveMemWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_RTPCL2, 1, &Data32);
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_PCIE_EQCFG1_RTLEPCEB | B_PCH_PCIE_EQCFG1_RTPCOE;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_EQCFG1, &Data32Or, &Data32And);
+
+ //
+ // Perform link retrain.
+ //
+ Data32And = (UINT32) (~B_PCIE_LCTL2_TLS);
+ Data32Or = V_PCIE_LCTL2_TLS_GEN3;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_LCTL2, &Data32Or, &Data32And);
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCIE_EX_LCTL3_PE;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_EX_LCTL3, &Data32Or, &Data32And);
+ Data32Or = B_PCIE_LCTL_RL;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_LCTL, &Data32Or, &Data32And);
+ /// PCH BIOS Spec Section 8.15 Additional PCI Express* Programming Steps
+ /// Set "Link Speed Training Policy", Dxx:Fn + D4h[6] to 1.
+ /// Make sure this is after mod-PHY related programming is completed.
+ Data32Or = B_PCH_PCIE_MPC2_LSTP;
+ DEBUG ((DEBUG_WARN, "Gen3Eq S3MmioOr32 0x%08x\n", RpBase + R_PCH_PCIE_MPC2));
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, RpBase + R_PCH_PCIE_MPC2, &Data32Or, &Data32And);
+ }
+}
+
+/**
+ Initialize the PCH device according to the PCH Policy HOB
+ and install PCH info instance.
+**/
+VOID
+InitializePchDevice (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ PCH_INFO_PROTOCOL *PchInfo;
+ EFI_STATUS Status;
+ UINT32 PchPwrmBase;
+
+ Handle = NULL;
+
+ DEBUG ((DEBUG_INFO, "InitializePchDevice() Start\n"));
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ //
+ // Create the PCH Info protocol instance
+ //
+ PchInfo = AllocateZeroPool (sizeof (PCH_INFO_PROTOCOL));
+ if (PchInfo == NULL) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ PchInfo->Revision = PCH_INFO_PROTOCOL_REVISION;
+
+ UpdatePcieConfigInfo (PchInfo);
+
+ //
+ // Store PCIE Gen3 software equalization settings in bootscripts to save time on S3 resume
+ // This must happen before some rootports get hidden by RST remapping
+ //
+ SavePcieGen3Eq ();
+
+
+ //
+ // Configure root port function number mapping
+ // For UEFI bios, execute RPFN mapping after RST configuraion and before PCI enumeration.
+ //
+ Status = PchConfigureRpfnMapping ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Pch Emmc Tuning Protocol
+ //
+ if ((mPchConfigHob->Scs.ScsEmmcEnabled == TRUE) && (mPchConfigHob->Scs.ScsEmmcHs400Enabled == TRUE)) {
+ InstallPchEmmcTuningProtocol ();
+ }
+
+ //
+ // Install PCH info protocol on new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gPchInfoProtocolGuid,
+ PchInfo,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "InitializePchDevice() End\n"));
+}
+/**
+ <b>PchInit DXE Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchInit module is a DXE driver that initializes the Intel Platform Controller Hub
+ following the PCH BIOS specification and EDS requirements and recommendations. It consumes
+ the PCH_POLICY_HOB SI_POLICY_HOB for expected configurations per policy.
+ This is the standard EFI driver point that detects whether there is an supported PCH in
+ the system and if so, initializes the chipset.
+
+ - <b>Details</b>\n
+ This module is required for initializing the Intel Platform Controller Hub to
+ follow the PCH BIOS specification and EDS.
+ This includes some initialization sequences, enabling and disabling PCH devices,
+ configuring clock gating, RST PCIe Storage Remapping, SATA controller, ASPM of PCIE devices. Right before end of DXE,
+ it's responsible to lock down registers for security requirement.
+
+ - @pre
+ - PCH PCR base address configured
+ - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+
+ - @result
+ - Publishes the @link _PCH_INFO_PROTOCOL PCH_INFO_PROTOCOL @endlink
+ - Publishes the @link _PCH_EMMC_TUNING_PROTOCOL PCH_EMMC_TUNING_PROTOCOL @endlink
+
+ - <b>References</b>\n
+ - @link _PCH_POLICY PCH_POLICY_HOB @endlink.
+ - @link _SI_POLICY_STRUCT SI_POLICY_HOB @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 The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchInitEntryPointDxe (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointDxe() Start\n"));
+
+ mImageHandle = ImageHandle;
+
+ PchInitEntryPointCommon ();
+
+ InitializePchDevice ();
+
+ Status = PchAcpiInit (ImageHandle);
+
+ CreateSerialIoHandles ();
+
+ PchRegisterNotifications ();
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointDxe() End\n"));
+
+ return Status;
+}
+
+/**
+ PCH initialization before ExitBootServices / LegacyBoot events
+ Useful for operations which must happen later than at EndOfPost event
+
+ @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
+PchOnBootToOs (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ ///
+ /// Closed the event to avoid call twice
+ ///
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ ConfigureSerialIoAtBoot ();
+
+ return;
+}
+
+/**
+ PCH initialization on ExitBootService. This event is used if only ExitBootService is used
+ and not in legacy boot
+
+ @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.
+
+ @retval None
+**/
+VOID
+EFIAPI
+PchOnExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ PchOnBootToOs (NULL, NULL);
+
+ PchUpdateNvsOnExitBootServices ();
+
+ return;
+}
+
+/**
+ PCH initialization before boot 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
+PchOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+#ifndef FSP_WRAPPER_FLAG
+ UINTN XhciMmioBase;
+ UINTN XhciPciMmBase;
+ UINT8 XhciPciCommand;
+ BOOLEAN XhciPdoRestartNeeded;
+#endif // FSP_WRAPPER_FLAG
+
+ DEBUG ((DEBUG_INFO, "Uefi PchOnReadyToBoot() Start\n"));
+
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+#ifndef FSP_WRAPPER_FLAG
+ if (mPchConfigHob->Usb.DelayPdoProgramming == TRUE) {
+ XhciPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PCI_FUNCTION_NUMBER_PCH_XHCI
+ );
+
+ // Check if xHCI has memory access
+ XhciPciCommand = MmioRead8 (XhciPciMmBase + PCI_COMMAND_OFFSET);
+
+ if ((XhciPciCommand & EFI_PCI_COMMAND_MEMORY_SPACE) == 0x0) {
+ DEBUG ((DEBUG_ERROR, "xHCI Controller isn't configured properly for PDO setting\n"));
+ } else {
+ // Getting base MMIO address for xHCI
+ XhciMmioBase = (
+ MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) |
+ ((UINTN) MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE_2) << N_PCH_XHCI_MEM_SHIFT)
+ ) & ((UINTN)~(B_PCH_XHCI_MEM_ALIGN_MASK));
+
+ XhciPdoRestartNeeded = UsbPdoProgramming (
+ XhciMmioBase,
+ mPchConfigHob->Usb.Usb2DisabledPorts,
+ mPchConfigHob->Usb.Usb3DisabledPorts
+ );
+ // If PDO registers are locked, reset platform to unlock them
+ if (XhciPdoRestartNeeded) {
+ gST->RuntimeServices->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "PDO register already programmed\n"));
+ }
+#endif // FSP_WRAPPER_FLAG
+
+ //
+ // Trigger an Iotrap SMI to config PCIE power management setting after PCI enumrate is done
+ //
+ if (mPcieIoTrapAddress != 0) {
+ IoWrite32 ((UINTN) mPcieIoTrapAddress, PciePmTrap);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ DEBUG ((DEBUG_INFO, "Uefi PchOnReadyToBoot() End\n"));
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.inf
new file mode 100644
index 0000000000..0242dcbe9a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.inf
@@ -0,0 +1,101 @@
+## @file
+# Component description file for Pch Initialization driver
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PchInitDxe
+FILE_GUID = DE23ACEE-CF55-4fb6-AA77-984AB53DE823
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+ENTRY_POINT = PchInitEntryPointDxe
+
+
+[LibraryClasses]
+S3BootScriptLib
+PchCycleDecodingLib
+PchPcieRpLib
+PchP2sbLib
+PchPcrLib
+PchInfoLib
+PchPciExpressHelpersLib
+UefiBootServicesTableLib
+DebugLib
+IoLib
+TimerLib
+HobLib
+BaseMemoryLib
+MemoryAllocationLib
+UefiLib
+DxeServicesTableLib
+UefiDriverEntryPoint
+UefiRuntimeServicesTableLib
+AslUpdateLib
+CpuPlatformLib
+GpioLib
+PchSerialIoLib
+PchHdaLib
+PchInitCommonLib
+ConfigBlockLib
+PchPsfLib
+PchPsfPrivateLib
+RstPrivateLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[Sources]
+PchInitDxe.c
+PchInit.h
+PchInit.c
+PchSata.c
+PchRstPcieStorage.c
+PchSerialIo.c
+PchSerialIoDxe.c
+PchHdaAcpi.c
+PchScs.c
+PchCio2Acpi.c
+PchAcpi.c
+
+
+[Protocols]
+gPchInfoProtocolGuid ## PRODUCES
+gPchNvsAreaProtocolGuid ## PRODUCES
+gPchEmmcTuningProtocolGuid ## PRODUCES
+gEfiPciIoProtocolGuid ## CONSUMES
+gEfiAcpiTableProtocolGuid ## CONSUMES
+gEfiBlockIoProtocolGuid ## CONSUMES
+gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
+gPchPcieIoTrapProtocolGuid ## CONSUMES
+
+
+[Guids]
+gEfiEndOfDxeEventGroupGuid
+gEfiAcpiTableGuid
+gSiConfigHobGuid ## CONSUMES
+gPchConfigHobGuid ## CONSUMES
+gPchPcieStorageDetectHobGuid ## CONSUMES
+
+
+[Depex]
+gEfiPciHostBridgeResourceAllocationProtocolGuid ## This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFsp.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFsp.inf
new file mode 100644
index 0000000000..18feffd894
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFsp.inf
@@ -0,0 +1,80 @@
+## @file
+# Component description file for Pch Initialization driver for FSP package
+#
+# Copyright (c) 2017, 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 = PchInitDxe
+FILE_GUID = 5AA5031E-4CB6-43D4-B219-FE50FF5D116C
+MODULE_TYPE = PEIM
+VERSION_STRING = 1.0
+ENTRY_POINT = PchInitEntryPointFsp
+
+
+[LibraryClasses]
+PeimEntryPoint
+PchCycleDecodingLib
+PchPcieRpLib
+PchP2sbLib
+PchPcrLib
+PchInfoLib
+PchEspiLib
+PchPciExpressHelpersLib
+DebugLib
+IoLib
+TimerLib
+HobLib
+BaseMemoryLib
+MemoryAllocationLib
+CpuPlatformLib
+GpioLib
+PchSerialIoLib
+PchInitCommonLib
+S3BootScriptLib # NULL library
+ConfigBlockLib
+PchPsfLib
+PchPsfPrivateLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[Sources]
+PchInitFsp.c
+PchInit.h
+PchInit.c
+PchSata.c
+PchSerialIo.c
+
+
+[Protocols]
+gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
+
+
+[Guids]
+gEfiEventReadyToBootGuid
+gSiConfigHobGuid ## CONSUMES
+gPchConfigHobGuid ## CONSUMES
+
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c
new file mode 100644
index 0000000000..9307b8fc4c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c
@@ -0,0 +1,169 @@
+/** @file
+ This is the FSP driver that initializes the Intel PCH.
+
+Copyright (c) 2017, 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 that 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 "PchInit.h"
+
+EFI_STATUS
+EFIAPI
+PchOnPciEnumCompleteFsp (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+STATIC
+EFI_PEI_NOTIFY_DESCRIPTOR mPchOnPciEnumCompleteNotifyList[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ PchOnPciEnumCompleteFsp
+ }
+};
+
+EFI_STATUS
+EFIAPI
+PchReadyToBootEventFsp (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+STATIC EFI_PEI_NOTIFY_DESCRIPTOR mReadyToBootNotifyList[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEventReadyToBootGuid,
+ PchReadyToBootEventFsp
+ }
+};
+
+
+/**
+ <b>FSP PchInit Module Entry Point for FSP</b>\n
+
+ @param[in] FileHandle PEIM's file handle
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchInitEntryPointFsp (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointFsp() Start\n"));
+
+ PchInitEntryPointCommon ();
+
+ Status = PeiServicesNotifyPpi (mPchOnPciEnumCompleteNotifyList);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesNotifyPpi (mReadyToBootNotifyList);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointFsp() End\n"));
+
+ return Status;
+}
+
+/**
+ Fsp PCH initialization on PCI enumeration complete
+
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchOnPciEnumCompleteFsp (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteFsp() Start\n"));
+
+ PchOnPciEnumCompleteCommon ();
+
+ DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteFsp() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ FSP PCH Ready to boot event handler
+
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchReadyToBootEventFsp (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ UINTN XhciMmioBase;
+ UINTN XhciPciMmBase;
+ UINT16 XhciPciCommand;
+ BOOLEAN XhciPdoRestartNeeded;
+
+ DEBUG ((DEBUG_INFO, "PchReadyToBootEventFsp() Start\n"));
+
+ // Check if USB PDO programming was skipped during PEI phase
+ if (mPchConfigHob->Usb.DelayPdoProgramming == TRUE) {
+ XhciPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PCI_FUNCTION_NUMBER_PCH_XHCI
+ );
+
+ // Check if xHCI has memory access
+ XhciPciCommand = MmioRead16 (XhciPciMmBase + PCI_COMMAND_OFFSET);
+ if ((XhciPciCommand & EFI_PCI_COMMAND_MEMORY_SPACE) == 0x0) {
+ DEBUG ((DEBUG_ERROR, "xHCI Controller isn't configured properly\n"));
+ } else {
+ // Getting base MMIO address for xHCI
+ XhciMmioBase = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) & (B_PCH_XHCI_MEM_ALIGN_MASK << N_PCH_XHCI_MEM_ALIGN);
+
+ XhciPdoRestartNeeded = UsbPdoProgramming (
+ XhciMmioBase,
+ mPchConfigHob->Usb.Usb2DisabledPorts,
+ mPchConfigHob->Usb.Usb3DisabledPorts
+ );
+ // If PDO registers are locked, reset platform to unlock them
+ if (XhciPdoRestartNeeded) {
+ (*PeiServices)->ResetSystem2 (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "PDO register already programmed\n"));
+ }
+
+ DEBUG ((DEBUG_INFO, "PchReadyToBootEventFsp() End\n"));
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchRstPcieStorage.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchRstPcieStorage.c
new file mode 100644
index 0000000000..801abf2602
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchRstPcieStorage.c
@@ -0,0 +1,286 @@
+/** @file
+ Configures the remapping for PCH Intel RST PCie Storage
+ In order to use this feature, Intel RST Driver is required
+
+Copyright (c) 2017, 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 that 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 "PchInit.h"
+#include <Library/RstPrivateLib.h>
+#include <PchPcieStorageDetectHob.h>
+
+//
+// Variables below indicate the memory range to be allocated to the PCIe storage device BAR usage when it is HIDDEN,
+// thus it does not overlapped with the SGREG_BAR from the host perspective
+//
+#define RST_PCIE_STORAGE_MEMORY_START_RANGE PCH_PCR_BASE_ADDRESS
+#define RST_PCIE_STORAGE_MEMORY_END_RANGE (PCH_PCR_BASE_ADDRESS + PCH_PCR_MMIO_SIZE - 1)
+
+#define PCI_CARD_PM_CAP_ID 0x01
+#define PCI_CARD_MSIX_CAP_ID 0x11
+#define PCI_CARD_SATA_CAP_ID 0x12
+#define PCI_CARD_BAR_TOTAL 6
+#define PCI_CARD_LINK_SPEED_GEN1_GEN2 0
+#define PCI_CARD_LINK_SPEED_GEN3 1
+#define PCI_CARD_LINK_WIDTH_1 0
+#define PCI_CARD_LINK_WIDTH_2 1
+#define PCI_CARD_LINK_WIDTH_4 2
+#define PCI_CARD_REVISION 0x08
+#define PCI_CARD_BASE_ADDR0 0x10
+#define PCI_CARD_BASE_ADDR1 0x14
+#define PCI_CARD_BASE_ADDR5 0x24
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_RST_PCIE_STORAGE_DETECTION mRstPcieStorageDetection [PCH_MAX_RST_PCIE_STORAGE_CR];
+
+UINT32 PchRstPcieStorageCurrentMemoryRange = RST_PCIE_STORAGE_MEMORY_START_RANGE;
+
+
+/**
+ Function to perform dump for PCH_RST_PCIE_STORAGE_DETECTION
+
+ @param[in] Index Index for RST PCIe Storage Cycle Router Instance
+
+ @retval None
+**/
+VOID
+PchRstPcieStorageRemappingDump (
+ IN UINTN Index
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ DEBUG ((DEBUG_INFO, "PchRstPcieStorageRemappingDump() Started\n"));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].SupportRstPcieStoragRemapping = %x\n", Index, mRstPcieStorageDetection[Index].SupportRstPcieStoragRemapping));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].RootPortNum = %x\n", Index, mRstPcieStorageDetection[Index].RootPortNum));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].RootPortLane = %x\n", Index, mRstPcieStorageDetection[Index].RootPortLane));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].DeviceInterface = %x\n", Index, mRstPcieStorageDetection[Index].DeviceInterface));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].IsMsixSupported = %x\n", Index, mRstPcieStorageDetection[Index].IsMsixSupported));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].MsixStartingVector = %x\n", Index, mRstPcieStorageDetection[Index].MsixStartingVector));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].MsixEndingVector = %x\n", Index, mRstPcieStorageDetection[Index].MsixEndingVector));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointBarSize = %x\n", Index, mRstPcieStorageDetection[Index].EndPointBarSize));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixTableBar = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixTableBar));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixTableBarValue = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixTableBarValue));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixPbaBar = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixPbaBar));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixPbaBarValue = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixPbaBarValue));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointBcc = %x\n", Index, mRstPcieStorageDetection[Index].EndPointBcc));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointScc = %x\n", Index, mRstPcieStorageDetection[Index].EndPointScc));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointPi = %x\n", Index, mRstPcieStorageDetection[Index].EndPointPi));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.PmCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.PmCapPtr));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.PcieCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.PcieCapPtr));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.L1ssCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.L1ssCapPtr));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointL1ssControl2 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointL1ssControl2));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointL1ssControl1 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointL1ssControl1));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.LtrCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.LtrCapPtr));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointLtrData = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointLtrData));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointLctlData16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointLctlData16));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointDctlData16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointDctlData16));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointDctl2Data16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointDctl2Data16));
+ DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.RootPortDctl2Data16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.RootPortDctl2Data16));
+ DEBUG ((DEBUG_INFO, "PchRstPcieStorageRemappingDump() Ended\n"));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Perform memory space allocation or free memory pool for AHCI BAR
+
+ @param[in] Operation True: Perform memory space allocation for AHCI BAR
+ False: Perform memory pool free for AHCI BAR
+ @param[in,out] MemBaseAddress The base memory address used by AHCI BAR
+**/
+VOID
+AbarMemorySpaceOperation (
+ IN BOOLEAN Operation,
+ IN OUT EFI_PHYSICAL_ADDRESS *MemBaseAddress
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINTN AhciBarAlignment;
+ UINTN AhciBarLength;
+
+ //
+ // Assign a 512k size memory space to the ABAR when NVM Remapping is enabled
+ //
+ AhciBarAlignment = N_PCH_SATA_AHCI_BAR_ALIGNMENT_512K; // 2^19: 512K Alignment
+ AhciBarLength = V_PCH_SATA_AHCI_BAR_LENGTH_512K; // 512K Length
+
+
+ if (Operation == TRUE) {
+ ///
+ /// If MemBaseAddress is not allocated yet, allocate the AHCI BAR
+ ///
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ BaseAddress = 0x0ffffffff;
+ }
+ Status = gDS->AllocateMemorySpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdMemoryTypeMemoryMappedIo,
+ AhciBarAlignment,
+ AhciBarLength,
+ &BaseAddress,
+ mImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ *MemBaseAddress = BaseAddress;
+ } else {
+ ///
+ /// Else, free the GCD pool
+ ///
+ gDS->FreeMemorySpace (
+ *MemBaseAddress,
+ AhciBarLength
+ );
+ }
+}
+
+/**
+ Function to perform memory allocation for PCIe storage device that support unique BAR
+
+ @param[in] BarSize The BAR size required for memory allocation
+ @param[in,out] AllocAddr The Address that been allocated by this function
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Memory or storage is not enough
+**/
+EFI_STATUS
+PchRstPcieStorageMemAllocation (
+ IN UINT32 BarSize,
+ IN OUT UINT32 *AllocAddr
+ )
+{
+ if ((PchRstPcieStorageCurrentMemoryRange + BarSize) > RST_PCIE_STORAGE_MEMORY_END_RANGE) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if ((PchRstPcieStorageCurrentMemoryRange & (BarSize - 1)) != 0) {
+ *AllocAddr = (PchRstPcieStorageCurrentMemoryRange + BarSize) & ~(BarSize-1);
+ } else {
+ *AllocAddr = PchRstPcieStorageCurrentMemoryRange;
+ }
+
+ PchRstPcieStorageCurrentMemoryRange = *AllocAddr + BarSize;
+ return EFI_SUCCESS;
+}
+
+/**
+ Check and detect PCIe storage device per policies, and if existed, indicate if it should be subjected for remapping
+ Populate the mRstPcieStorageDetection structure along with it for later usages
+
+ @param[in, out] RemappingRequired Boolean value with TRUE indicates that RST PCIe Storage Remapping is required
+ @param[in] TempPciBusMin The temporary minimum Bus number for root port initialization
+ @param[in] SataRegBase SATA Register Base
+
+ @retval None
+**/
+VOID
+DetectPcieStorageDevices (
+ IN OUT BOOLEAN *RemappingRequired,
+ IN UINT8 TempPciBusMin,
+ IN UINTN SataRegBase
+ )
+{
+ EFI_STATUS Status;
+ PCH_SERIES PchSeries;
+ UINT8 DeviceInterface;
+ UINT32 PortNum;
+ UINTN PciRootPortRegBase;
+ UINTN RpDev;
+ UINTN RpFunc;
+ UINT8 RootPortLane;
+ PCIE_STORAGE_INFO_HOB *PcieStorageInfoHob;
+ VOID *Hob;
+ UINT32 CycleRouterNum;
+
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: DetectPcieStorageDevices Started\n"));
+
+ Hob = NULL;
+ Hob = GetFirstGuidHob (&gPchPcieStorageDetectHobGuid);
+ if (Hob != NULL) {
+ PcieStorageInfoHob = (PCIE_STORAGE_INFO_HOB *) GET_GUID_HOB_DATA (Hob);
+ } else {
+ return;
+ }
+
+ PchSeries = GetPchSeries ();
+
+ for (PortNum = 0; PortNum < GetPchMaxPciePortNum (); PortNum++) {
+
+ //
+ // Check Info hob for Cycle Router avaliable
+ // skip to next root port if Cr is not avaliable
+ //
+ CycleRouterNum = PcieStorageInfoHob->RstCycleRouterMap[PortNum / 4];
+ if (CycleRouterNum == RST_PCIE_STORAGE_CR_INVALID) {
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: cycle router not avaliable on Rp = %d\n", PortNum));
+ continue;
+ }
+
+ Status = GetPchPcieRpDevFun (PortNum, &RpDev, &RpFunc);
+ ASSERT_EFI_ERROR (Status);
+
+ PciRootPortRegBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDev, (UINT32) RpFunc);
+ RootPortLane = RstGetRpLaneOccupyMask (PortNum);
+
+
+ if (RootPortLane == 0) {
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: root port lane is not occupied\n"));
+ continue;
+ }
+
+ ///
+ /// Check if the RST PCIe Storage Cycle Router is enabled, continue to the next root port in the next x4 lane if it is disabled
+ ///
+ if (mPchConfigHob->Sata.RstPcieStorageRemap[CycleRouterNum].Enable == 0) {
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: RST PCIe Storage Cycle Router %d is disabled\n", CycleRouterNum));
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: Proceed to root port in the next x4 lane (@ port %d)\n", PortNum + 1));
+ PortNum += 3 - (PortNum % 4);
+ continue;
+ }
+
+ ///
+ /// Check if the current root port is matching selected root port from policy, continue to next port if they are not matched
+ ///
+ if ((mPchConfigHob->Sata.RstPcieStorageRemap[CycleRouterNum].RstPcieStoragePort != 0) &&
+ (mPchConfigHob->Sata.RstPcieStorageRemap[CycleRouterNum].RstPcieStoragePort != PortNum + 1)) {
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: root port %d not matched with selected root port, proceed to next port\n", PortNum + 1));
+ continue;
+ }
+
+
+ // Read device programming interface from info hob
+ // if no device is present continue
+ if (PcieStorageInfoHob->PcieStorageLinkWidth[PortNum]) {
+ DeviceInterface = PcieStorageInfoHob->PcieStorageProgrammingInterface[PortNum];
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: Device present on RP# %d, PiInterface = %d\n", PortNum + 1, DeviceInterface));
+ } else {
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: RP# %d no device present\n", PortNum + 1));
+ continue;
+ }
+
+
+ ///
+ /// Update the remapping detail for detected PCIe storage device, and move to the root port in the next x4 lane
+ ///
+ if ((DeviceInterface != RST_PCIE_STORAGE_INTERFACE_NONE)) {
+ mRstPcieStorageDetection[CycleRouterNum].SupportRstPcieStoragRemapping = TRUE;
+ mRstPcieStorageDetection[CycleRouterNum].RootPortNum = (UINT8) PortNum;
+ mRstPcieStorageDetection[CycleRouterNum].RootPortLane = RootPortLane;
+ mRstPcieStorageDetection[CycleRouterNum].DeviceInterface = DeviceInterface;
+ PortNum += 3 - (PortNum % 4);
+ *RemappingRequired = TRUE;
+ } else {
+ continue;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: DetectPcieStorageDevices() Ended\n"));
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c
new file mode 100644
index 0000000000..d1f2948de6
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c
@@ -0,0 +1,125 @@
+/** @file
+ Perform related functions for PCH Sata in DXE phase
+
+Copyright (c) 2017, 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 that 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 <PchInit.h>
+
+/**
+ Perform the remaining configuration on PCH SATA to perform device detection,
+ then set the SATA SPD and PxE corresponding, and set the Register Lock on PCH SATA
+
+ @retval None
+**/
+VOID
+ConfigurePchSataOnEndOfDxe (
+ VOID
+ )
+{
+ UINTN PciSataRegBase;
+ UINT16 SataPortsEnabled;
+ PCH_SERIES PchSeries;
+ UINT16 WordReg;
+ UINT32 DwordReg;
+ UINTN Index;
+
+ ///
+ /// SATA PCS: Enable the port in any of below condition:
+ /// i.) Hot plug is enabled
+ /// ii.) A device is attached
+ /// iii.) Test mode is enabled
+ /// iv.) Configured as eSATA port
+ ///
+ PciSataRegBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA);
+ PchSeries = GetPchSeries ();
+ SataPortsEnabled = 0;
+
+ if (MmioRead16 (PciSataRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return;
+ }
+ if (PchSeries == PchLp) {
+ WordReg = MmioRead16 (PciSataRegBase + R_PCH_LP_SATA_PCS);
+ for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) {
+ if ((mPchConfigHob->Sata.PortSettings[Index].HotPlug == TRUE) ||
+ (WordReg & (B_PCH_LP_SATA_PCS_P0P << Index)) ||
+ (mPchConfigHob->Sata.TestMode == TRUE) ||
+ (mPchConfigHob->Sata.PortSettings[Index].External == TRUE)) {
+ SataPortsEnabled |= (mPchConfigHob->Sata.PortSettings[Index].Enable << Index);
+ }
+ }
+
+ ///
+ /// Set MAP."Sata PortX Disable", SATA PCI offset 90h[10:8] to 1b if SATA Port 0/1/2 is disabled
+ ///
+ MmioOr16 (PciSataRegBase + R_PCH_LP_SATA_MAP, ((~SataPortsEnabled << N_PCH_LP_SATA_MAP_SPD) & (UINT16) B_PCH_LP_SATA_MAP_SPD));
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint16,
+ (UINTN) (PciSataRegBase + R_PCH_LP_SATA_MAP),
+ 1,
+ (VOID *) (UINTN) (PciSataRegBase + R_PCH_LP_SATA_MAP)
+ );
+
+ ///
+ /// Program PCS "Port X Enabled", SATA PCI offset 92h[2:0] = Port 0~2 Enabled bit as per SataPortsEnabled value.
+ ///
+ MmioOr16 (PciSataRegBase + R_PCH_LP_SATA_PCS, SataPortsEnabled);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint16,
+ (UINTN) (PciSataRegBase + R_PCH_LP_SATA_PCS),
+ 1,
+ (VOID *) (UINTN) (PciSataRegBase + R_PCH_LP_SATA_PCS)
+ );
+ } else {
+ DwordReg = MmioRead32 (PciSataRegBase + R_PCH_H_SATA_PCS);
+ for (Index = 0; Index < GetPchMaxSataPortNum (); Index++) {
+ if ((mPchConfigHob->Sata.PortSettings[Index].HotPlug == TRUE) ||
+ (DwordReg & (B_PCH_H_SATA_PCS_P0P << Index)) ||
+ (mPchConfigHob->Sata.TestMode == TRUE) ||
+ (mPchConfigHob->Sata.PortSettings[Index].External == TRUE)) {
+ SataPortsEnabled |= (mPchConfigHob->Sata.PortSettings[Index].Enable << Index);
+ }
+ }
+
+ ///
+ /// Set MAP."Sata PortX Disable", SATA PCI offset 90h[23:16] to 1b if SATA Port 0/1/2/3/4/5/6/7 is disabled
+ ///
+ MmioOr32 (PciSataRegBase + R_PCH_H_SATA_MAP, ((~SataPortsEnabled << N_PCH_H_SATA_MAP_SPD) & (UINT32) B_PCH_H_SATA_MAP_SPD));
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PciSataRegBase + R_PCH_H_SATA_MAP),
+ 1,
+ (VOID *) (UINTN) (PciSataRegBase + R_PCH_H_SATA_MAP)
+ );
+
+ ///
+ /// Program PCS "Port X Enabled", SATA PCI offset 94h[7:0] = Port 0~7 Enabled bit as per SataPortsEnabled value.
+ ///
+ MmioOr16 (PciSataRegBase + R_PCH_H_SATA_PCS, SataPortsEnabled);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint16,
+ (UINTN) (PciSataRegBase + R_PCH_H_SATA_PCS),
+ 1,
+ (VOID *) (UINTN) (PciSataRegBase + R_PCH_H_SATA_PCS)
+ );
+ }
+
+ ///
+ /// Step 14
+ /// Program SATA PCI offset 9Ch [31] to 1b
+ ///
+ MmioOr32 ((UINTN) (PciSataRegBase + R_PCH_SATA_SATAGC), BIT31);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PciSataRegBase + R_PCH_SATA_SATAGC),
+ 1,
+ (VOID *) (UINTN) (PciSataRegBase + R_PCH_SATA_SATAGC)
+ );
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchScs.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchScs.c
new file mode 100644
index 0000000000..34227826b4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchScs.c
@@ -0,0 +1,1869 @@
+/** @file
+ Initializes PCH Storage and Communications Subsystem Controllers.
+
+Copyright (c) 2017, 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 that 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 <PchInit.h>
+
+//
+// HS400 Tuning Definitions
+//
+#define RX_STROBE_DLL1_TAP_MAX_RANGE 39
+#define RX_STROBE_DLL1_TAP_MIN_RANGE 0
+#define RX_STROBE_DLL1_TAP_MIN_MEPT 5
+#define RX_STROBE_DLL1_TAP_MAX_MEPT 16
+#define TX_DATA_DLL_TAP_MAX_RANGE 79
+#define TX_DATA_DLL_TAP_MIN_RANGE 0
+#define TX_DATA_DLL_TAP_MIN_MEPT 4
+#define TX_DATA_DLL_TAP_MAX_MEPT 22
+
+//
+// Command Definitions
+//
+#define CMD6 6
+#define CMD8 8
+#define CMD13 13
+#define CMD31 31
+#define SWITCH CMD6
+#define SEND_EXT_CSD CMD8
+#define SEND_STATUS CMD13
+#define SEND_WRITE_PROT_TYPE CMD31
+#define WRITE_BYTE_MODE 3
+#define BLOCK_LENGTH 512
+#define TIMEOUT_COMMAND 100
+#define TIMEOUT_DATA 5000
+#define HS_TIMING_INDEX 185
+#define BUS_WIDTH_INDEX 183
+
+//
+// Card Status Definitions
+//
+#define SWITCH_ERROR BIT7
+#define ERASE_RESET BIT13
+#define WP_ERASE_SKIP BIT15
+#define CID_CSD_OVERWRITE BIT16
+#define ERROR BIT19
+#define CC_ERROR BIT20
+#define CARD_ECC_FAILED BIT21
+#define ILLEGAL_COMMAND BIT22
+#define COM_CRC_ERROR BIT23
+#define LOCK_UNLOCK_FAILED BIT24
+#define CARD_IS_LOCKED BIT25
+#define WP_VIOLATION BIT26
+#define ERASE_PARAM BIT27
+#define ERASE_SEQ_ERROR BIT28
+#define BLOCK_LEN_ERROR BIT29
+#define ADDRESS_MISALIGN BIT30
+#define ADDRESS_OUT_OF_RANGE BIT31
+
+typedef enum {
+ Hs200 = 0,
+ Hs400,
+ DDR50,
+ SDR25
+} EMMC_MODE;
+
+typedef enum {
+ RxDll1 = 0,
+ RxDll2
+} RX_STROBE_DLL_REG;
+
+typedef enum {
+ NotAvailable = 0,
+ Passed,
+ Failed
+} BLOCK_READ_WRITE_STATUS;
+
+typedef enum {
+ ResponseNo = 0,
+ ResponseR1,
+ ResponseR1b,
+ ResponseR2,
+ ResponseR3,
+ ResponseR4,
+ ResponseR5,
+ ResponseR5b,
+ ResponseR6,
+ ResponseR7
+} RESPONSE_TYPE;
+
+typedef enum {
+ NoData = 0,
+ InData,
+ OutData
+} TRANSFER_TYPE;
+
+typedef struct {
+ UINT32 CmdSet: 3;
+ UINT32 Reserved0: 5;
+ UINT32 Value: 8;
+ UINT32 Index: 8;
+ UINT32 Access: 2;
+ UINT32 Reserved1: 6;
+} SWITCH_ARGUMENT;
+
+//
+// PCH_EMMC_TUNING PROTOCOL Global Variable
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_EMMC_TUNING_PROTOCOL PchEmmcTuningProtocol = {
+ ConfigureEmmcHs400Mode
+};
+
+#define EMMC_HS400_TUNING_PATTERN_BLOCKS_NUMBER 5
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 EmmcWorstCasePattern[] =
+{
+0x60FEFE00, 0xEDFF10FE, 0x60FEFE00, 0xEDFF10FE, 0xDE08216A, 0xE25F20DF, 0xDE08216A, 0xE25F20DF, // spt_a0_sandisk_50ohm
+0xFF00CFFF, 0x1014B5CF, 0xFF00CFFF, 0x1014B5CF, 0x225F25DF, 0x20DFDE61, 0x225F25DF, 0x20DFDE61, // spt_a0_sandisk_40ohm
+0xEFE770BD, 0x4AFF0000, 0xEFE770BD, 0x4AFF0000, 0x7B84FF5B, 0x5B655B0E, 0x7B84FF5B, 0x5B655B0E, // spt_a0_hynix_50ohm
+0x7B93D620, 0xDFFF00E8, 0x7B93D620, 0xDFFF00E8, 0x3DC2FF3D, 0x38EA7DF3, 0x3DC2FF3D, 0x38EA7DF3, // spt_a0_hynix_40ohm
+0x50127FAC, 0x4400FD00, 0x50127FAC, 0x4400FD00, 0x7887FF78, 0x109A394F, 0x7887FF78, 0x109A394F, // spt_a0_hynix_33ohm
+0x50F20DBF, 0x3832CDFD, 0x50F20DBF, 0x3832CDFD, 0xFB04D720, 0xE69DC704, 0xFB04D720, 0xE69DC704, // spt_a0_samsung19nm_33ohm
+0x40EFFF00, 0x40FFFF00, 0x40EFFF00, 0x40FFFF00, 0xE85F20DF, 0x20DF003F, 0xE85F20DF, 0x20DF003F, // spt_a0_toshiba_50ohm
+0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0x20DFA0FF, 0x58DB20DF, 0x20DFA0FF, 0x58DB20DF, // spt_a0_toshiba_40ohm
+0x50FF0008, 0x7E10FFFF, 0x50FF0008, 0x7E10FFFF, 0x3B8F7A85, 0xFF7A5AFF, 0x3B8F7A85, 0xFF7A5AFF, // spt_b0_hynix_40ohm
+0x8A7575FF, 0x9ACA7F54, 0x8A7575FF, 0x9ACA7F54, 0xDF649B92, 0x7B24AFA0, 0xDF649B92, 0x7B24AFA0, // spt_b0_samsung16nm_50ohm
+0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xDAD6EF50, 0x6B1C6B25, 0xDAD6EF50, 0x6B1C6B25, // spt_b0_samsung16nm_40ohm
+0x7f52ff02, 0xff02ff02, 0x7f52ff02, 0xff02ff02, 0x72bc63a5, 0x679afa9d, 0x72bc63a5, 0x679afa9d, // spt_b0_samsung16nm_33ohm
+
+0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, // baseline_pattern_8
+0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
+0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
+0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 EmmcWorstCasePatternSize = sizeof (EmmcWorstCasePattern);
+
+
+
+/**
+ Set max clock frequency of the host, the actual frequency may not be the same
+ as MaxFrequency. It depends on the max frequency the host can support, divider,
+ and host speed mode.
+
+ @param[in] This Pointer to EFI_SD_HOST_IO_PROTOCOL
+ @param[in] MaxFrequency Max frequency in HZ
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_TIMEOUT The timeout time expired.
+**/
+EFI_STATUS
+EFIAPI
+SetClockFrequency (
+ IN UINTN EmmcBaseAddress,
+ IN UINT32 MaxFrequency
+ )
+{
+ UINT16 Data16;
+ UINT32 Frequency;
+ UINT32 Divider = 0;
+ UINT32 TimeOutCount;
+ UINT32 CurrentClockInKHz;
+
+ DEBUG ((DEBUG_INFO, "SetClockFrequency: BaseClockInMHz = %d \n", 200));
+
+ Frequency = (200 * 1000 * 1000) / MaxFrequency;
+ DEBUG ((DEBUG_INFO, "SetClockFrequency: FrequencyInHz = %d \n", Frequency));
+
+ if ((200 * 1000 * 1000 % MaxFrequency) != 0) {
+ Frequency += 1;
+ }
+
+ Divider = 1;
+ while (Frequency > Divider) {
+ Divider = Divider * 2;
+ }
+ if (Divider >= 0x400) {
+ Divider = 0x200;
+ }
+ Divider = Divider >> 1;
+
+ DEBUG ((DEBUG_INFO, "SetClockFrequency: after shift: Base Clock Divider = 0x%x \n", Divider));
+
+ CurrentClockInKHz = (200 * 1000);
+ if (Divider != 0) {
+ CurrentClockInKHz = CurrentClockInKHz / (Divider * 2);
+ }
+ //
+ //Set frequency
+ // Bit[15:8] SDCLK Frequency Select at offset 2Ch
+ // 80h - base clock divided by 256
+ // 40h - base clock divided by 128
+ // 20h - base clock divided by 64
+ // 10h - base clock divided by 32
+ // 08h - base clock divided by 16
+ // 04h - base clock divided by 8
+ // 02h - base clock divided by 4
+ // 01h - base clock divided by 2
+ // 00h - Highest Frequency the target support (10MHz-63MHz)
+ //
+ // Bit [07:06] are assigned to bit 09-08 of clock divider in SDCLK Frequency Select on SD controller 3.0
+ //
+
+ Data16 = (UINT16) ((Divider & 0xFF) << 8 | (((Divider & 0xFF00) >> 8) << 6));
+
+ DEBUG ((DEBUG_INFO,
+ "SetClockFrequency: base=%dMHz, clkctl=0x%04x, f=%dKHz\n",
+ 200,
+ Data16,
+ CurrentClockInKHz
+ ));
+ DEBUG ((DEBUG_INFO, "SetClockFrequency: set MMIO_CLKCTL value = 0x%x \n", Data16));
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL, Data16);
+ Data16 |= BIT0;
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL, Data16);
+ TimeOutCount = 1000;
+ do {
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL);
+ MicroSecondDelay (100);
+ TimeOutCount--;
+ if (TimeOutCount == 0) {
+ DEBUG ((DEBUG_INFO, "SetClockFrequency: Timeout\n"));
+ return EFI_TIMEOUT;
+ }
+ } while ((Data16 & BIT1) != BIT1);
+
+ Data16 |= BIT2;
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL, Data16);
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Error Reason from Host
+
+ @param[in] CommandIndex Command Index which return error
+ @param[in] ErrorCode Command Error Code
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_TIMEOUT Command Timeout Error
+ @retval EFI_TIMEOUT Data Timeout Error
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+ @retval EFI_DEVICE_ERROR Command End Bit Error
+ Command Index Error
+ Data End Bit Error
+ Current Limit Error
+ Auto CMD12 Error
+ ADMA Error
+**/
+STATIC
+EFI_STATUS
+EmmcGetErrorReason (
+ IN UINT16 CommandIndex,
+ IN UINT16 ErrorCode
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_ERROR, "[%2d] -- ", CommandIndex));
+
+ if (ErrorCode & BIT0) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((DEBUG_ERROR, "Command Timeout Error\n"));
+ }
+
+ if (ErrorCode & BIT1) {
+ Status = EFI_CRC_ERROR;
+ DEBUG ((DEBUG_ERROR, "Command CRC Error\n"));
+ }
+
+ if (ErrorCode & BIT2) {
+ DEBUG ((DEBUG_ERROR, "Command End Bit Error\n"));
+ }
+
+ if (ErrorCode & BIT3) {
+ DEBUG ((DEBUG_ERROR, "Command Index Error\n"));
+ }
+
+ return Status;
+}
+
+/**
+ Reset the host CMD and DATA Line
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_TIMEOUT The timeout time expired.
+**/
+EFI_STATUS
+EmmcReset (
+ IN UINTN EmmcBaseAddress
+ )
+{
+ UINT8 Data8;
+ UINT8 ResetType;
+ UINT16 SaveClkCtl;
+ UINT32 Data;
+ UINT32 TimeOutCount;
+
+ ResetType = (B_PCH_SCS_DEV_MEM_SWRST_CMDLINE | B_PCH_SCS_DEV_MEM_SWRST_DATALINE);
+
+ //
+ // To improve eMMC stability, we zero the R_PCH_SCS_DEV_MEM_CLKCTL register and
+ // stall for 50 microsecond before reseting the controller. We
+ // restore the register setting following the reset operation.
+ //
+ SaveClkCtl = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL);
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL, 0);
+ MicroSecondDelay (50);
+ //
+ // Reset the SD host controller
+ //
+ MmioWrite8 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_SWRST, ResetType);
+
+ Data = 0;
+ TimeOutCount = 1000; // 1 second timeout
+ do {
+ MicroSecondDelay (1 * 1000);
+
+ TimeOutCount --;
+
+ Data8 = MmioRead8 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_SWRST);
+ if ((Data8 & ResetType) == 0) {
+ break;
+ }
+ } while (TimeOutCount > 0);
+
+ //
+ // We now restore the R_PCH_SCS_DEV_MEM_CLKCTL register which we set to 0 above.
+ //
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CLKCTL, SaveClkCtl);
+
+ if (TimeOutCount == 0) {
+ DEBUG ((DEBUG_ERROR, "EmmcReset: Time out \n"));
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check card status, print the DEBUG info and check the error
+
+ @param[in] CardStatus Status got from card status register
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI controller.
+ @retval EFI_DEVICE_ERROR Device failed during operation
+**/
+EFI_STATUS
+EmmcCheckCardStatus (
+ IN UINT32 CardStatus
+ )
+{
+
+ EFI_STATUS Status;
+ Status = EFI_SUCCESS;
+ DEBUG ((DEBUG_ERROR, "CardStatus:"));
+
+ if (CardStatus & ADDRESS_OUT_OF_RANGE) {
+ DEBUG ((DEBUG_ERROR, " ADDRESS_OUT_OF_RANGE"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ADDRESS_MISALIGN) {
+ DEBUG ((DEBUG_ERROR, " ADDRESS_MISALIGN"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & BLOCK_LEN_ERROR) {
+ DEBUG ((DEBUG_ERROR, " BLOCK_LEN_ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ERASE_SEQ_ERROR) {
+ DEBUG ((DEBUG_ERROR, " ERASE_SEQ_ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ERASE_PARAM) {
+ DEBUG ((DEBUG_ERROR, " ERASE_PARAM"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & WP_VIOLATION) {
+ DEBUG ((DEBUG_ERROR, " WP_VIOLATION"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & CARD_IS_LOCKED) {
+ DEBUG ((DEBUG_ERROR, " CARD_IS_LOCKED"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & LOCK_UNLOCK_FAILED) {
+ DEBUG ((DEBUG_ERROR, " LOCK_UNLOCK_FAILED"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & COM_CRC_ERROR) {
+ DEBUG ((DEBUG_ERROR, " COM_CRC_ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ILLEGAL_COMMAND) {
+ DEBUG ((DEBUG_ERROR, " ILLEGAL_COMMAND"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & CARD_ECC_FAILED) {
+ DEBUG ((DEBUG_ERROR, " CARD_ECC_FAILED"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & CC_ERROR) {
+ DEBUG ((DEBUG_ERROR, " CC_ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ERROR) {
+ DEBUG ((DEBUG_ERROR, " ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & CID_CSD_OVERWRITE) {
+ DEBUG ((DEBUG_ERROR, " CID_CSD_OVERWRITE"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & WP_ERASE_SKIP) {
+ DEBUG ((DEBUG_ERROR, " WP_ERASE_SKIP"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & ERASE_RESET) {
+ DEBUG ((DEBUG_ERROR, " ERASE_RESET"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ if (CardStatus & SWITCH_ERROR) {
+ DEBUG ((DEBUG_ERROR, " SWITCH_ERROR"));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ DEBUG ((DEBUG_ERROR, " \n"));
+
+ return Status;
+}
+/**
+ The main function used to send the command to the card inserted into the SD/MMC host
+ slot. It will assemble the arguments to set the command register and wait for the command
+ and transfer completed until timeout. Then it will read the response register to fill
+ the ResponseData.
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] CommandIndex The command index to set the command index field of command register
+ @param[in] Argument Command argument to set the argument field of command register
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out
+ @param[in] Buffer Contains the data read from / write to the device
+ @param[in] BufferSize The size of the buffer
+ @param[in] ResponseType RESPONSE_TYPE
+ @param[in] TimeOut Time out value in 1 ms unit
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_OUT_OF_RESOURCES A resource has run out.
+ @retval EFI_TIMEOUT The timeout time expired.
+ @retval EFI_DEVICE_ERROR The physical device reported an error while attempting the operation
+**/
+EFI_STATUS
+SendCommand (
+ IN UINTN EmmcBaseAddress,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ResponseDataCount;
+ UINT16 Data16;
+ UINT32 Data32;
+ UINT64 Data64;
+ UINT32 BlockLength;
+ UINT32 Index;
+ BOOLEAN CommandCompleted;
+ BOOLEAN BufferReadReady;
+ INT32 Timeout;
+
+ Status = EFI_SUCCESS;
+ BlockLength = BLOCK_LENGTH;
+
+ if (Buffer != NULL && DataType == NoData) {
+ Status = EFI_INVALID_PARAMETER;
+ return Status;
+ }
+
+ //
+ // Check CMD INHIBIT and DATA INHIBIT before send command
+ //
+ Timeout = 1000;
+ do {
+ Data32 = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_PSTATE);
+ MicroSecondDelay (100);
+ } while ((Timeout-- > 0) && (Data32 & BIT0));
+
+ Timeout = 1000;
+ do {
+ Data32 = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_PSTATE);
+ MicroSecondDelay (100);
+ } while ((Timeout-- > 0) && (Data32 & BIT1));
+
+
+ //
+ // Enable Interrupts
+ //
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTEN, B_PCH_SCS_DEV_MEM_NINTEN_MASK);
+
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_ERINTEN, B_PCH_SCS_DEV_MEM_ERINTEN_MASK);
+
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSIGNEN, B_PCH_SCS_DEV_MEM_NINTSIGNEN_MASK);
+
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_ERINTSIGNEN, B_PCH_SCS_DEV_MEM_ERINTSIGNEN_MASK);
+
+ //
+ // Clear status bits
+ //
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS, B_PCH_SCS_DEV_MEM_NINTSTS_CLEAR_MASK);
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_ERINTSTS, B_PCH_SCS_DEV_MEM_ERINTSTS_CLEAR_MASK);
+
+ if (Buffer != NULL) {
+ Data16 = 0;
+ if (BufferSize <= BlockLength) {
+ Data16 |= BufferSize;
+ } else {
+ Data16 |= BlockLength;
+ }
+ } else {
+ Data16 = 0;
+ }
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_BLKSZ, Data16);
+
+ if (Buffer != NULL) {
+ if (BufferSize <= BlockLength) {
+ Data16 = 1;
+ } else {
+ Data16 = (UINT16) (BufferSize / BlockLength);
+ }
+ } else {
+ Data16 = 0;
+ }
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_BLKCNT, Data16);
+
+ //
+ // Argument
+ //
+ MmioWrite32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CMDARG, Argument);
+
+ //
+ // Transfer Mode
+ //
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_XFRMODE);
+
+ //
+ // Data Transfer Direction Select
+ //
+ Data16 = 0;
+ if (DataType == InData) {
+ Data16 |= B_PCH_SCS_DEV_MEM_XFRMODE_DATA_TRANS_DIR;
+ }
+
+ if (CommandIndex == SEND_EXT_CSD) {
+ Data16 |= B_PCH_SCS_DEV_MEM_XFRMODE_BLKCNT_EN;
+ }
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_XFRMODE, Data16);
+ //
+ //Command
+ //
+ //ResponseTypeSelect IndexCheck CRCCheck ResponseType
+ // 00 0 0 NoResponse
+ // 01 0 1 R2
+ // 10 0 0 R3, R4
+ // 10 1 1 R1, R5, R6, R7
+ // 11 1 1 R1b, R5b
+ //
+ switch (ResponseType) {
+ case ResponseNo:
+ Data16 = (CommandIndex << 8);
+ ResponseDataCount = 0;
+ break;
+
+ case ResponseR1:
+ case ResponseR5:
+ case ResponseR6:
+ case ResponseR7:
+ Data16 = (CommandIndex << 8) | V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP48 |
+ B_PCH_SCS_DEV_MEM_SDCMD_CMD_INDEX_CHECK_EN | B_PCH_SCS_DEV_MEM_SDCMD_CMD_CRC_CHECK_EN;
+ ResponseDataCount = 1;
+ break;
+
+ case ResponseR1b:
+ case ResponseR5b:
+ Data16 = (CommandIndex << 8) | V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP48_CHK |
+ B_PCH_SCS_DEV_MEM_SDCMD_CMD_INDEX_CHECK_EN | B_PCH_SCS_DEV_MEM_SDCMD_CMD_CRC_CHECK_EN;
+ ResponseDataCount = 1;
+ break;
+
+ case ResponseR2:
+ Data16 = (CommandIndex << 8) | V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP136 |
+ B_PCH_SCS_DEV_MEM_SDCMD_CMD_CRC_CHECK_EN;
+ ResponseDataCount = 4;
+ break;
+
+ case ResponseR3:
+ case ResponseR4:
+ Data16 = (CommandIndex << 8) | V_PCH_SCS_DEV_MEM_SDCMD_RESP_TYPE_SEL_RESP48;
+ ResponseDataCount = 1;
+ break;
+
+ default:
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ return Status;
+ }
+
+ if (DataType != NoData) {
+ Data16 |= B_PCH_SCS_DEV_MEM_SDCMD_DATA_PRESENT_SEL;
+ }
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_SDCMD, Data16);
+ CommandCompleted = FALSE;
+ BufferReadReady = FALSE;
+ TimeOut = 1000;
+ do {
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_ERINTSTS);
+ if ((Data16 & B_PCH_SCS_DEV_MEM_ERINTSTS_MASK) != 0) {
+ Status = EmmcGetErrorReason (CommandIndex, Data16);
+ return Status;
+ }
+
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS) & 0x1ff;
+ if (Data16 & B_PCH_SCS_DEV_MEM_NINTSTS_CMD_COMPLETE) {
+ //
+ // Command completed
+ //
+ CommandCompleted = TRUE;
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS, B_PCH_SCS_DEV_MEM_NINTSTS_CMD_COMPLETE);
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS);
+ if ((DataType == NoData) & (ResponseType != ResponseR1b)) {
+ break;
+ }
+ }
+
+ if ((CommandCompleted) && (ResponseType == ResponseR1b)) {
+ Data32 = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_PSTATE);
+ if (Data32 & B_PCH_SCS_DEV_MEM_PSTATE_DAT0) {
+ break;
+ }
+ }
+
+ if ((CommandCompleted) && (Buffer!= NULL)) {
+ if (!(Data16 & B_PCH_SCS_DEV_MEM_NINTSTS_CMD_COMPLETE)) {
+
+ if (Data16 & B_PCH_SCS_DEV_MEM_NINTSTS_BUF_READ_READY_INTR) {
+ BufferReadReady = TRUE;
+ MmioOr16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS, B_PCH_SCS_DEV_MEM_NINTSTS_BUF_READ_READY_INTR);
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS);
+ }
+
+ if (BufferReadReady) {
+ if (!(Data16 & B_PCH_SCS_DEV_MEM_NINTSTS_BUF_READ_READY_INTR)) {
+ for (Index = 0; Index < BufferSize; Index = Index + 4) {
+ Data32 = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_BUFDATAPORT);
+ if ((Index + 4) < BufferSize) {
+ CopyMem ((Buffer + Index), &Data32, 4);
+ } else {
+ CopyMem ((Buffer + Index), &Data32, (BufferSize - Index));
+ }
+ }
+ }
+ Data16 = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS);
+ }
+
+ if (Data16 & B_PCH_SCS_DEV_MEM_NINTSTS_TRANSFER_COMPLETE) {
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_NINTSTS, B_PCH_SCS_DEV_MEM_NINTSTS_TRANSFER_COMPLETE);
+ break;
+ }
+ }
+ }
+ MicroSecondDelay (1*1000);
+
+ TimeOut --;
+
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ return Status;
+ }
+
+ if (ResponseData != NULL) {
+ UINT32 *ResDataPtr = NULL;
+
+ ResDataPtr = ResponseData;
+ for (Index = 0; Index < ResponseDataCount; Index++) {
+ *ResDataPtr = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_RESP + Index * 4);
+ ResDataPtr++;
+ }
+
+ if (ResponseType == ResponseR2) {
+ //
+ // Adjustment for R2 response
+ //
+ Data32 = 1;
+ for (Index = 0; Index < ResponseDataCount; Index++) {
+ Data64 = LShiftU64 (*ResponseData, 8);
+ *ResponseData = (UINT32) ((Data64 & 0xFFFFFFFF) | Data32);
+ Data32 = (UINT32) RShiftU64 (Data64, 32);
+ ResponseData++;
+ }
+ }
+ }
+ return Status;
+}
+
+/**
+ This main function is to send command to Emmc
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] CommandIndex The command index to set the command index field of command register
+ @param[in] Argument Command argument to set the argument field of command register
+ @param[in] DataType TRANSFER_TYPE, indicates no data, data in or data out
+ @param[in] Buffer Contains the data read from / write to the device
+ @param[in] BufferSize The size of the buffer
+ @param[in] ResponseType RESPONSE_TYPE
+ @param[in] TimeOut Time out value in 1 ms unit
+ @param[out] ResponseData Depending on the ResponseType, such as CSD or card status
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_OUT_OF_RESOURCES A resource has run out.
+ @retval EFI_TIMEOUT The timeout time expired.
+ @retval EFI_DEVICE_ERROR The physical device reported an error while attempting the operation
+**/
+EFI_STATUS
+EmmcSendCommand (
+ IN UINTN EmmcBaseAddress,
+ IN UINT16 CommandIndex,
+ IN UINT32 Argument,
+ IN TRANSFER_TYPE DataType,
+ IN UINT8 *Buffer, OPTIONAL
+ IN UINT32 BufferSize,
+ IN RESPONSE_TYPE ResponseType,
+ IN UINT32 TimeOut,
+ OUT UINT32 *ResponseData
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SendCommand (
+ EmmcBaseAddress,
+ CommandIndex,
+ Argument,
+ DataType,
+ Buffer,
+ BufferSize,
+ ResponseType,
+ TimeOut,
+ ResponseData
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {
+ ASSERT (ResponseData != NULL);
+ Status = EmmcCheckCardStatus (*ResponseData);
+ if (EFI_ERROR (Status)) {
+ EmmcReset (EmmcBaseAddress);
+ }
+ }
+ } else {
+ //
+ // Reset Host Controller CMD and DATA
+ //
+ EmmcReset (EmmcBaseAddress);
+ }
+
+ return Status;
+}
+/**
+ Set Tx Data Delay Control 1
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] Value Value (0 - 79)
+
+ @retval VOID
+**/
+VOID
+EmmcSetTxDllCtrl1 (
+ IN UINTN EmmcBaseAddress,
+ IN UINT8 Value
+ )
+{
+ MmioAndThenOr8 (EmmcBaseAddress + (R_PCH_SCS_DEV_MEM_TX_DATA_DLL_CNTL1 + 1), 0, Value);
+}
+
+/**
+ Set Rx Strobe Delay Control DLL1 for HS400
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] RxDll To program RxDll1 or RxDll2 register
+ @param[in] Value Value (0 - 39)
+
+ @retval VOID
+**/
+VOID
+EmmcSetRxDllCtrl (
+ IN UINTN EmmcBaseAddress,
+ IN UINT8 RxDll,
+ IN UINT8 Value
+ )
+{
+ if (RxDll == RxDll1) {
+ MmioAndThenOr8 (EmmcBaseAddress + (R_PCH_SCS_DEV_MEM_RX_STROBE_DLL_CNTL + 1), 0, Value);
+ } else {
+ MmioAndThenOr8 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_RX_STROBE_DLL_CNTL, 0, Value);
+ }
+}
+
+/**
+ Disable eMMC Host HS400 Support
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+
+ @retval N/A
+**/
+VOID
+EmmcHostHs400Disabled (
+ IN UINTN EmmcBaseAddress
+ )
+{
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode()::EmmcHostHs400Disabled()\n"));
+ MmioAnd32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1, (UINT32) ~B_PCH_SCS_DEV_MEM_CAP_BYPASS_REG1_HS400);
+}
+/**
+ Set Host Mode
+
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] Mode Set Host Mode, 0: HS200, 1: HS400
+
+ @retval N/A
+**/
+VOID
+EmmcSetHostMode (
+ IN UINTN EmmcBaseAddress,
+ IN UINT32 Mode
+ )
+{
+ UINT16 ModeSet;
+ UINT32 HostCapabilities;
+
+ ModeSet = MmioRead16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_HOST_CTL2);
+ HostCapabilities = MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_CAP2);
+
+ ModeSet &= ~B_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_MASK;
+ if ((Mode == Hs200) && (HostCapabilities & B_PCH_SCS_DEV_MEM_CAP2_SDR104_SUPPORT)) {
+ ModeSet |= V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_SDR104;
+ } else if ((Mode == Hs400) && (HostCapabilities & B_PCH_SCS_DEV_MEM_CAP2_HS400_SUPPORT)) {
+ ModeSet |= V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_HS400;
+ } else if (Mode == DDR50) {
+ ModeSet |= V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_DDR50;
+ } else if (Mode == SDR25) {
+ ModeSet |= V_PCH_SCS_DEV_MEM_HOST_CTL2_MODE_SDR25;
+ }
+
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode(): SetHostDdrMode = 0x%x\n", ModeSet));
+
+ MmioWrite16 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_HOST_CTL2, ModeSet);
+}
+
+/**
+ To select eMMC card operating mode HS200/HS400
+
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] EmmcMode To select HS200 or HS400 mode
+
+ @retval EFI_SUCCESS Emmc Mode Select successful.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+**/
+EFI_STATUS
+EmmcModeSelection (
+ IN EMMC_INFO *EmmcInfo,
+ IN UINTN EmmcBaseAddress,
+ IN EMMC_MODE EmmcMode
+ )
+{
+ SWITCH_ARGUMENT SwitchArgument;
+ UINT32 CardStatus;
+ UINT32 HsTimingValue;
+ UINT32 BusWidthValue;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode()::EmmcModeSelection() Start\n"));
+
+ if (EmmcMode == Hs200) {
+ HsTimingValue = 0x02;
+ BusWidthValue = EmmcInfo->HS200BusWidth;
+ DEBUG ((DEBUG_INFO, "HS200 Driver Strength: 50 Ohm\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "HS400 Driver Strength: "));
+ switch (mPchConfigHob->Scs.ScsEmmcHs400DriverStrength) {
+ case DriverStrength33Ohm:
+ HsTimingValue = 0x13;
+ DEBUG ((DEBUG_INFO, "33 Ohm\n"));
+ break;
+ case DriverStrength40Ohm:
+ HsTimingValue = 0x43;
+ DEBUG ((DEBUG_INFO, "40 Ohm\n"));
+ break;
+ case DriverStrength50Ohm:
+ HsTimingValue = 0x03;
+ DEBUG ((DEBUG_INFO, "50 Ohm\n"));
+ break;
+ default:
+ HsTimingValue = 0x13;
+ DEBUG ((DEBUG_INFO, "default - 33 Ohm\n"));
+ }
+
+ BusWidthValue = 6;
+ }
+ SetClockFrequency (EmmcBaseAddress, (50 * 1000 * 1000)); // Set 50MHz
+ //
+ // 1. Set HS_TIMING to 0x01 for High Speed interface timing. This is required prior DDR 8 bit bus width setting (CMD6)
+ //
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = 1;
+ SwitchArgument.Index = HS_TIMING_INDEX;
+ SwitchArgument.Access = WRITE_BYTE_MODE;
+ Status = EmmcSendCommand (
+ EmmcBaseAddress,
+ SWITCH,
+ *(UINT32*)&SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ &CardStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ EmmcSetHostMode (EmmcBaseAddress, SDR25);
+
+ //
+ // 2. Set desired bus width to DDR 8 bit CMD6
+ //
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = BusWidthValue;
+ SwitchArgument.Index = BUS_WIDTH_INDEX;
+ SwitchArgument.Access = WRITE_BYTE_MODE;
+ Status = EmmcSendCommand (
+ EmmcBaseAddress,
+ SWITCH,
+ *(UINT32*)&SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ &CardStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ EmmcSetHostMode (EmmcBaseAddress, DDR50);
+
+ //
+ // 3. Set HS400 bit and Driver Strentgh value in HS_TIMING (CMD6)
+ //
+ ZeroMem (&SwitchArgument, sizeof (SWITCH_ARGUMENT));
+ SwitchArgument.CmdSet = 0;
+ SwitchArgument.Value = HsTimingValue;
+ SwitchArgument.Index = HS_TIMING_INDEX;
+ SwitchArgument.Access = WRITE_BYTE_MODE;
+ Status = EmmcSendCommand (
+ EmmcBaseAddress,
+ SWITCH,
+ *(UINT32*)&SwitchArgument,
+ NoData,
+ NULL,
+ 0,
+ ResponseR1b,
+ TIMEOUT_COMMAND,
+ &CardStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (EmmcMode == Hs200) {
+ DEBUG ((DEBUG_INFO, "Set eMMC Mode: HS200\n"));
+ EmmcSetHostMode (EmmcBaseAddress, Hs200);
+ } else {
+ DEBUG ((DEBUG_INFO, "Set eMMC Mode: HS400\n"));
+ EmmcSetHostMode (EmmcBaseAddress, Hs400);
+ }
+ SetClockFrequency (EmmcBaseAddress, (200 * 1000 * 1000)); // Set 200MHz
+
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode()::EmmcModeSelection() End\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ Prints worst case pattern used for HS400 taining
+
+ @param[in] BlockIo A pointer to EFI_BLOCK_IO_PROTOCOL structure
+ @param[in] TuningPattern Data buffer containg pattern for training
+ @param[in] TuningPatternSize Size of the buffer with pattern
+
+ @retval N/A
+**/
+VOID
+EmmcPrintHs400TuningPattern (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UINT8 *TuningPattern,
+ IN UINT32 TuningPatternSize
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINT32 Index;
+
+ DEBUG ((DEBUG_VERBOSE, "--------------- TUNING PATTERN ----------------\n"));
+ DEBUG ((DEBUG_VERBOSE, "BlockIo->Media->MediaId = 0x%08x\n", BlockIo->Media->MediaId));
+ DEBUG ((DEBUG_VERBOSE, "BlockIo->Media->BlockSize = 0x%08x\n", BlockIo->Media->BlockSize));
+ DEBUG ((DEBUG_VERBOSE, "Tuning Pattern Size = 0x%08x\n", TuningPatternSize));
+ for (Index = 0; Index < TuningPatternSize; Index++) {
+ if (Index % 16 == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ }
+ if (Index % (BlockIo->Media->BlockSize) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "-------------------- BLOCK --------------------\n"));
+ }
+ DEBUG ((DEBUG_VERBOSE, "%02x ", TuningPattern[Index]));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n-----------------------------------------------\n"));
+ DEBUG_CODE_END ();
+}
+
+/**
+ Writes worst case pattern used for HS400 taining
+
+ @param[in] BlockIo A pointer to EFI_BLOCK_IO_PROTOCOL structure
+ @param[in] TuningPattern Data buffer containg pattern for training
+ @param[in] TuningPatternSize Size of the buffer with pattern
+
+ @retval EFI_SUCCESS HS400 Rx Data Path Training is successful.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+**/
+EFI_STATUS
+EmmcWriteHs400TuningPattern (
+ IN EMMC_INFO *EmmcInfo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UINTN EmmcBaseAddress,
+ IN UINT8 *TuningPattern
+ )
+{
+ UINT8 *Buffer;
+ UINT32 Index;
+ UINT32 TuningPatternSize;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ TuningPatternSize = BlockIo->Media->BlockSize * EMMC_HS400_TUNING_PATTERN_BLOCKS_NUMBER;
+
+ DEBUG ((DEBUG_INFO, "EmmcWriteHs400TuningPattern() Start\n"));
+
+ Buffer = (VOID *) AllocateZeroPool (TuningPatternSize);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ for (Index = 0; Index < EMMC_HS400_TUNING_PATTERN_BLOCKS_NUMBER; Index++){
+ CopyMem (Buffer + (Index * BlockIo->Media->BlockSize), TuningPattern, BlockIo->Media->BlockSize);
+ }
+
+ Status = BlockIo->WriteBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ TuningPatternSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcWriteHs400TuningPattern: Multiple Blocks Write at HS200 Mode Failed!\n"));
+ goto Exit;
+ }
+
+Exit:
+ FreePool (Buffer);
+ DEBUG ((DEBUG_INFO, "EmmcWriteHs400TuningPattern() End, Status = %r\n", Status));
+ return Status;
+}
+
+/**
+ To perform HS400 Rx Data Path Training
+
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[in] BlockIo A pointer to EFI_BLOCK_IO_PROTOCOL structure
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in/out] EmmcTuningData A pointer to EMMC_TUNING_DATA structure
+
+ @retval EFI_SUCCESS HS400 Rx Data Path Training is successful.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+**/
+EFI_STATUS
+EmmcRxHs400Tuning (
+ IN EMMC_INFO *EmmcInfo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UINTN EmmcBaseAddress,
+ IN OUT EMMC_TUNING_DATA *EmmcTuningData
+ )
+{
+ UINT8 *Buffer;
+ UINT8 DllCount;
+ UINT8 DllMax;
+ UINT8 DllMin;
+ UINT8 Smin;
+ UINT8 Smax;
+ UINT8 Sopt;
+ EFI_STATUS Status;
+ EFI_STATUS ModeStatus;
+ BLOCK_READ_WRITE_STATUS FirstRead;
+ UINT32 TuningPatternSize;
+
+ DEBUG ((DEBUG_INFO, "EmmcRxHs400Tuning() Start\n"));
+
+ Status = EFI_SUCCESS;
+ ModeStatus = EFI_SUCCESS;
+
+ Smin = RX_STROBE_DLL1_TAP_MIN_MEPT;
+ Smax = RX_STROBE_DLL1_TAP_MAX_MEPT;
+ TuningPatternSize = BlockIo->Media->BlockSize * EMMC_HS400_TUNING_PATTERN_BLOCKS_NUMBER;
+
+ Buffer = (VOID *) AllocateZeroPool (TuningPatternSize);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // 1. Read Tuning Block
+ //
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ TuningPatternSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcRxHs400Tuning: Tuning Blocks Read at HS200 Mode Failed!\n"));
+ goto Exit;
+ }
+
+ DEBUG_CODE ( EmmcPrintHs400TuningPattern (BlockIo, Buffer, TuningPatternSize); );
+
+ //
+ // 2. Move to HS400 Mode
+ //
+ Status = EmmcModeSelection (EmmcInfo, EmmcBaseAddress, Hs400);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcRxHs400Tuning: eMMC HS400 Mode Selection Failed!\n"));
+ goto Exit;
+ }
+ //
+ // 3. Set Rx Strobe DLL1 to the Minimal Expected Passing Tap (Smin)
+ // Offset 830h: Rx Strobe Delay DLL 1(HS400 Mode), bits [14:8]
+ // Set Rx Data Strobe DLL2 to middle point 0x13
+ // Offset 830h: Rx Strobe Delay DLL 2(HS400 Mode), bits [6:0]
+ DEBUG ((DEBUG_INFO, "EmmcRxHs400Tuning: Set Rx Data DLL1 to the Minimal Expected Passing Tap (Smin = 0x%x)\n", Smin));
+ DllCount = RX_STROBE_DLL1_TAP_MIN_MEPT;
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll1, DllCount);
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll2, DllCount);
+
+ //
+ // 4. Read the block that was stored
+ // 5. If CRC fails on first read, increase the DLL Step and repeat block read until passed
+ // Else if CRC passed on first read, decrease the DLL Step and repeat block read until failed
+ // 6. Store the Rx Path min DLL passing step number
+ //
+ FirstRead = NotAvailable;
+ DllMax = RX_STROBE_DLL1_TAP_MAX_RANGE;
+ DllMin = RX_STROBE_DLL1_TAP_MIN_RANGE;
+
+ while ((DllCount <= DllMax) && (DllCount >= DllMin)) {
+ DEBUG ((DEBUG_INFO, "[ EmmcRxHs400Tuning: Rx Min DLL1 (DllCount) = 0x%x ]\n", DllCount));
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ TuningPatternSize,
+ Buffer
+ );
+ if (Status == EFI_SUCCESS) {
+ if (FirstRead == NotAvailable) {
+ FirstRead = Passed;
+ } else if (FirstRead == Failed) {
+ Smin = DllCount;
+ break;
+ }
+ if (DllCount == RX_STROBE_DLL1_TAP_MIN_RANGE) {
+ Smin = RX_STROBE_DLL1_TAP_MIN_RANGE;
+ break;
+ }
+ } else if (Status == EFI_CRC_ERROR) { // Rely on the driver to return ReadBlocks status on CRC error
+ if (FirstRead == NotAvailable) {
+ FirstRead = Failed;
+ } else if (FirstRead == Passed) {
+ Smin = DllCount + 1;
+ break;
+ }
+ if (DllCount == RX_STROBE_DLL1_TAP_MAX_RANGE) {
+ Status = EFI_CRC_ERROR;
+ DEBUG ((DEBUG_ERROR, "[Rx DLL Tuning Failed] DllCount == TAP_MAX_RANGE\n"));
+ goto Exit;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "[Rx DLL Tuning Failed] Smin - Tuning Blocks Read Error!\n"));
+ goto Exit;
+ }
+
+ if (FirstRead == Failed) {
+ DllCount++;
+ } else {
+ DllCount--;
+ }
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll1, DllCount);
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll2, DllCount);
+ }
+
+ DEBUG ((DEBUG_INFO, "[Rx DLL Tuning] Found Minimal Passing Tap = 0x%x\n", Smin));
+
+ //
+ // 7. Set the Rx Strobe DLL1 to the Maximal Expected Passing Tap (Smax)
+ // Offset 830h: Rx Strobe Delay DLL 1(HS400 Mode), bits [14:8]
+ // 8. Read the block that was stored
+ // 9. If CRC fails on first read, decrease the DLL Step and repeat step 8 until pass
+ // Else if CRC passed on first read, increase the DLL Step and repeat step 8 until failed
+ //
+ DEBUG ((DEBUG_INFO, "EmmcRxHs400Tuning: Set Rx Data DLL1 to the Maximal Expected Passing Tap (Smax = 0x%x)\n", Smax));
+ DllCount = RX_STROBE_DLL1_TAP_MAX_MEPT;
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll1, DllCount);
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll2, DllCount);
+
+ FirstRead = NotAvailable;
+ DllMax = RX_STROBE_DLL1_TAP_MAX_RANGE;
+ DllMin = RX_STROBE_DLL1_TAP_MIN_RANGE;
+ while ((DllCount <= DllMax) && (DllCount >= DllMin)) {
+ DEBUG ((DEBUG_INFO, "[ EmmcRxHs400Tuning: Rx Max DLL1 (DllCount) = 0x%x ]\n", DllCount));
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ TuningPatternSize,
+ Buffer
+ );
+ if (Status == EFI_SUCCESS) {
+ if (FirstRead == NotAvailable) {
+ FirstRead = Passed;
+ } else if (FirstRead == Failed) {
+ Smax = DllCount;
+ break;
+ }
+ if (DllCount == RX_STROBE_DLL1_TAP_MAX_RANGE) {
+ Smax = DllCount;
+ break;
+ }
+ } else if (Status == EFI_CRC_ERROR) { // Rely on the driver to return ReadBlocks status on CRC error
+ if (FirstRead == NotAvailable) {
+ FirstRead = Failed;
+ } else if (FirstRead == Passed) {
+ Smax = DllCount - 1;
+ break;
+ }
+ if (DllCount == RX_STROBE_DLL1_TAP_MIN_RANGE) {
+ Status = EFI_CRC_ERROR;
+ goto Exit;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "[Rx DLL Tuning Failed] Smax - Tuning Blocks Read Error!\n"));
+ goto Exit;
+ }
+ if (FirstRead == Failed) {
+ DllCount--;
+ } else {
+ DllCount++;
+ }
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll1, DllCount);
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll2, DllCount);
+ }
+ //
+ // 10. Store the Rx Path max DLL Passing Step number
+ //
+
+ //
+ // 11. Compute the Rx DLL Optimal Point (Sopt) = (Smax - Smin)/2 + Smin
+ //
+ Sopt = (Smax - Smin) / 2 + Smin;
+ DEBUG ((DEBUG_INFO, "[Rx DLL Tuning] Optimal Point (Sopt = (Smax[0x%x] - Smin[0x%x]) / 2 + Smin[0x%x]) = 0x%x\n", Smax, Smin, Smin, Sopt));
+ //
+ // 12. Store the Rx DLL optimal value (Sopt)
+ //
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll1, Sopt);
+ EmmcSetRxDllCtrl (EmmcBaseAddress, RxDll2, Sopt);
+
+ DEBUG ((DEBUG_INFO, "[Rx HS400 Tuning Success] Rx Strobe Delay Control (830h) = 0x%08x\n",
+ MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_RX_STROBE_DLL_CNTL)));
+
+ Status = EFI_SUCCESS;
+ EmmcTuningData->Hs400RxStrobe1Dll = Sopt;
+
+Exit:
+ FreePool (Buffer);
+ DEBUG ((DEBUG_INFO, "EmmcRxHs400Tuning() End, Status = %r\n", Status));
+ return Status;
+}
+
+/**
+ To perform HS400 Tx Data Path Training
+
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[in] EmmcBaseAddress Base address of MMIO register
+ @param[in] BlockIo A pointer to EFI_BLOCK_IO_PROTOCOL structure
+ @param[in/out] EmmcTuningData A pointer to EMMC_TUNING_DATA structure
+
+ @retval EFI_SUCCESS HS400 Rx Data Path Training is successful.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+**/
+EFI_STATUS
+EmmcTxHs400Tuning (
+ IN EMMC_INFO *EmmcInfo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UINTN EmmcBaseAddress,
+ IN OUT EMMC_TUNING_DATA *EmmcTuningData
+ )
+{
+ UINT8 *Buffer;
+ UINT8 DllCount;
+ UINT8 DllMax;
+ UINT8 DllMin;
+ UINT8 Smin;
+ UINT8 Smax;
+ UINT8 Sopt;
+ UINT8 N;
+ EFI_STATUS Status;
+ EFI_STATUS ModeStatus;
+ BLOCK_READ_WRITE_STATUS FirstWrite;
+
+ DEBUG ((DEBUG_INFO, "EmmcTxHs400Tuning() Start\n"));
+ Status = EFI_SUCCESS;
+ ModeStatus = EFI_SUCCESS;
+
+ Smin = TX_DATA_DLL_TAP_MIN_MEPT;
+ Smax = TX_DATA_DLL_TAP_MAX_MEPT;
+ N = 0;
+
+ Buffer = (VOID *) AllocateZeroPool (BlockIo->Media->BlockSize);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ //
+ // 1. Read Tuning Block that used at Rx HS400 Tuning
+ //
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ BlockIo->Media->BlockSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "EmmcTxHs400Tuning: Tuning Block Read at HS400 Mode Failed!\n"));
+ goto Exit;
+ }
+ DEBUG_CODE ( EmmcPrintHs400TuningPattern (BlockIo, Buffer, BlockIo->Media->BlockSize); );
+
+ //
+ // 2. Set Tx Data DLL1 to the Minimal Expected Passing Tap (Smin)
+ // Offset 824h: Tx Data Delay Control 1
+ // Tx Data Delay (HS400 Mode), BIT[14:8]
+ //
+ DEBUG ((DEBUG_INFO, "EmmcTxHs400Tuning: Set Tx Data DLL to the Minimal Expected Passing Tap (Smin = 0x%x)\n", Smin));
+
+ DllCount = TX_DATA_DLL_TAP_MIN_MEPT;
+ EmmcSetTxDllCtrl1 (EmmcBaseAddress, DllCount);
+
+ //
+ // 2. Write Single Block
+ //
+ FirstWrite = NotAvailable;
+ DllMax = TX_DATA_DLL_TAP_MAX_RANGE;
+ DllMin = TX_DATA_DLL_TAP_MIN_RANGE;
+
+ while ((DllCount <= DllMax) && (DllCount >= DllMin)) {
+ DEBUG ((DEBUG_INFO, "[ EmmcTxHs400Tuning: Tx Min DLL (DllCount) = 0x%x ]\n", DllCount));
+ Status = BlockIo->WriteBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ BlockIo->Media->BlockSize,
+ Buffer
+ );
+ if (Status == EFI_SUCCESS) {
+ if (FirstWrite == NotAvailable) {
+ FirstWrite = Passed;
+ } else if (FirstWrite == Failed) {
+ Smin = DllCount;
+ break;
+ }
+ if (DllCount == TX_DATA_DLL_TAP_MIN_RANGE) {
+ Smin = TX_DATA_DLL_TAP_MIN_RANGE;
+ break;
+ }
+ //
+ // 3. If CRC fails increment DLL Step and repeat step 2
+ //
+ } else if (Status == EFI_CRC_ERROR) { // Rely on the driver to return ReadBlocks status on CRC error
+ if (FirstWrite == NotAvailable) {
+ FirstWrite = Failed;
+ } else if (FirstWrite == Passed) {
+ Smin = DllCount + 1;
+ break;
+ }
+ if (DllCount == TX_DATA_DLL_TAP_MAX_RANGE) {
+ DEBUG ((DEBUG_ERROR, "[Tx DLL Tuning Failed] DllCount == TAP_MAX_RANGE\n"));
+ goto Exit;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "[Tx DLL Tuning Failed] Smin - Tuning Block Write Error!\n"));
+ goto Exit;
+ }
+ if (FirstWrite == Failed) {
+ DllCount++;
+ } else {
+ DllCount--;
+ }
+ EmmcSetTxDllCtrl1 (EmmcBaseAddress, DllCount);
+ }
+ //
+ // 4. Store the Tx Path min DLL passing step number
+ //
+ DEBUG ((DEBUG_INFO, "[Tx DLL Tuning] Found Minimal Passing Tap = 0x%x\n", Smin));
+
+ //
+ // 5. Set the DLL to max expected passing step (Smax)
+ //
+ DEBUG ((DEBUG_INFO, "EmmcTxHs400Tuning: Set Tx Data DLL to the Maximal Expected Passing Tap (Smax = 0x%x)\n", Smax));
+ DllCount = TX_DATA_DLL_TAP_MAX_MEPT;
+ EmmcSetTxDllCtrl1 (EmmcBaseAddress, DllCount);
+ //
+ // 6. Write Single Block
+ //
+ FirstWrite = NotAvailable;
+ DllMax = TX_DATA_DLL_TAP_MAX_RANGE;
+ DllMin = TX_DATA_DLL_TAP_MIN_RANGE;
+
+ while ((DllCount <= DllMax) && (DllCount >= DllMin)) {
+ DEBUG ((DEBUG_INFO, "[ EmmcTxHs400Tuning: Tx Max DLL1 (DllCount) = 0x%x ]\n", DllCount));
+ Status = BlockIo->WriteBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ EmmcInfo->Lba,
+ BlockIo->Media->BlockSize,
+ Buffer
+ );
+
+ if (Status == EFI_SUCCESS) {
+ if (FirstWrite == NotAvailable) {
+ FirstWrite = Passed;
+ } else if (FirstWrite == Failed) {
+ Smax = DllCount;
+ break;
+ }
+ if (DllCount == TX_DATA_DLL_TAP_MAX_RANGE) {
+ Smax = TX_DATA_DLL_TAP_MAX_RANGE;
+ break;
+ }
+ //
+ // 7. If CRC fails decrement DLL Step and repeat step 6
+ //
+ } else if (Status == EFI_CRC_ERROR) { // Rely on the driver to return ReadBlocks status on CRC error
+ if (FirstWrite == NotAvailable) {
+ FirstWrite = Failed;
+ } else if (FirstWrite == Passed) {
+ Smax = DllCount - 1;
+ break;
+ }
+ if (DllCount == TX_DATA_DLL_TAP_MIN_RANGE) {
+ DEBUG ((DEBUG_ERROR, "[Tx DLL Tuning Failed] DllCount == TAP_MIN_RANGE\n"));
+ goto Exit;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "[Tx DLL Tuning Failed] Smax - Tuning Block Write Error!\n"));
+ goto Exit;
+ }
+ if (FirstWrite == Failed) {
+ DllCount--;
+ } else {
+ DllCount++;
+ }
+ EmmcSetTxDllCtrl1 (EmmcBaseAddress, DllCount);
+ }
+ //
+ // 8. Store the DLL passing step number (Smax)
+ //
+ DEBUG ((DEBUG_INFO, "[Tx DLL Tuning] Found Maximal Passing Tap = 0x%x\n", Smax));
+
+ N = Smax - Smin;
+ if (N <= 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // 9. Compute the Tx DLL Optimal point (Sopt) = (Smax - Smin) / 2 + Smin
+ //
+ Sopt = (Smax - Smin) / 2 + Smin;
+ DEBUG ((DEBUG_INFO, "[Tx DLL Tuning] Optimal Point (Sopt = (Smax[0x%x] - Smin[0x%x]) / 2 + Smin[0x%x]) = 0x%x\n", Smax, Smin, Smin, Sopt));
+
+ //
+ // 10. Store the Tx Strobe DLL Optimal point value
+ //
+ EmmcSetTxDllCtrl1 (EmmcBaseAddress, Sopt);
+
+ DEBUG ((DEBUG_INFO, "[Tx HS400 Tuning Success] Tx Data Delay Control 1 (824h) = 0x%08x\n",
+ MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_TX_DATA_DLL_CNTL1)));
+
+ Status = EFI_SUCCESS;
+ EmmcTuningData->Hs400TxDataDll = Sopt;
+
+Exit:
+ FreePool (Buffer);
+ DEBUG ((DEBUG_INFO, "EmmcTxHs400Tuning() End, Status = %r\n", Status));
+ return Status;
+}
+
+/**
+ To perform write protection checking on the address to write
+
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[in] BlockIo A pointer to EFI_BLOCK_IO_PROTOCOL structure
+ @param[in] EmmcBaseAddress Base address of MMIO register
+
+ @retval EFI_SUCCESS HS400 Rx Data Path Training is successful.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+**/
+EFI_STATUS
+EmmcWriteProtectCheck (
+ IN EMMC_INFO *EmmcInfo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UINTN EmmcBaseAddress
+ )
+{
+ EFI_STATUS Status;
+ UINT32 DataSize;
+ UINT32 CardStatus;
+ UINT32 Address;
+ UINT32 Timeout;
+ UINT16 CommandIndex;
+ UINT8 *Buffer;
+
+ Status = EFI_SUCCESS;
+ DataSize = 8;
+ CommandIndex = SEND_WRITE_PROT_TYPE;
+ Timeout = TIMEOUT_DATA;
+
+ Buffer = (VOID *) AllocateZeroPool (DataSize);
+ Address = (UINT32) DivU64x32 (MultU64x32 (EmmcInfo->Lba, BlockIo->Media->BlockSize), 512);
+
+ DEBUG ((DEBUG_INFO, "EmmcWriteProtectCheck() Start\n"));
+
+ if (BlockIo->Media->ReadOnly == TRUE) {
+ Status = EFI_WRITE_PROTECTED;
+ goto Exit;
+ }
+
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ Status = EmmcSendCommand (
+ EmmcBaseAddress,
+ CommandIndex,
+ Address,
+ InData,
+ Buffer,
+ DataSize,
+ ResponseR1,
+ Timeout,
+ &CardStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((Buffer[7] & (BIT0 | BIT1)) !=0) {
+ Status = EFI_WRITE_PROTECTED;
+ goto Exit;
+ }
+
+Exit:
+ FreePool (Buffer);
+ DEBUG ((DEBUG_INFO, "EmmcWriteProtectCheck End, Status = %r\n", Status));
+ return Status;
+}
+
+/**
+ Configure eMMC in HS400 Mode
+
+ @param[in] This A pointer to PCH_EMMC_TUNING_PROTOCOL structure
+ @param[in] Revision Revision parameter used to verify the layout of EMMC_INFO and TUNINGDATA.
+ @param[in] EmmcInfo A pointer to EMMC_INFO structure
+ @param[out] EmmcTuningData A pointer to EMMC_TUNING_DATA structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND The item was not found
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER A parameter was incorrect.
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+ @retval EFI_CRC_ERROR Command or Data CRC Error
+**/
+EFI_STATUS
+EFIAPI
+ConfigureEmmcHs400Mode (
+ IN PCH_EMMC_TUNING_PROTOCOL *This,
+ IN UINT8 Revision,
+ IN EMMC_INFO *EmmcInfo,
+ OUT EMMC_TUNING_DATA *EmmcTuningData
+ )
+{
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_STATUS Status;
+ EFI_STATUS ModeStatus;
+ UINTN EmmcBaseAddress;
+ UINTN EmmcPciBaseAddress;
+ ModeStatus = EFI_SUCCESS;
+
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode() Start\n"));
+ EmmcTuningData->Hs400DataValid = FALSE;
+ //
+ // Check PCH_EMMC_TUNING_PROTOCOL_REVISION
+ //
+ if (Revision != PCH_EMMC_TUNING_PROTOCOL_REVISION) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: PCH eMMC Tuning Protocol Revision Not Match! Tuning Aborted\n"));
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get eMMC Host Controller Mmio base register
+ //
+ EmmcPciBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SCS_EMMC,
+ PCI_FUNCTION_NUMBER_PCH_SCS_EMMC
+ );
+
+ if (MmioRead16 (EmmcPciBaseAddress + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: eMMC Host Controller Unavailable!\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Assume BAR is ready since it's executed after blockio ready, handling 64bit BAR in DXE is not required
+ //
+ EmmcBaseAddress = MmioRead32 (EmmcPciBaseAddress + PCI_BASE_ADDRESSREG_OFFSET) & 0xFFFFF000;
+ //
+ // Enable Memory Decode
+ //
+ if ((MmioRead8 (EmmcPciBaseAddress + PCI_COMMAND_OFFSET) & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) {
+ MmioOr8 (EmmcPciBaseAddress + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+
+ DEBUG ((DEBUG_INFO, "Initial HS400 DLL values (set in PEI):\n"));
+ DEBUG ((DEBUG_INFO, "Tx Data Delay Control 1 (824h) = 0x%08x\n", MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_TX_DATA_DLL_CNTL1)));
+ DEBUG ((DEBUG_INFO, "Rx Strobe Delay Control (830h) = 0x%08x\n", MmioRead32 (EmmcBaseAddress + R_PCH_SCS_DEV_MEM_RX_STROBE_DLL_CNTL)));
+
+ if (mPchConfigHob->Scs.ScsEmmcHs400TuningRequired == FALSE) {
+ if (mPchConfigHob->Scs.ScsEmmcHs400DllDataValid == TRUE) {
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode: SCS eMMC 5.0 HS400 Tuning Not Required, set device to HS400 mode\n"));
+ Status = EmmcModeSelection (EmmcInfo, EmmcBaseAddress, Hs400);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: eMMC HS400 Mode Selection Failed!\n"));
+ }
+ return Status;
+ } else {
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode: SCS eMMC 5.0 HS400 Mode Selection Not Required.\n"));
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Handle Platform Emmc Info Protocol for Efi Block Io Protocol
+ //
+ Status = gBS->HandleProtocol (
+ EmmcInfo->PartitionHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID**) &BlockIo
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: BlockIo: Platform Emmc Info Protocol Handle Not Found!\n"));
+ EmmcHostHs400Disabled (EmmcBaseAddress);
+ return Status;
+ }
+
+ //
+ // Write Protection checking on the region
+ //
+ Status = EmmcWriteProtectCheck (EmmcInfo, BlockIo, EmmcBaseAddress);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: Region is write protected! HS400 Tuning Abort!\n"));
+ EmmcHostHs400Disabled (EmmcBaseAddress);
+ return Status;
+ }
+
+ Status = EmmcWriteHs400TuningPattern (EmmcInfo, BlockIo, EmmcBaseAddress, (UINT8*)EmmcWorstCasePattern);
+
+ //
+ // Rx HS400 Auto Tuning
+ //
+ Status = EmmcRxHs400Tuning (EmmcInfo, BlockIo, EmmcBaseAddress, EmmcTuningData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: Rx HS400 Auto Tuning Failed!\n"));
+ ModeStatus = EmmcModeSelection (EmmcInfo, EmmcBaseAddress, Hs200);
+ if (EFI_ERROR (ModeStatus)) {
+ DEBUG ((DEBUG_ERROR, "EmmcTxHs400Tuning: eMMC HS200 Mode Selection Failed!\n"));
+ }
+ EmmcTuningData->Hs400DataValid = FALSE;
+ return Status;
+ }
+
+ //
+ // Tx HS400 Auto Tuning
+ //
+ Status = EmmcTxHs400Tuning (EmmcInfo, BlockIo, EmmcBaseAddress, EmmcTuningData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ConfigureEmmcHs400Mode: Tx HS400 Auto Tuning Failed!\n"));
+ ModeStatus = EmmcModeSelection (EmmcInfo, EmmcBaseAddress, Hs200);
+ if (EFI_ERROR (ModeStatus)) {
+ DEBUG ((DEBUG_ERROR, "EmmcTxHs400Tuning: eMMC HS200 Mode Selection Failed!\n"));
+ }
+ EmmcTuningData->Hs400DataValid = FALSE;
+ return Status;
+ }
+
+ //
+ // Set current HS400 Driver Strength in tuning data structre
+ // Set HS400 Data Valid Tuning Bit to TRUE
+ //
+ EmmcTuningData->Hs400DriverStrength = (UINT8) mPchConfigHob->Scs.ScsEmmcHs400DriverStrength;
+ EmmcTuningData->Hs400DataValid = TRUE;
+
+ DEBUG ((DEBUG_INFO, "ConfigureEmmcHs400Mode() End\n"));
+ return Status;
+}
+
+/**
+ Install PCH EMMC TUNING PROTOCOL
+
+**/
+VOID
+InstallPchEmmcTuningProtocol (
+ VOID
+ )
+{
+
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ Handle = NULL;
+
+ ///
+ /// For normal boot flow
+ /// 1. If ScsEmmcEnabled and ScsEmmcHs400Enabled policy set,
+ /// a) Set ScsEmmcHs400TuningRequired policy to state tuning required in PEI,
+ /// - if RTC_PWR_STS bit is set which indicates a new coin-cell battery insertion, a battery failure or CMOS clear.(Boot with default settings)
+ /// - if non-volatile variable 'Hs400TuningData' does not exist
+ /// b) RC installed Pch Emmc Tuning Protocol regardless of ScsEmmcHs400TuningRequired policy setting.in DXE
+ /// c) If boot with default settings after CMOS cleared, platform delete variable 'Hs400TuningData' in DXE
+ /// 2. Once RC successfully installed Pch Emmc Tuning Protocol, it will be used to perform EmmcTune for Hs400.
+ /// 3. Then, platform must set the variable with returned EmmcTuningData no matter tuning pass of fail
+ /// 4. Platform shall set variable 'Hs400TuningData' for one time only or after CMOS clear
+ ///
+ /// For fast boot flow
+ /// 1. If ScsEmmcEnabled and ScsEmmcHs400Enabled policy set,
+ /// a) Set ScsEmmcHs400TuningRequired policy to state tuning not required, if non-volatile variable 'Hs400TuningData' exist
+ /// b) RC installed Pch Emmc Tuning Protocol regardless of ScsEmmcHs400TuningRequired policy setting in DXE
+ /// 2. Once RC successfully installed Pch Emmc Tuning Protocol, it will be used to perform EmmcTune
+ /// 3. Since ScsEmmcHs400TuningRequired state tuning not required, RC will not perform Emmc Hs400 Tuning but just set the device to operate in HS400 mode if data is valid
+ /// 4. Platform shall not set variable 'Hs400TuningData'
+ ///
+ //
+ // Install PchEmmcTuningProtocol Protocol
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gPchEmmcTuningProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &PchEmmcTuningProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c
new file mode 100644
index 0000000000..013c729ddf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c
@@ -0,0 +1,49 @@
+/** @file
+ Initializes Serial IO Controllers.
+
+Copyright (c) 2017, 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 that 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 <PchInit.h>
+#include <Library/PchSerialIoLib.h>
+
+
+/**
+ Puts all SerialIo controllers (except UARTs in debug mode) in D3
+ Clears MemoryEnable for all PCI-mode controllers
+**/
+EFI_STATUS
+ConfigureSerialIoAtBoot (
+ VOID
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER Index;
+ UINTN PciCfgBase;
+
+ for (Index = 0; Index < PchSerialIoIndexMax; Index++) {
+ if ((mPchConfigHob->SerialIo.DevMode[Index] == PchSerialIoDisabled) ||
+ (mPchConfigHob->SerialIo.DevMode[Index] == PchSerialIoSkipInit) ) {
+ continue;
+ }
+ if ((Index >= PchSerialIoIndexUart0) &&
+ (mPchConfigHob->SerialIo.EnableDebugUartAfterPost) &&
+ (mPchConfigHob->SerialIo.DebugUartNumber == (UINT32) (Index - PchSerialIoIndexUart0))) {
+ continue;
+ }
+ PciCfgBase = FindSerialIoBar (Index,1);
+ MmioOr32 (PciCfgBase + R_PCH_SERIAL_IO_PME_CTRL_STS, B_PCH_SERIAL_IO_PME_CTRL_STS_PWR_ST);
+ MmioRead32 (PciCfgBase + R_PCH_SERIAL_IO_PME_CTRL_STS);
+ if (mPchConfigHob->SerialIo.DevMode[Index] == PchSerialIoPci) {
+ MmioAnd32 (PciCfgBase + PCI_COMMAND_OFFSET, (UINT32)~(EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER) );
+ }
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c
new file mode 100644
index 0000000000..3b951092b5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c
@@ -0,0 +1,112 @@
+/** @file
+ Initializes Serial IO Controllers.
+
+Copyright (c) 2017, 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 that 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 <PchInit.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/DevicePathLib.h>
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH RootPort;
+ ACPI_EXTENDED_HID_DEVICE_PATH AcpiDev;
+ CHAR8 HidString[8];
+ CHAR8 UidString;
+ CHAR8 CidString;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} SERIALIO_DEVICE_PATH;
+
+#define gPciRootBridge {{ACPI_DEVICE_PATH, ACPI_DP, {(UINT8)(sizeof(ACPI_HID_DEVICE_PATH)), 0}}, EISA_PNP_ID (0x0A03), 0}
+#define gAcpiDev {{ACPI_DEVICE_PATH,ACPI_EXTENDED_DP,{(UINT8)(sizeof(ACPI_EXTENDED_HID_DEVICE_PATH)+SERIALIO_TOTAL_ID_LENGTH),0}},0,0,0}
+#define gEndEntire {END_DEVICE_PATH_TYPE,END_ENTIRE_DEVICE_PATH_SUBTYPE,{END_DEVICE_PATH_LENGTH,0}}
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIALIO_DEVICE_PATH gSerialIoPath = {
+ gPciRootBridge,
+ gAcpiDev,
+ "\0\0\0\0\0\0\0",
+ '\0',
+ '\0',
+ gEndEntire
+};
+
+/**
+Mark memory used by SerialIo devices in ACPI mode as allocated
+
+@retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+AllocateSerialIoMemory (
+ VOID
+ )
+{
+ PCH_SERIAL_IO_CONTROLLER i;
+ UINT8 BarNumber;
+ UINTN Bar;
+ EFI_STATUS Status;
+
+ for (i=0; i<PchSerialIoIndexMax; i++) {
+ if (mPchConfigHob->SerialIo.DevMode[i] == PchSerialIoAcpiHidden ||
+ mPchConfigHob->SerialIo.DevMode[i] == PchSerialIoLegacyUart ||
+ mPchConfigHob->SerialIo.DevMode[i] == PchSerialIoAcpi) {
+ for (BarNumber = 0; BarNumber<=1; BarNumber++) {
+ Bar = FindSerialIoBar (i,BarNumber);
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeReserved,
+ Bar,
+ V_PCH_SERIAL_IO_BAR_SIZE,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeReserved,
+ N_PCH_SERIAL_IO_BAR_ALIGNMENT,
+ V_PCH_SERIAL_IO_BAR_SIZE,
+ &Bar,
+ mImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+VOID
+CreateSerialIoHandles (
+ VOID
+ )
+{
+ EFI_HANDLE NewHandle;
+ EFI_DEVICE_PATH_PROTOCOL *NewPath;
+ EFI_STATUS Status;
+ UINT32 Controller;
+
+ for (Controller = 0; Controller < PchSerialIoIndexMax; Controller++) {
+ if (mPchConfigHob->SerialIo.DevMode[Controller] == PchSerialIoAcpi) {
+ NewHandle = NULL;
+ CopyMem (gSerialIoPath.HidString, GetSerialIoAcpiHID (Controller), SERIALIO_HID_LENGTH);
+ NewPath = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL*)&gSerialIoPath);
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &NewHandle,
+ &gEfiDevicePathProtocolGuid,
+ NewPath,
+ NULL );
+ }
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c
new file mode 100644
index 0000000000..cfaf0d57bd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c
@@ -0,0 +1,130 @@
+/** @file
+ PCH BIOS Write Protect Driver.
+
+Copyright (c) 2017, 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 that 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 "PchInitSmm.h"
+
+///
+/// Global variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_TCO_SMI_DISPATCH_PROTOCOL *mPchTcoSmiDispatchProtocol;
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSpiRegBase;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_ESPI_SMI_DISPATCH_PROTOCOL *mEspiSmmDispatchProtocol;
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLpcRegBase;
+
+/**
+ This hardware SMI handler will be run every time the BIOS Write Enable bit is set.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+PchSpiBiosWpCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ //
+ // Disable BIOSWE bit to protect BIOS
+ //
+ MmioAnd8 ((UINTN) (mSpiRegBase + R_PCH_SPI_BC), (UINT8) ~B_PCH_SPI_BC_WPD);
+}
+
+/**
+ This hardware SMI handler will be run every time the BIOS Write Enable bit is set.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+PchLpcBiosWpCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ //
+ // Disable BIOSWE bit to protect BIOS
+ //
+ MmioAnd8 ((UINTN) (mLpcRegBase + R_PCH_LPC_BC), (UINT8) ~B_PCH_LPC_BC_WPD);
+}
+
+/**
+ Entry point for Pch 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
+InstallPchBiosWriteProtect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ DEBUG ((DEBUG_INFO, "InstallPchBiosWriteProtect()\n"));
+
+ if (mPchConfigHob->LockDown.BiosLock != TRUE) {
+ return EFI_SUCCESS;
+ }
+
+ mSpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+
+ mLpcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ DEBUG ((DEBUG_INFO, "Installing BIOS Write Protect SMI handler\n"));
+
+ //
+ // Get the PCH TCO SMM dispatch protocol
+ //
+ mPchTcoSmiDispatchProtocol = NULL;
+ Status = gSmst->SmmLocateProtocol (&gPchTcoSmiDispatchProtocolGuid, NULL, (VOID **) &mPchTcoSmiDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Always register an SPI BiosWp callback function to handle TCO BIOSWR SMI
+ // NOTE: No matter the BIOS resides behind SPI or not, it needs to handle the SPI BIOS WP SMI
+ // to avoid SMI deadloop on SPI WPD write.
+ //
+ Handle = NULL;
+ Status = mPchTcoSmiDispatchProtocol->SpiBiosWpRegister (
+ mPchTcoSmiDispatchProtocol,
+ PchSpiBiosWpCallback,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register an LPC BiosWp callback function to handle TCO BIOSWR SMI
+ //
+ Handle = NULL;
+ Status = mPchTcoSmiDispatchProtocol->LpcBiosWpRegister (
+ mPchTcoSmiDispatchProtocol,
+ PchLpcBiosWpCallback,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchGpioSxIsolationSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchGpioSxIsolationSmm.c
new file mode 100644
index 0000000000..4c3dd6cf11
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchGpioSxIsolationSmm.c
@@ -0,0 +1,48 @@
+/** @file
+ PCH GPIO Sx Isolation Driver Entry
+
+Copyright (c) 2017, 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 that 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 "PchInitSmm.h"
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+
+/**
+ This function performs GPIO Sx Isolation for DevSlp pins.
+**/
+VOID
+PchGpioSxIsolationCallback (
+ VOID
+ )
+{
+ UINT32 SataPortsMax;
+ UINT32 SataPort;
+ GPIO_PAD DevSlpGpioPad;
+
+ SataPortsMax = GetPchMaxSataPortNum ();
+
+ //
+ // If DevSlp pad is used in its native mode then
+ // set PadRstCfg to 10'b (GPIO Reset)
+ //
+ for (SataPort = 0; SataPort < SataPortsMax; SataPort++) {
+ //
+ // Check if DevSlp pad is in native mode
+ //
+ if (GpioIsSataDevSlpPinEnabled (SataPort, &DevSlpGpioPad)) {
+ //
+ // Program PADCFG_DW0.PadRstCfg
+ //
+ GpioSetPadResetConfig (DevSlpGpioPad, GpioResetNormal);
+ }
+ }
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c
new file mode 100644
index 0000000000..c6e1809946
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c
@@ -0,0 +1,308 @@
+/** @file
+ PCH Init Smm module for PCH specific SMI handlers.
+
+Copyright (c) 2017, 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 that 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 "PchInitSmm.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *mPchIoTrap;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA *mPchNvsArea;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mAcpiBaseAddr;
+
+//
+// NOTE: The module variables of policy here are only valid in post time, but not runtime time.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_CONFIG_HOB *mPchConfigHob;
+GLOBAL_REMOVE_IF_UNREFERENCED SI_CONFIG_HOB *mSiConfigHob;
+
+//
+// The reserved MMIO range to be used in Sx handler
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS mResvMmioBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mResvMmioSize;
+//
+// The reserved MMIO range to be used by xHCI ASL code
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS mXhciMmioBaseAddr;
+
+/**
+ SMBUS Sx entry SMI handler.
+**/
+VOID
+SmbusSxCallback (
+ VOID
+ )
+{
+ UINTN SmbusRegBase;
+ UINT16 SmbusIoBase;
+
+ SmbusRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+
+ if (MmioRead32 (SmbusRegBase) == 0xFFFFFFFF) {
+ return;
+ }
+
+ SmbusIoBase = MmioRead16 (SmbusRegBase + R_PCH_SMBUS_BASE) & B_PCH_SMBUS_BASE_BAR;
+ if (SmbusIoBase == 0) {
+ return;
+ }
+
+ MmioOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_IO_SPACE);
+ //
+ // Clear SMBUS status and SMB_WAK_STS of GPE0
+ //
+ IoWrite8 (SmbusIoBase + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_SMBALERT_STS);
+ IoWrite32 (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96, B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK);
+}
+
+/**
+ 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
+ )
+{
+ PchGpioSxIsolationCallback ();
+ PchLanSxCallback ();
+
+ if (((EFI_SMM_SX_REGISTER_CONTEXT*)Context)->Type == SxS3) {
+ PchXhciS3Callback ();
+ }
+
+ SmbusSxCallback ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize PCH Sx entry SMI handler.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+**/
+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"));
+}
+
+/**
+ Allocates reserved MMIO for Sx SMI handler use.
+
+ This function is only called from entry point therefore DXE/boot Services can be used here.
+ Updates ACPI NVS location to reserve allocated MMIO range as system resource.
+**/
+VOID
+AllocateReservedMmio (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ PCH_NVS_AREA_PROTOCOL *PchNvsAreaProtocol;
+ EFI_STATUS Status;
+
+ mResvMmioSize = 1 << N_PCH_LAN_MBARA_ALIGN;
+
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ mResvMmioBaseAddr = 0xFFFFFFFF;
+ }
+ Status = gDS->AllocateMemorySpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdMemoryTypeMemoryMappedIo,
+ N_PCH_LAN_MBARA_ALIGN,
+ mResvMmioSize,
+ &mResvMmioBaseAddr,
+ ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "mResvMmioBaseAddr %x\n", mResvMmioBaseAddr));
+
+ //
+ // Locate the PCH shared data area and update reserved memory base address
+ //
+ Status = gBS->LocateProtocol (&gPchNvsAreaProtocolGuid, NULL, (VOID **) &PchNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ PchNvsAreaProtocol->Area->SxMemSize = (UINT32) mResvMmioSize;
+ PchNvsAreaProtocol->Area->SxMemBase = (UINT32) mResvMmioBaseAddr;
+
+ //
+ // Install and initialize all the needed protocols
+ //
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ mXhciMmioBaseAddr = 0xFFFFFFFF;
+ }
+ Status = gDS->AllocateMemorySpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdMemoryTypeMemoryMappedIo,
+ N_PCH_XHCI_MEM_ALIGN,
+ V_PCH_XHCI_MEM_LENGTH,
+ &mXhciMmioBaseAddr,
+ ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "mXhciMmioBaseAddr %x\n", mXhciMmioBaseAddr));
+
+ //
+ // Update XWMB, XHCI memory base address
+ //
+ PchNvsAreaProtocol->Area->XhciRsvdMemBase = (UINT32) mXhciMmioBaseAddr;
+}
+
+/**
+ 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_HOB and SI_POLICY_HOB 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, registers BIOS WP handler to process BIOSWP status,
+ and registers SPI Async SMI handler to handler SPI Async SMI.
+ This module also registers Sx SMI callback function to detail with GPIO Sx Isolation and LAN requirement.
+
+ - @pre
+ - PCH PCR base address configured
+ - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+ - EFI_SMM_BASE2_PROTOCOL
+ - EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL
+ - EFI_SMM_SX_DISPATCH2_PROTOCOL
+ - EFI_SMM_CPU_PROTOCOL
+ - @link _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_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
+
+ - <b>References</b>\n
+ - @link _PCH_POLICY PCH_POLICY_HOB @endlink.
+ - @link _SI_POLICY_STRUCT SI_POLICY_HOB @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
+PchInitSmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ PCH_NVS_AREA_PROTOCOL *PchNvsAreaProtocol;
+ EFI_PEI_HOB_POINTERS HobPtr;
+
+ DEBUG ((DEBUG_INFO, "PchInitSmmEntryPoint()\n"));
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmIoTrapDispatch2ProtocolGuid,
+ NULL,
+ (VOID **) &mPchIoTrap
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ NULL,
+ (VOID**) &mSxDispatch
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gPchNvsAreaProtocolGuid, NULL, (VOID **) &PchNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mPchNvsArea = PchNvsAreaProtocol->Area;
+
+ //
+ // Get PCH Data HOB.
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gPchConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mPchConfigHob = (PCH_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ HobPtr.Guid = GetFirstGuidHob (&gSiConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mSiConfigHob = (SI_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ PchAcpiBaseGet (&mAcpiBaseAddr);
+
+ AllocateReservedMmio (ImageHandle);
+
+ InitializeSxHandler (ImageHandle);
+
+ Status = InitializePchPcieSmm (ImageHandle, SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = InstallIoTrapPort61h (ImageHandle, SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = InstallPchBiosWriteProtect (ImageHandle, SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = InstallPchSpiAsyncSmiHandler ();
+ ASSERT_EFI_ERROR (Status);
+
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h
new file mode 100644
index 0000000000..58ef567cc0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h
@@ -0,0 +1,344 @@
+/** @file
+ Header file for PCH Init SMM Handler
+
+Copyright (c) 2017, 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 that 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 _PCH_INIT_SMM_H_
+#define _PCH_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/SmmSxDispatch2.h>
+#include <Protocol/SmmIoTrapDispatch2.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/HobLib.h>
+#include <Protocol/SmmCpu.h>
+
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/PchEspiLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Protocol/PchPcieSmiDispatch.h>
+#include <Protocol/PchTcoSmiDispatch.h>
+#include <Protocol/PchSmiDispatch.h>
+#include <Protocol/PchEspiSmiDispatch.h>
+#include <Protocol/PchSmmIoTrapControl.h>
+#include <Protocol/PchNvs.h>
+#include <Protocol/PcieIoTrap.h>
+#include <SiConfigHob.h>
+#include <PchConfigHob.h>
+
+extern EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *mPchIoTrap;
+extern EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
+
+extern PCH_NVS_AREA *mPchNvsArea;
+extern UINT16 mAcpiBaseAddr;
+
+extern EFI_PHYSICAL_ADDRESS mResvMmioBaseAddr;
+extern EFI_PHYSICAL_ADDRESS mXhciMmioBaseAddr;
+extern UINTN mResvMmioSize;
+
+//
+// NOTE: The module variables of policy here are only valid in post time, but not runtime time.
+//
+extern PCH_CONFIG_HOB *mPchConfigHob;
+extern SI_CONFIG_HOB *mSiConfigHob;
+
+#define EFI_PCI_CAPABILITY_ID_PCIPM 0x01
+
+#define DeviceD0 0x00
+#define DeviceD3 0x03
+
+typedef enum {
+ PciCfg,
+ PciMmr
+} PCH_PCI_ACCESS_TYPE;
+
+typedef enum {
+ Acpi,
+ Rcrb,
+ Tco
+} PCH_ACCESS_TYPE;
+
+typedef struct {
+ PCH_ACCESS_TYPE AccessType;
+ UINT32 Address;
+ UINT32 Data;
+ UINT32 Mask;
+ UINT8 Width;
+} PCH_SAVE_RESTORE_REG;
+
+typedef struct {
+ PCH_SAVE_RESTORE_REG* PchSaveRestoreReg;
+ UINT8 size;
+ PCH_SERIES PchSeries;
+} PCH_SAVE_RESTORE_REG_WRAP;
+
+struct _PCH_SAVE_RESTORE_PCI;
+
+typedef struct _PCH_SAVE_RESTORE_PCI{
+ PCH_PCI_ACCESS_TYPE AccessType;
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 BarOffset;
+ UINT16 Offset;
+ UINT32 Data;
+ UINT32 Mask;
+ UINT8 Width;
+ VOID (*RestoreFunction)(struct _PCH_SAVE_RESTORE_PCI *PchSaveRestorePci);
+} PCH_SAVE_RESTORE_PCI;
+
+typedef struct {
+ PCH_SAVE_RESTORE_PCI* PchSaveRestorePci;
+ UINT8 size;
+ PCH_SERIES PchSeries;
+} PCH_SAVE_RESTORE_PCI_WRAP;
+
+typedef struct {
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 PowerState;
+} DEVICE_POWER_STATE;
+
+VOID
+RestorePxDevSlp(
+ IN PCH_SAVE_RESTORE_PCI *PchSaveRestorePci
+ );
+
+/**
+ Register PCIE Hotplug SMI dispatch function to handle Hotplug enabling
+
+ @param[in] ImageHandle The image handle of this module
+ @param[in] SystemTable The EFI System Table
+
+ @retval EFI_SUCCESS The function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+InitializePchPcieSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ 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
+PchPcieSmi (
+ IN UINT8 PortIndex,
+ IN UINT8 RpDevice,
+ IN UINT8 RpFunction
+ );
+
+/**
+ PCIE Hotplug SMI call back function for each Root port
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieSmiRpHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ 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.
+**/
+VOID
+EFIAPI
+PchPcieLinkActiveStateChange (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_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.
+**/
+VOID
+EFIAPI
+PchPcieLinkEqHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ An IoTrap callback to config PCIE power management settings
+
+ @param[in] DispatchHandle - The handle of this callback, obtained when registering
+ @param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
+
+**/
+VOID
+PchPcieIoTrapSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_IO_TRAP_CONTEXT *CallbackContext,
+ 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
+PchInitLateSmm (
+ 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
+**/
+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
+PchSxHandler (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ );
+
+/**
+ xHCI S3 entry handler
+**/
+VOID
+PchXhciS3Callback (
+ VOID
+ );
+
+/**
+ GbE Sx entry handler
+**/
+VOID
+PchLanSxCallback (
+ VOID
+ );
+
+/**
+ This function performs GPIO Sx Isolation for DevSlp pins.
+**/
+VOID
+PchGpioSxIsolationCallback (
+ VOID
+ );
+
+/**
+ Register dispatch function to handle GPIO pads Sx isolation
+**/
+VOID
+InitializeGpioSxIsolationSmm (
+ VOID
+ );
+
+/**
+ Entry point for Pch 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
+InstallPchBiosWriteProtect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ This fuction install SPI ASYNC SMI handler.
+
+ @retval EFI_SUCCESS Initialization complete.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpiAsyncSmiHandler (
+ VOID
+ );
+
+
+
+
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf
new file mode 100644
index 0000000000..458eac090e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf
@@ -0,0 +1,107 @@
+## @file
+# Component description file for PchInitSmm driver
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PchInitSmm
+FILE_GUID = D7B10D4E-67E6-4C74-83E9-F9AF0ACC33CC
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = PchInitSmmEntryPoint
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+
+[LibraryClasses]
+UefiBootServicesTableLib
+UefiDriverEntryPoint
+DxeServicesTableLib
+IoLib
+DebugLib
+BaseLib
+BaseMemoryLib
+S3BootScriptLib
+PchPciExpressHelpersLib
+SmmServicesTableLib
+MmPciLib
+HobLib
+GpioLib
+GpioPrivateLib
+ReportStatusCodeLib
+DevicePathLib
+PchCycleDecodingLib
+PchPcieRpLib
+PchInfoLib
+TimerLib
+ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[Sources]
+PchInitSmm.c
+PchPcieSmm.c
+PchPort61hSmm.c
+PchGpioSxIsolationSmm.c
+PchLanSxSmm.c
+PchInitSmm.h
+PchBiosWriteProtect.c
+PchSpiAsync.c
+PchXhciSxSmm.c
+
+
+[Protocols]
+gEfiSmmIoTrapDispatch2ProtocolGuid ## CONSUMES
+gEfiSmmSxDispatch2ProtocolGuid ## CONSUMES
+gPchSmmIoTrapControlGuid ## CONSUMES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+gPchNvsAreaProtocolGuid ## CONSUMES
+gPchPcieSmiDispatchProtocolGuid ## CONSUMES
+gPchTcoSmiDispatchProtocolGuid ## CONSUMES
+gPchSmiDispatchProtocolGuid ## CONSUMES
+gPchEspiSmiDispatchProtocolGuid ## CONSUMES
+gPchPcieIoTrapProtocolGuid ## PRODUCES
+
+
+[Guids]
+gSiConfigHobGuid ## CONSUMES
+gPchConfigHobGuid ## CONSUMES
+gPchDeviceTableHobGuid
+
+
+[Depex]
+gEfiSmmIoTrapDispatch2ProtocolGuid AND
+gEfiSmmSxDispatch2ProtocolGuid AND
+gPchSmmIoTrapControlGuid AND
+gPchPcieSmiDispatchProtocolGuid AND
+gPchTcoSmiDispatchProtocolGuid AND
+gEfiSmmCpuProtocolGuid AND
+gPchNvsAreaProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND # This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiSmmBase2ProtocolGuid # This is for SmmServicesTableLib
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c
new file mode 100644
index 0000000000..d05cb61bbc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c
@@ -0,0 +1,415 @@
+/** @file
+ PCH LAN Sx handler implementation.
+
+Copyright (c) 2017, 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 that 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 <Library/TimerLib.h>
+#include "PchInitSmm.h"
+
+//
+// Maximum loop time for GbE status check
+//
+#define GBE_MAX_LOOP_TIME 4000
+
+/**
+ Checks if Lan is Enabled or Disabled
+
+ @retval BOOLEAN TRUE if device is enabled, FALSE otherwise.
+**/
+BOOLEAN
+IsGbeEnabled (
+ VOID
+ )
+{
+ UINTN GbePciBase;
+
+ GbePciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LAN,
+ PCI_FUNCTION_NUMBER_PCH_LAN
+ );
+
+ if (MmioRead32 (GbePciBase) != 0xFFFFFFFF) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+/**
+ Test for MDIO operation complete.
+
+ @param [in] GbeBar GbE MMIO space
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+**/
+EFI_STATUS
+GbeMdiWaitReady (
+ UINT32 GbeBar
+ )
+{
+ UINT32 Count;
+
+ for (Count = 0; Count < GBE_MAX_LOOP_TIME; ++Count) {
+ if (MmioRead32 (GbeBar + R_PCH_LAN_CSR_MDIC) & B_PCH_LAN_CSR_MDIC_RB) {
+ return EFI_SUCCESS;
+ }
+ MicroSecondDelay (50);
+ }
+ return EFI_TIMEOUT;
+}
+
+/**
+ Acquire MDIO software semaphore.
+
+ 1. Ensure that MBARA offset F00h [5] = 1b
+ 2. Poll MBARA offset F00h [5] up to 200ms
+
+ @param [in] GbeBar GbE MMIO space
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+**/
+EFI_STATUS
+GbeAcquireMdio (
+ IN UINT32 GbeBar
+ )
+{
+ UINT32 ExtCnfCtrl;
+ UINT32 Count;
+
+ MmioOr32 (GbeBar + R_PCH_LAN_CSR_EXTCNF_CTRL, B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG);
+ for (Count = 0; Count < GBE_MAX_LOOP_TIME; ++Count) {
+ ExtCnfCtrl = MmioRead32 (GbeBar + R_PCH_LAN_CSR_EXTCNF_CTRL);
+ if (ExtCnfCtrl & B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG) {
+ return EFI_SUCCESS;
+ }
+ MicroSecondDelay (50);
+ }
+ ASSERT (FALSE);
+ return EFI_TIMEOUT;
+}
+
+
+/**
+ Release MDIO software semaphore by clearing MBARA offset F00h [5]
+
+ @param [in] GbeBar GbE MMIO space
+**/
+VOID
+GbeReleaseMdio (
+ IN UINT32 GbeBar
+ )
+{
+ ASSERT (MmioRead32 (GbeBar + R_PCH_LAN_CSR_EXTCNF_CTRL) & B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG);
+ MmioAnd32 (GbeBar + R_PCH_LAN_CSR_EXTCNF_CTRL, (UINT32) ~B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG);
+ ASSERT ((MmioRead32 (GbeBar + R_PCH_LAN_CSR_EXTCNF_CTRL) & B_PCH_LAN_CSR_EXTCNF_CTRL_SWFLAG) == 0);
+}
+
+/**
+ Perform MDI write.
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] Data Value to write in lower 16bits, upper 16bit may contain opcode.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+GbeMdiWrite (
+ IN UINT32 GbeBar,
+ IN UINT32 Data
+ )
+{
+ MmioWrite32 (GbeBar + R_PCH_LAN_CSR_MDIC, Data | 0x04000000);
+ return GbeMdiWaitReady (GbeBar);
+}
+
+/**
+ Perform MDI read.
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] Command MDI command
+ @param [out] Data Value read
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+GbeMdiRead (
+ IN UINT32 GbeBar,
+ IN UINT32 Command,
+ OUT UINT16 *Data
+ )
+{
+ EFI_STATUS Status;
+ MmioWrite32 (GbeBar + R_PCH_LAN_CSR_MDIC, Command | 0x08000000);
+ Status = GbeMdiWaitReady (GbeBar);
+ *Data = (UINT16) MmioRead32 (GbeBar + R_PCH_LAN_CSR_MDIC);
+ return Status;
+}
+
+/**
+ Configure WOL during Sx entry.
+
+ @param [in] GbeBar GbE MMIO space
+**/
+VOID
+GbeWolWorkaround (
+ IN UINT32 GbeBar
+ )
+{
+ UINT32 RAL0;
+ UINT32 RAH0;
+ EFI_STATUS Status;
+ UINT16 Data16;
+
+ //
+ // System BIOS performs read from MBARA offset 5400h [31:0] and MBARA offset 5404h [31:0]
+ //
+ RAL0 = MmioRead32 (GbeBar + R_PCH_LAN_CSR_RAL);
+ RAH0 = MmioRead32 (GbeBar + R_PCH_LAN_CSR_RAH);
+
+ //
+ // Set MBARA offset 20h = 0x043f6400
+ //
+ Status = GbeMdiWrite (GbeBar, 0x043f6400);
+
+ //
+ // If timeout is reached, force MAC to SMB and try again
+ // Assert if failed on second attempt
+ //
+ if (Status == EFI_TIMEOUT) {
+ //
+ // Change Extended Device Control Register BIT 11 to 1 which
+ // forces the interface between the MAC and the Phy to be on SMBus.
+ // Cleared on the assertion of PCI reset.
+ //
+ MmioOr32 (GbeBar + R_PCH_LAN_CSR_CTRL_EXT, B_PCH_LAN_CSR_CTRL_EXT_FORCE_SMB);
+ Status = GbeMdiWrite (GbeBar, 0x043f6400);
+ }
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Wait 4 mSec
+ //
+ MicroSecondDelay (4000);
+
+ //
+ // Set MBARA offset 20h = 0x4310010
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310010);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4320000 or with
+ // the least significant word of MBARA offset 5400
+ //
+ Status = GbeMdiWrite (GbeBar, (0x04320000 | (RAL0 & 0xFFFF)));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4310011
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310011);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4320000 or with
+ // the most significant word of MBARA offset 5400
+ //
+ Status = GbeMdiWrite (GbeBar, (0x04320000 | (RAL0 >> 16)));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4310012
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310012);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4320000 or with
+ // the least significant word of MBARA offset 5404
+ //
+ Status = GbeMdiWrite (GbeBar, (0x04320000 | (RAH0 & B_PCH_LAN_CSR_RAH_RAH)));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4310013
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310013);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4328000
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04328000);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4310001
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310001);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x8320000
+ //
+ Status = GbeMdiRead (GbeBar, 0x08320000, &Data16);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x4320000 OR TEMP[15:0] OR 1
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04320000 | Data16 | BIT0);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x43f6460
+ //
+ Status = GbeMdiWrite (GbeBar, 0x043f6460);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Wait 4 mSec
+ //
+ MicroSecondDelay (4000);
+
+ //
+ // Set MBARA offset 20h = 0x4310042
+ //
+ Status = GbeMdiWrite (GbeBar, 0x04310042);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA offset 20h = 0x43F6020
+ //
+ Status = GbeMdiWrite (GbeBar, 0x043F6020);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Wait 4 mSec
+ //
+ MicroSecondDelay (4000);
+
+ //
+ // Set MBARA offset 20h = 0x8310000
+ // TEMP[15:0] = MBARA + 20[15:0]
+ //
+ Status = GbeMdiRead (GbeBar, 0x08310000, &Data16);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // Set MBARA + 20h = 4310000h or with the TEMP[15:0] OR 10h
+ //
+ GbeMdiWrite (GbeBar, 0x04310000 | Data16 | BIT4);
+}
+
+/**
+ Additional Internal GbE Controller special cases WOL Support.
+
+ System BIOS is required perform additional steps upon S0 to S3,4,5 transition
+ when ME is off and GbE device in D0. This is needed to enable LAN wake
+ in particular when platform is shut-down from EFI.
+**/
+VOID
+GbeSxWorkaround (
+ VOID
+ )
+{
+ UINTN LanRegBase;
+ UINT32 GbeBar;
+ EFI_STATUS Status;
+
+ LanRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LAN,
+ PCI_FUNCTION_NUMBER_PCH_LAN
+ );
+
+ if (MmioRead16 (LanRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return;
+ }
+
+ //
+ // Check if GbE device is in D0
+ //
+ if ((MmioRead16 (LanRegBase + R_PCH_LAN_PMCS) & B_PCH_LAN_PMCS_PS) != V_PCH_LAN_PMCS_PS0) {
+ return;
+ }
+
+ ASSERT (mResvMmioSize >= (1 << N_PCH_LAN_MBARA_ALIGN));
+ GbeBar = (UINT32) mResvMmioBaseAddr;
+ if (GbeBar == 0) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Enable MMIO decode using reserved range.
+ //
+ MmioAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (LanRegBase + R_PCH_LAN_MBARA, GbeBar);
+ MmioOr16 (LanRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ //
+ // If MBARA offset 5800h [0] = 1b then proceed with the w/a
+ //
+ if (MmioRead32 (GbeBar + R_PCH_LAN_CSR_WUC) & B_PCH_LAN_CSR_WUC_APME) {
+ Status = GbeAcquireMdio (GbeBar);
+ ASSERT_EFI_ERROR (Status);
+ if (!EFI_ERROR (Status)) {
+ GbeWolWorkaround (GbeBar);
+ GbeReleaseMdio (GbeBar);
+ }
+ }
+
+ //
+ // Disable MMIO decode.
+ //
+ MmioAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (LanRegBase + R_PCH_LAN_MBARA, 0);
+}
+
+/**
+ Enable platform wake from LAN when in DeepSx if platform supports it.
+ Called upon Sx entry.
+**/
+VOID
+GbeConfigureDeepSxWake (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ if ((MmioRead32 (PchPwrmBase + R_PCH_PWRM_DSX_CFG) & (UINT32) B_PCH_PWRM_DSX_CFG_LAN_WAKE_EN) != 0) {
+ IoOr32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_EN_127_96), (UINT32) B_PCH_ACPI_GPE0_EN_127_96_LAN_WAKE);
+ }
+}
+
+/**
+ GbE Sx entry handler
+**/
+VOID
+PchLanSxCallback (
+ VOID
+ )
+{
+ if (IsGbeEnabled ()) {
+ GbeSxWorkaround ();
+ GbeConfigureDeepSxWake ();
+
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c
new file mode 100644
index 0000000000..b4234f649c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c
@@ -0,0 +1,464 @@
+/** @file
+ PCH Pcie SMM Driver Entry
+
+Copyright (c) 2017, 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 that 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 "PchInitSmm.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_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 PCH_PCIE_ROOT_PORT_CONFIG mPcieRootPortConfig[PCH_MAX_PCIE_ROOT_PORTS];
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mLtrNonSupportRpBitMap;
+
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mPciePmTrapExecuted = FALSE;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mAllowNoLtrIccPllShutdownPolicy = FALSE;
+
+extern EFI_GUID gPchDeviceTableHobGuid;
+
+
+/**
+ 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
+PchPcieSmi (
+ IN UINT8 PortIndex,
+ IN UINT8 RpDevice,
+ IN UINT8 RpFunction
+ )
+{
+ UINT8 SecBus;
+ UINT8 SubBus;
+ EFI_HANDLE Handle;
+ UINT32 PwrmBase;
+ UINTN RpBase;
+ BOOLEAN LtrSupported;
+ BOOLEAN DownstreamDevicePresent;
+
+ Handle = NULL;
+ LtrSupported = TRUE;
+
+ RpBase = MmPciBase (
+ mPchBusNumber,
+ (UINT32) RpDevice,
+ (UINT32) RpFunction
+ );
+
+ if (MmioRead16 (RpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Check for presence detect state
+ //
+ DownstreamDevicePresent = !!(MmioRead16 (RpBase + R_PCH_PCIE_SLSTS) & B_PCIE_SLSTS_PDS);
+
+ mLtrNonSupportRpBitMap &= ~(1 << PortIndex);
+
+ if (DownstreamDevicePresent) {
+ SecBus = MmioRead8 (RpBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ SubBus = MmioRead8 (RpBase + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ ASSERT (SecBus != 0 && SubBus != 0);
+ PchPcieInitRootPortDownstreamDevices (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ RpDevice,
+ RpFunction,
+ mTempRootPortBusNumMin,
+ mTempRootPortBusNumMax,
+ (BOOLEAN)mPcieRootPortConfig[PortIndex].EnableCpm
+ );
+ if (!LtrSupported) {
+ mLtrNonSupportRpBitMap |= 1 << PortIndex;
+ }
+
+ //
+ // Perform Equalization
+ //
+ MmioOr32 (RpBase + R_PCH_PCIE_EX_LCTL3, B_PCIE_EX_LCTL3_PE);
+ MmioOr32 (RpBase + R_PCH_PCIE_LCTL, B_PCIE_LCTL_RL);
+ }
+
+ //
+ // If not all devices support LTR, set PWRMBASE + 0x3EC [24,16] = 0, 1
+ // This will disable ICC PLL shutdown
+ //
+ if (!mAllowNoLtrIccPllShutdownPolicy) {
+ PchPwrmBaseGet (&PwrmBase);
+ if (mLtrNonSupportRpBitMap != 0) {
+ MmioAndThenOr32 (PwrmBase + R_PCH_PWRM_CS_SD_CTL2, (UINT32) ~BIT24, BIT16);
+ } else {
+ MmioAnd32 (PwrmBase + R_PCH_PWRM_CS_SD_CTL2, (UINT32) ~(BIT24 | BIT16));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ PCIE Hotplug SMI call back function for each Root port
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieSmiRpHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ PchPcieSmi (RpContext->RpIndex, RpContext->DevNum, RpContext->FuncNum);
+}
+
+/**
+ 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.
+**/
+VOID
+EFIAPI
+PchPcieLinkActiveStateChange (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_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.
+**/
+VOID
+EFIAPI
+PchPcieLinkEqHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ ///
+ /// From PCI Express specification, the PCIe device can request for Link Equalization. When the
+ /// Link Equalization is requested by the device, an SMI will be generated by PCIe RP when
+ /// enabled and the SMI subroutine would invoke the Software Preset/Coefficient Search
+ /// software to re-equalize the link.
+ ///
+
+ return;
+
+}
+
+
+/**
+ An IoTrap callback to config PCIE power management settings
+**/
+VOID
+PchPciePmIoTrapSmiCallback (
+ VOID
+ )
+{
+ UINT32 PwrmBase;
+ UINT32 PortIndex;
+ UINTN RpBase;
+ BOOLEAN L1SubstatesSupportedPerPort;
+ UINT8 MaxPciePortNum;
+ UINTN RpDevice;
+ UINTN RpFunction;
+ PCH_GENERATION PchGen;
+ PCH_SERIES PchSeries;
+ PCH_STEPPING PchStep;
+
+ PchGen = GetPchGeneration ();
+ PchSeries = GetPchSeries ();
+ PchStep = PchStepping ();
+ L1SubstatesSupportedPerPort = FALSE;
+ MaxPciePortNum = GetPchMaxPciePortNum ();
+
+ //
+ // Step 4a
+ // In case not all devices support LTR, disable ICC PLL shutdown
+ // set PWRMBASE + 0x3EC [24,16] = 0, 1
+ // (Note this register should be saved and restored during S3 transitions)
+ //
+ if (!mAllowNoLtrIccPllShutdownPolicy) {
+ PchPwrmBaseGet (&PwrmBase);
+ MmioAndThenOr32 (PwrmBase + R_PCH_PWRM_CS_SD_CTL2, (UINT32) ~BIT24, BIT16);
+ }
+
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
+ GetPchPcieRpDevFun (PortIndex, &RpDevice, &RpFunction);
+ RpBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDevice, (UINT32) RpFunction);
+ }
+ //
+ // Step 4b
+ // By this time, LTR support map is known.
+ // If all devices support LTR, allow ICC PLL shutdown
+ // (Note this register should be saved and restored during S3 transitions)
+ //
+ if (!mAllowNoLtrIccPllShutdownPolicy) {
+ if (mLtrNonSupportRpBitMap == 0) {
+ PchPwrmBaseGet (&PwrmBase);
+ MmioAnd32 (PwrmBase + R_PCH_PWRM_CS_SD_CTL2, (UINT32) ~(BIT24 | BIT16));
+ }
+ }
+
+ //
+ // Program the remapped root port's ASPM based on endpoint's ASPM
+ //
+ if ((PchGen == SklPch) &&
+ (((PchSeries == PchLp) && (PchStep < PchLpC0)) ||
+ ((PchSeries == PchH) && (PchStep < PchHD0)))) {
+ return;
+ }
+}
+
+/**
+ An IoTrap callback to config PCIE power management settings
+
+ @param[in] DispatchHandle - The handle of this callback, obtained when registering
+ @param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
+
+**/
+VOID
+PchPcieIoTrapSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_IO_TRAP_CONTEXT *CallbackContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ if (CallbackContext->WriteData == PciePmTrap) {
+ if (mPciePmTrapExecuted == FALSE) {
+ PchPciePmIoTrapSmiCallback ();
+ mPciePmTrapExecuted = 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
+
+ @retval EFI_SUCCESS PCH register saved
+**/
+EFI_STATUS
+EFIAPI
+PchPcieS3EntryCallBack (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ mPciePmTrapExecuted = 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
+InitializePchPcieSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT8 PortIndex;
+ UINT8 Data8;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINTN RpBase;
+ UINTN RpDevice;
+ UINTN RpFunction;
+ EFI_HANDLE PcieHandle;
+ PCH_PCIE_SMI_DISPATCH_PROTOCOL *PchPcieSmiDispatchProtocol;
+ EFI_HOB_GUID_TYPE* Hob;
+ UINT32 DevTableSize;
+ EFI_HANDLE PchIoTrapHandle;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT PchIoTrapContext;
+ EFI_SMM_SX_REGISTER_CONTEXT SxDispatchContext;
+ PCH_PCIE_IOTRAP_PROTOCOL *PchPcieIoTrapProtocol;
+ EFI_HANDLE SxDispatchHandle;
+ UINT8 MaxPciePortNum;
+
+ DEBUG ((DEBUG_INFO, "InitializePchPcieSmm () Start\n"));
+
+ MaxPciePortNum = GetPchMaxPciePortNum ();
+
+ //
+ // Locate Pch Pcie Smi Dispatch Protocol
+ //
+ Status = gSmst->SmmLocateProtocol (&gPchPcieSmiDispatchProtocolGuid, NULL, (VOID**)&PchPcieSmiDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ mPolicyRevision = mSiConfigHob->Header.Revision;
+ mPchBusNumber = DEFAULT_PCI_BUS_NUMBER_PCH;
+ mTempRootPortBusNumMin = mSiConfigHob->TempPciBusMin;
+ mTempRootPortBusNumMax = mSiConfigHob->TempPciBusMax;
+ mAllowNoLtrIccPllShutdownPolicy = (BOOLEAN) mPchConfigHob->PcieRp.AllowNoLtrIccPllShutdown;
+
+ ASSERT (sizeof mPcieRootPortConfig == sizeof mPchConfigHob->PcieRp.RootPort);
+ CopyMem (
+ mPcieRootPortConfig,
+ &(mPchConfigHob->PcieRp.RootPort),
+ sizeof (mPcieRootPortConfig)
+ );
+
+ mDevAspmOverride = NULL;
+ mNumOfDevAspmOverride = 0;
+ mLtrNonSupportRpBitMap = 0;
+
+ Hob = GetFirstGuidHob (&gPchDeviceTableHobGuid);
+ if (Hob != NULL) {
+ DevTableSize = GET_GUID_HOB_DATA_SIZE (Hob);
+ ASSERT ((DevTableSize % sizeof (PCH_PCIE_DEVICE_OVERRIDE)) == 0);
+ mNumOfDevAspmOverride = DevTableSize / sizeof (PCH_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);
+ }
+
+ //
+ // Throught all PCIE root port function and register the SMI Handler for enabled ports.
+ //
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
+ GetPchPcieRpDevFun (PortIndex, &RpDevice, &RpFunction);
+ RpBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDevice, (UINT32) RpFunction);
+ //
+ // Skip the root port function which is not enabled
+ //
+ if (MmioRead32 (RpBase) == 0xFFFFFFFF) {
+ continue;
+ }
+
+ if (!mPcieRootPortConfig[PortIndex].EnableHotplugSmi) {
+ continue;
+ }
+ //
+ // Register SMI Handlers for Hot Plug and Link Active State Change
+ //
+ Data8 = MmioRead8 (RpBase + R_PCH_PCIE_SLCAP);
+ if (Data8 & B_PCIE_SLCAP_HPC) {
+ PcieHandle = NULL;
+ Status = PchPcieSmiDispatchProtocol->HotPlugRegister (
+ PchPcieSmiDispatchProtocol,
+ PchPcieSmiRpHandlerFunction,
+ PortIndex,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PchPcieSmiDispatchProtocol->LinkActiveRegister (
+ PchPcieSmiDispatchProtocol,
+ PchPcieLinkActiveStateChange,
+ PortIndex,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Data32Or = B_PCH_PCIE_MPC_HPME;
+ Data32And = (UINT32) ~B_PCH_PCIE_MPC_HPME;
+ S3BootScriptSaveMemReadWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (RpBase + R_PCH_PCIE_MPC),
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+ }
+
+ //
+ // Register SMI Handler for Link Equalization Request from Gen 3 Devices.
+ //
+ Data8 = MmioRead8 (RpBase + R_PCH_PCIE_LCAP);
+ if ((Data8 & B_PCIE_LCAP_MLS) == V_PCIE_LCAP_MLS_GEN3) {
+ Status = PchPcieSmiDispatchProtocol->LinkEqRegister (
+ PchPcieSmiDispatchProtocol,
+ PchPcieLinkEqHandlerFunction,
+ PortIndex,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ ASSERT_EFI_ERROR (Status);
+
+ PchIoTrapContext.Type = WriteTrap;
+ PchIoTrapContext.Length = 4;
+ PchIoTrapContext.Address = 0;
+ Status = mPchIoTrap->Register (
+ mPchIoTrap,
+ (EFI_SMM_HANDLER_ENTRY_POINT2) PchPcieIoTrapSmiCallback,
+ &PchIoTrapContext,
+ &PchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the PCH Pcie IoTrap protocol
+ //
+ (gBS->AllocatePool) (EfiBootServicesData, sizeof (PCH_PCIE_IOTRAP_PROTOCOL), (VOID **)&PchPcieIoTrapProtocol);
+ PchPcieIoTrapProtocol->PcieTrapAddress = PchIoTrapContext.Address;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gPchPcieIoTrapProtocolGuid,
+ PchPcieIoTrapProtocol,
+ NULL
+ );
+
+ //
+ // Register the callback for S3 entry
+ //
+ SxDispatchContext.Type = SxS3;
+ SxDispatchContext.Phase = SxEntry;
+ Status = mSxDispatch->Register (
+ mSxDispatch,
+ PchPcieS3EntryCallBack,
+ &SxDispatchContext,
+ &SxDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "InitializePchPcieSmm () End\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPort61hSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPort61hSmm.c
new file mode 100644
index 0000000000..0717f38291
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchPort61hSmm.c
@@ -0,0 +1,160 @@
+/** @file
+ PCH Port 61h bit-4 toggling in SMM IO Trap
+
+Copyright (c) 2017, 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 that 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 "PchInitSmm.h"
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpu; ///< To read and write save state
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mPchIoTrapHandle; ///< Pause and resume via EFI_HANDLE
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_IO_TRAP_CONTROL_PROTOCOL *mPchSmmIoTrapControl; ///< To pause and resume IO trap
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mInternalState = 0; ///< To store the toggle value for each CPU threads
+
+/**
+ This SMI handle will pause the IO trap in the beginning
+
+ @param[in] DispatchHandle - The handle of this callback, obtained when registering
+ @param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
+
+ @retval None
+**/
+VOID
+PchIoTrapPort61hSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *CallbackContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN CpuIndex;
+ UINTN Mask;
+ UINT8 ReadValue, WriteValue;
+ EFI_SMM_SAVE_STATE_IO_INFO IoInfo;
+ //
+ // Disabling the IO Trap, prevent SMI re-enter because of reading port 61h in handler itself
+ //
+ Status = mPchSmmIoTrapControl->Pause (
+ mPchSmmIoTrapControl,
+ mPchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Detects the CPU which causes the IO Trap
+ //
+ for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {
+ Status = mSmmCpu->ReadSaveState (
+ mSmmCpu,
+ sizeof (EFI_SMM_SAVE_STATE_IO_INFO),
+ EFI_SMM_SAVE_STATE_REGISTER_IO,
+ CpuIndex,
+ &IoInfo
+ );
+ if (Status == EFI_SUCCESS) {
+ //
+ // Make sure the IO trap is byte read, port input only, and it is port 0x61
+ //
+ if ((IoInfo.IoWidth == EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8) &&
+ (IoInfo.IoType == EFI_SMM_SAVE_STATE_IO_TYPE_INPUT) &&
+ (IoInfo.IoPort == 0x61)) {
+ //
+ // Read from Port 61h, toggle bit4 based on the internal state
+ //
+ ReadValue = IoRead8 (0x61);
+ Mask = (UINTN) (1 << CpuIndex);
+ mInternalState ^= Mask;
+ WriteValue = (mInternalState & Mask) ? (ReadValue | 0x10) : (ReadValue & ~0x10);
+ Status = mSmmCpu->WriteSaveState (
+ mSmmCpu,
+ sizeof (UINT8),
+ EFI_SMM_SAVE_STATE_REGISTER_RAX,
+ CpuIndex,
+ &WriteValue
+ );
+ ASSERT_EFI_ERROR (Status);
+ } //if the iotrap is the one we want
+ } //if iotrap happens for this thread
+ } //for (iterate for all threads)
+
+ //
+ // Resume the IO Trap
+ // Port 61h bit-4 emulation will be disabled after exit boot service
+ // The disabling mechanism is actually to not resume the trap.
+ // This means, even after exit boot service, this handler will be called once
+ // before it is disabled
+ //
+ if (mPchNvsArea->ExitBootServicesFlag == 0) {
+ Status = mPchSmmIoTrapControl->Resume (
+ mPchSmmIoTrapControl,
+ mPchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ DEBUG ((DEBUG_INFO, "Port61H trap has been disabled. \n"));
+ }
+}
+
+
+/**
+ Locate required protocol and register the IO trap in this entry point
+
+ @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
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT PchIoTrapContext;
+
+ DEBUG ((DEBUG_INFO, "InstallIoTrapPort61h()\n"));
+
+ if (mPchConfigHob->Port61hSmm.Enable == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Locate the protocol to read and write save state
+ //
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Locate the protocol for pause and resume
+ //
+ Status = gSmst->SmmLocateProtocol (&gPchSmmIoTrapControlGuid, NULL, (VOID **) &mPchSmmIoTrapControl);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Configure trap type, in ECP, MergeDisable should be TRUE for pause and resume to work
+ //
+ PchIoTrapContext.Type = ReadTrap;
+ PchIoTrapContext.Length = 1;
+ PchIoTrapContext.Address = 0x61;
+ Status = mPchIoTrap->Register (
+ mPchIoTrap,
+ (EFI_SMM_HANDLER_ENTRY_POINT2) PchIoTrapPort61hSmiCallback,
+ &PchIoTrapContext,
+ &mPchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c
new file mode 100644
index 0000000000..463de1dba8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c
@@ -0,0 +1,74 @@
+/** @file
+ PCH SPI Async SMI handler.
+
+Copyright (c) 2017, 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 that 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 "PchInitSmm.h"
+
+///
+/// Global variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMI_DISPATCH_PROTOCOL *mPchSmiDispatchProtocol;
+
+/**
+ This hardware SMI handler will be run every time the flash write/earse happens.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+PchSpiAsyncCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ //
+ // Dummy SMI handler
+ //
+}
+
+/**
+ This fuction install SPI ASYNC SMI handler.
+
+ @retval EFI_SUCCESS Initialization complete.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpiAsyncSmiHandler (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ DEBUG ((DEBUG_INFO, "InstallPchSpiAsyncSmiHandler()\n"));
+
+ ///
+ /// Get the PCH SMM dispatch protocol
+ ///
+ mPchSmiDispatchProtocol = NULL;
+ Status = gSmst->SmmLocateProtocol (&gPchSmiDispatchProtocolGuid, NULL, (VOID **) &mPchSmiDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Register an SpiAsync callback function
+ ///
+ Handle = NULL;
+ Status = mPchSmiDispatchProtocol->SpiAsyncRegister (
+ mPchSmiDispatchProtocol,
+ PchSpiAsyncCallback,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchXhciSxSmm.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchXhciSxSmm.c
new file mode 100644
index 0000000000..f17b125d4f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchInit/Smm/PchXhciSxSmm.c
@@ -0,0 +1,73 @@
+/** @file
+ PCH xHCI Sx handler implementation.
+
+Copyright (c) 2017, 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 that 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 <Library/TimerLib.h>
+#include "PchInitSmm.h"
+
+/**
+ xHCI Controller Configurations Prior to Entering S3
+**/
+VOID
+PchXhciS3Callback (
+ VOID
+ )
+{
+ UINTN XhciPciMmBase;
+ UINT8 OrgCmdByte;
+ UINT16 OrgPmcs;
+ UINT32 OrgMmioAddr;
+ UINT32 OrgMmioHAddr;
+ UINT32 XhciMmioBase;
+
+ XhciPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PCI_FUNCTION_NUMBER_PCH_XHCI
+ );
+
+ ///
+ /// Save Cmd and XhciBar and Pmcs registers
+ ///
+ OrgCmdByte = MmioRead8 (XhciPciMmBase + PCI_COMMAND_OFFSET);
+ OrgPmcs = MmioRead16 (XhciPciMmBase + R_PCH_XHCI_PWR_CNTL_STS);
+ OrgMmioAddr = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE) & 0xFFFF0000;
+ OrgMmioHAddr = MmioRead32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE + 4);
+
+ ///
+ /// Use the reserved MMIO
+ /// Clear MSE before changing MMIO address
+ ///
+ MmioAnd8 (XhciPciMmBase + PCI_COMMAND_OFFSET, (UINT8)~(EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE, (UINT32) mXhciMmioBaseAddr);
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE + 4, 0);
+
+ ///
+ /// Set MSE
+ ///
+ MmioOr8 (XhciPciMmBase + PCI_COMMAND_OFFSET, (EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
+
+ XhciMmioBase = (UINT32) mXhciMmioBaseAddr;
+
+ ///
+ /// Restore Cmd and XhciBar and Pmcs registers
+ ///
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE + 4, OrgMmioHAddr);
+ MmioWrite32 (XhciPciMmBase + R_PCH_XHCI_MEM_BASE, OrgMmioAddr);
+ MmioWrite8 (XhciPciMmBase + PCI_COMMAND_OFFSET, OrgCmdByte);
+ ///
+ /// Bring device to D3
+ ///
+ MmioOr8 (XhciPciMmBase + R_PCH_XHCI_PWR_CNTL_STS, (UINT8)(V_PCH_XHCI_PWR_CNTL_STS_PWR_STS_D3));
+
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c
new file mode 100644
index 0000000000..5c3ea07646
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c
@@ -0,0 +1,913 @@
+/** @file
+ Main implementation source file for the Io Trap SMM driver
+
+Copyright (c) 2017, 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 that 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 "PchSmmHelpers.h"
+#include <Protocol/PchNvs.h>
+
+#define GENERIC_IOTRAP_SIZE 0x100
+
+//
+// Module global variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mDriverImageHandle;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mIoTrapHandle;
+
+GLOBAL_REMOVE_IF_UNREFERENCED IO_TRAP_INSTANCE mIoTrapData;
+GLOBAL_REMOVE_IF_UNREFERENCED IO_TRAP_RECORD *mIoTrapRecord;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA *mPchNvsArea;
+
+
+static CONST UINT16 mLengthTable[10] = { 1, 2, 3, 4, 8, 16, 32, 64, 128, 256 };
+
+/**
+ Helper function that encapsulates IoTrap register access.
+ IO trap related register updates must be made in 2 registers, IOTRAP and DMI source decode.
+
+ @param[in] TrapHandlerNum trap number (0-3)
+ @param[in] Value value to be written in both registers
+ @param[in] SaveToBootscript if true, this register write will be saved to bootscript
+
+**/
+VOID
+SetIoTrapLowDword (
+ IN UINT8 TrapHandlerNum,
+ IN UINT32 Value,
+ IN BOOLEAN SaveToBootscript
+ )
+{
+ PchPcrWrite32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, Value);
+ PchPcrWrite32 (PID_DMI, R_PCH_PCR_DMI_IOT1 + TrapHandlerNum * 8, Value);
+ if (SaveToBootscript) {
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, 1, &Value);
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_DMI, R_PCH_PCR_DMI_IOT1 + TrapHandlerNum * 8, 1, &Value);
+ }
+}
+
+/**
+ Helper function that encapsulates IoTrap register access.
+ IO trap related register updates must be made in 2 registers, IOTRAP and DMI source decode.
+
+ @param[in] TrapHandlerNum trap number (0-3)
+ @param[in] Value value to be written in both registers
+ @param[in] SaveToBootscript if true, this register write will be saved to bootscript
+
+**/
+VOID
+SetIoTrapHighDword (
+ IN UINT8 TrapHandlerNum,
+ IN UINT32 Value,
+ IN BOOLEAN SaveToBootscript
+ )
+{
+ PchPcrWrite32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8 + 4, Value);
+ PchPcrWrite32 (PID_DMI, R_PCH_PCR_DMI_IOT1 + TrapHandlerNum * 8 + 4, Value);
+ if (SaveToBootscript) {
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8 + 4, 1, &Value);
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_DMI, R_PCH_PCR_DMI_IOT1 + TrapHandlerNum * 8 + 4, 1, &Value);
+ }
+}
+
+/**
+ IO resources allocated to IO traps need to be reported to OS so that they don't get reused.
+ This function makes IO trap allocation data available to ACPI
+
+ @param[in] TrapHandlerNum trap number (0-3)
+ @param[in] BaseAddress address of allocated IO resource
+ @param[in] Track TRUE = resource allocated, FALSE = resource freed
+
+**/
+VOID
+UpdateIoTrapAcpiResources (
+ IN UINT8 TrapHandlerNum,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN BOOLEAN Track
+ )
+{
+
+ if (Track == TRUE) {
+ mPchNvsArea->IoTrapAddress[TrapHandlerNum] = (UINT16) BaseAddress;
+ mPchNvsArea->IoTrapStatus[TrapHandlerNum] = 1;
+ } else {
+ mPchNvsArea->IoTrapStatus[TrapHandlerNum] = 0;
+ }
+}
+
+/**
+ Register a new IO Trap SMI dispatch function with a parent SMM driver.
+ The caller will provide information about the IO trap characteristics via
+ the context. This includes base address, length, read vs. r/w, etc.
+ This function will autoallocate IO base address from a common pool if the base address is 0,
+ and the RegisterContext Address field will be updated.
+ The service will not perform GCD allocation if the base address is non-zero.
+ In this case, the caller is responsible for the existence and allocation of the
+ specific IO range.
+ This function looks for the suitable handler and Register a new IoTrap handler
+ if the IO Trap handler is not used. It also enable the IO Trap Range to generate
+ SMI.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source.
+ @param[in, out] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the IO trap SMI source for which the dispatch
+ function should be invoked. This may not be NULL.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record. This may not be NULL.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources are available
+ @retval EFI_INVALID_PARAMETER Address requested is already in use.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN OUT EFI_SMM_IO_TRAP_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS NextBaseAddress;
+ UINT32 NextUsedLength;
+ UINT8 NextTrapHandlerNum;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ UINT8 LengthIndex;
+ BOOLEAN TempMergeDisable;
+
+ //
+ // Return error if the type is invalid
+ //
+ if (RegisterContext->Type >= IoTrapTypeMaximum) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch Type %0X is invalid! \n", RegisterContext->Type));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Return error if the Length is invalid
+ //
+ if (RegisterContext->Length < 1 || RegisterContext->Length > GENERIC_IOTRAP_SIZE) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch Length %0X is invalid! \n", RegisterContext->Length));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Return error if the address is invalid
+ // PCH supports non-aligned address but (Address % 4 + Length) must not be more than 4
+ //
+ if (((RegisterContext->Length & (RegisterContext->Length - 1)) != 0) && (RegisterContext->Length != 3)) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch Length is not power of 2 \n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((RegisterContext->Length >= 4) && (RegisterContext->Address & 0x3)) ||
+ ((RegisterContext->Length < 4) && (((RegisterContext->Address & 0x3) + RegisterContext->Length) > 4))) {
+ DEBUG ((DEBUG_ERROR, "PCH does not support Dispatch Address %0X and Length %0X combination \n", RegisterContext->Address, RegisterContext->Length));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((RegisterContext->Length >= 4) && ((RegisterContext->Address & (RegisterContext->Length - 1)) != 0)) {
+ DEBUG ((DEBUG_ERROR, "Dispatch Address %0X is not aligned to the Length %0X \n", RegisterContext->Address, RegisterContext->Length));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (RegisterContext->Address) {
+ TempMergeDisable = TRUE;
+ }else {
+ TempMergeDisable = FALSE;
+ }
+ //
+ // Loop through the first IO Trap handler, looking for the suitable handler
+ //
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // Get information from Io Trap handler register
+ //
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, &IoTrapRegLowDword);
+
+ //
+ // Check if the IO Trap handler is not used
+ //
+ if ((IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD) == 0) {
+ //
+ // Search available IO address and allocate it if the IO address is 0
+ //
+ BaseAddress = RegisterContext->Address;
+ if (BaseAddress == 0) {
+ //
+ // Allocate 256 byte range from GCD for common pool usage
+ //
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ BaseAddress = 0xFFFF;
+ }
+ Status = gDS->AllocateIoSpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdIoTypeIo,
+ 8,
+ GENERIC_IOTRAP_SIZE,
+ &BaseAddress,
+ mDriverImageHandle,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Can't find any available IO address! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RegisterContext->Address = (UINT16) BaseAddress;
+ UsedLength = GENERIC_IOTRAP_SIZE;
+ mIoTrapData.TrapUsedLength[TrapHandlerNum] = RegisterContext->Length;
+ mIoTrapData.TrackIoResource[TrapHandlerNum] = TRUE;
+ UpdateIoTrapAcpiResources (TrapHandlerNum, BaseAddress, TRUE);
+ } else {
+ BaseAddress &= B_PCH_PCR_PSTH_TRPREG_AD;
+ UsedLength = RegisterContext->Length;
+ }
+
+ //
+ // Register a new IoTrap handler
+ //
+ Status = PchInternalIoTrapSmiRegister (
+ IoTrapCallback,
+ TrapHandlerNum,
+ &mIoTrapHandle
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ mIoTrapData.IoTrapHandle[TrapHandlerNum] = mIoTrapHandle;
+ //
+ // Fill in the Length, address and Enable the IO Trap SMI
+ //
+ IoTrapRegLowDword = (UINT32) (((UsedLength - 1) & ~(BIT1 + BIT0)) << 16) |
+ (UINT16) BaseAddress |
+ B_PCH_PCR_PSTH_TRPREG_TSE;
+ if (UsedLength < 4) {
+ //
+ // The 4 bits is the Byte Enable Mask bits to indicate which byte that are trapped.
+ //
+ IoTrapRegHighDword = (((1 << UsedLength) - 1) << ((RegisterContext->Address & 0x3) + N_PCH_PCR_PSTH_TRPREG_BEM)) |
+ (UINT32) (RegisterContext->Type << N_PCH_PCR_PSTH_TRPREG_RWIO);
+ } else {
+ IoTrapRegHighDword = 0x000000F0 | (UINT32) (RegisterContext->Type << N_PCH_PCR_PSTH_TRPREG_RWIO);
+ }
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, TRUE);
+ SetIoTrapHighDword (TrapHandlerNum, IoTrapRegHighDword, TRUE);
+ //
+ // Set MergeDisable flag of the registered IoTrap
+ //
+ mIoTrapData.MergeDisable[TrapHandlerNum] = TempMergeDisable;
+ } else {
+ //
+ // Check next handler if MergeDisable is TRUE or the registered IoTrap if MergeDisable is TRUE
+ //
+ if ((TempMergeDisable == TRUE) || (mIoTrapData.MergeDisable[TrapHandlerNum] == TRUE)) {
+ continue;
+ }
+ //
+ // The IO Trap handler is used, calculate the Length
+ //
+ UsedLength = ((IoTrapRegLowDword >> 16) & 0xFC) + 4;
+ BaseAddress = IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD;
+ //
+ // Assign an addfress from common pool if the caller's address is 0
+ //
+ if (RegisterContext->Address == 0) {
+ //
+ // Check next handler if it's fully used
+ //
+ if (mIoTrapData.TrapUsedLength[TrapHandlerNum] >= GENERIC_IOTRAP_SIZE) {
+ continue;
+ }
+ //
+ // Check next handler if it's not for a common pool
+ //
+ if (UsedLength < GENERIC_IOTRAP_SIZE) {
+ continue;
+ }
+ //
+ // Check next handler if the size is too big
+ //
+ if (RegisterContext->Length >= (UINT16) GENERIC_IOTRAP_SIZE - mIoTrapData.TrapUsedLength[TrapHandlerNum]) {
+ continue;
+ }
+ //
+ // For common pool, we don't need to change the BaseAddress and UsedLength
+ //
+ RegisterContext->Address = (UINT16) (BaseAddress + mIoTrapData.TrapUsedLength[TrapHandlerNum]);
+ mIoTrapData.TrapUsedLength[TrapHandlerNum] += RegisterContext->Length;
+ } else {
+ //
+ // Check next handler if the address is smaller than the IO trap handler's start address
+ //
+ if (RegisterContext->Address < (UINT16) BaseAddress) {
+ continue;
+ }
+ //
+ // Check next handler if the max address is bigger than IO trap handler's range
+ //
+ if ((RegisterContext->Address + RegisterContext->Length) > (UINT16) (BaseAddress + 256)) {
+ continue;
+ }
+ //
+ // If this handler is used for common pool, assert if the caller's address is within the range
+ //
+ if (mIoTrapData.TrapUsedLength[TrapHandlerNum] != 0) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch address %0x is used for common pool! \n", RegisterContext->Address));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Calculate the Length which is maximum use address - start address
+ //
+ UsedLength = RegisterContext->Address + RegisterContext->Length - (UINT16) BaseAddress;
+ //
+ // Check the alignment is dword * power of 2 or not
+ //
+ for (LengthIndex = 0; LengthIndex < sizeof (mLengthTable) / sizeof (UINT16); LengthIndex++) {
+ if (UsedLength == mLengthTable[LengthIndex]) {
+ break;
+ }
+ }
+ //
+ // Check next handler if the alignment is not dword * power of 2
+ //
+ if (LengthIndex >= sizeof (mLengthTable) / sizeof (UINT16)) {
+ continue;
+ }
+
+ //
+ // Merge the overlap range: remove next Io Trap handler if next Io Trap handler's range is within this handler's range
+ //
+ for (NextTrapHandlerNum = TrapHandlerNum + 1; NextTrapHandlerNum != TrapHandlerNum; NextTrapHandlerNum++) {
+ //
+ // Check if NextTrapHandlerNum overflow
+ //
+ if (NextTrapHandlerNum >= IO_TRAP_HANDLER_NUM) {
+ NextTrapHandlerNum = 0;
+ }
+ //
+ // Get information from Io Trap handler register
+ //
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + NextTrapHandlerNum * 8, &IoTrapRegLowDword);
+ //
+ // Check next handler if the IO Trap handler is not used
+ //
+ if ((IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD) == 0) {
+ continue;
+ }
+ //
+ // Check if next Io Trap handler's range is within this handler's range
+ //
+ NextUsedLength = ((IoTrapRegLowDword >> 16) & 0xFC) + 4;
+ NextBaseAddress = IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD;
+ if ((BaseAddress > NextBaseAddress) || ((BaseAddress + UsedLength) < (NextBaseAddress + NextUsedLength))) {
+ continue;
+ }
+ //
+ // Unregister the IO Trap handler
+ //
+ mIoTrapHandle = mIoTrapData.IoTrapHandle[NextTrapHandlerNum];
+ Status = PchInternalIoTrapSmiUnRegister (mIoTrapHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Clear the Io Trap handler register
+ //
+ SetIoTrapHighDword (NextTrapHandlerNum, 0, TRUE);
+ SetIoTrapLowDword (NextTrapHandlerNum, 0, TRUE);
+ }
+
+ ///
+ /// Update the Length
+ ///
+ IoTrapRegLowDword = (UINT32) (((UsedLength - 1) & ~(BIT1 + BIT0)) << 16) |
+ (UINT16) BaseAddress |
+ B_PCH_PCR_PSTH_TRPREG_TSE;
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, TRUE);
+ }
+ //
+ // Only set RWM bit when we need both read and write cycles.
+ //
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8 + 4, &IoTrapRegHighDword);
+ if ((IoTrapRegHighDword & B_PCH_PCR_PSTH_TRPREG_RWM) == 0 &&
+ (UINT32) ((IoTrapRegHighDword & B_PCH_PCR_PSTH_TRPREG_RWIO) >> N_PCH_PCR_PSTH_TRPREG_RWIO) !=
+ (UINT32) RegisterContext->Type) {
+ IoTrapRegHighDword = ((IoTrapRegHighDword | B_PCH_PCR_PSTH_TRPREG_RWM) & ~B_PCH_PCR_PSTH_TRPREG_RWIO);
+ SetIoTrapHighDword (TrapHandlerNum, IoTrapRegHighDword, TRUE);
+ }
+ }
+ break;
+ }
+
+ if (TrapHandlerNum >= IO_TRAP_HANDLER_NUM) {
+ DEBUG ((DEBUG_ERROR, "All IO Trap handler is used, no available IO Trap handler! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Create database record and add to database
+ //
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (IO_TRAP_RECORD),
+ (VOID **) &mIoTrapRecord
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to allocate memory for mIoTrapRecord! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Gather information about the registration request
+ //
+ mIoTrapRecord->Signature = IO_TRAP_RECORD_SIGNATURE;
+ mIoTrapRecord->Context = *RegisterContext;
+ mIoTrapRecord->Callback = DispatchFunction;
+
+ InsertTailList (&mIoTrapData.CallbackDataBase, &mIoTrapRecord->Link);
+
+ //
+ // Child's handle will be the address linked list link in the record
+ //
+ *DispatchHandle = (EFI_HANDLE) (&mIoTrapRecord->Link);
+
+ DEBUG ((DEBUG_INFO, "RegisterContext->Address:%x! \n", RegisterContext->Address));
+ DEBUG ((DEBUG_INFO, "RegisterContext->Length:%x! \n", RegisterContext->Length));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapUnRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ IO_TRAP_RECORD *RecordToDelete;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ UINT8 LengthIndex;
+
+ if (DispatchHandle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ RecordToDelete = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+ //
+ // Take the entry out of the linked list
+ //
+ if (RecordToDelete->Link.ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Loop through the first IO Trap handler, looking for the suitable handler
+ //
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // Get information from Io Trap handler register
+ //
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, &IoTrapRegLowDword);
+
+ //
+ // Check next Io Trap handler if the IO Trap handler is not used
+ //
+ if ((IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD) == 0) {
+ continue;
+ }
+
+ UsedLength = ((IoTrapRegLowDword >> 16) & 0xFC) + 4;
+ BaseAddress = IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD;
+
+ //
+ // Check if it's the maximum address of the Io Trap handler
+ //
+ if ((UINTN)(BaseAddress + UsedLength) == (UINTN)(RecordToDelete->Context.Address + RecordToDelete->Context.Length)) {
+
+ if (BaseAddress == RecordToDelete->Context.Address) {
+ //
+ // Disable the IO Trap handler if it's the only child of the Trap handler
+ //
+ mIoTrapHandle = mIoTrapData.IoTrapHandle[TrapHandlerNum];
+ Status = PchInternalIoTrapSmiUnRegister (mIoTrapHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ mIoTrapData.TrackIoResource[TrapHandlerNum] = FALSE;
+ //
+ // Clear the Io Trap handler register
+ //
+ IoTrapRegLowDword = 0;
+ IoTrapRegHighDword = 0;
+ SetIoTrapHighDword (TrapHandlerNum, IoTrapRegHighDword, TRUE);
+ if (mIoTrapData.TrackIoResource[TrapHandlerNum] == TRUE) {
+ mIoTrapData.TrackIoResource[TrapHandlerNum] = FALSE;
+ gDS->FreeIoSpace (BaseAddress, GENERIC_IOTRAP_SIZE);
+ UpdateIoTrapAcpiResources (TrapHandlerNum, BaseAddress, FALSE);
+ }
+
+ } else {
+ //
+ // Calculate the new IO Trap handler Length
+ //
+ UsedLength = UsedLength - RecordToDelete->Context.Length;
+ //
+ // Check the alignment is dword * power of 2 or not
+ //
+ for (LengthIndex = 0; LengthIndex < sizeof (mLengthTable) / sizeof (UINT16); LengthIndex++) {
+ if (UsedLength == mLengthTable[LengthIndex]) {
+ break;
+ }
+ }
+ //
+ // Do not decrease the length if the alignment is not dword * power of 2
+ //
+ if (LengthIndex >= sizeof (mLengthTable) / sizeof (UINT16)) {
+ break;
+ }
+ //
+ // Decrease the length to prevent the IO trap SMI
+ //
+ IoTrapRegLowDword = (UINT32) ((((UsedLength - 1) &~(BIT1 + BIT0)) << 16) | BaseAddress | B_PCH_PCR_PSTH_TRPREG_TSE);
+ }
+
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, TRUE);
+ break;
+ }
+ }
+
+ RemoveEntryList (&RecordToDelete->Link);
+ Status = gSmst->SmmFreePool (RecordToDelete);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This I/O Trap SMI handler invokes the ACPI reference code to handle the SMI.
+ It currently assumes it owns all of the IO trap SMI.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+IoTrapCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IO_TRAP_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT CurrentIoTrapRegisterData;
+ EFI_SMM_IO_TRAP_CONTEXT CurrentIoTrapContextData;
+ UINT16 BaseAddress;
+ UINT16 StartAddress;
+ UINT16 EndAddress;
+ UINT32 Data32;
+
+ if (!IsListEmpty (&mIoTrapData.CallbackDataBase)) {
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPC, &Data32);
+ BaseAddress = (UINT16) (Data32 & B_PCH_PCR_PSTH_TRPC_IOA);
+ StartAddress = (Data32 & B_PCH_PCR_PSTH_TRPC_AHBE) >> 16;
+ //
+ // StartAddress and EndAddress will be equal if it's byte access
+ //
+ EndAddress = (UINT16) (HighBitSet32 ((UINT32) (StartAddress))) + BaseAddress;
+ StartAddress = (UINT16) (LowBitSet32 ((UINT32) (StartAddress))) + BaseAddress;
+
+ CurrentIoTrapRegisterData.Type = (BOOLEAN) ((Data32 & B_PCH_PCR_PSTH_TRPC_RW) != 0);
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPD, &Data32);
+ CurrentIoTrapContextData.WriteData = Data32;
+ LinkInDb = GetFirstNode (&mIoTrapData.CallbackDataBase);
+
+ while (!IsNull (&mIoTrapData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = IO_TRAP_RECORD_FROM_LINK (LinkInDb);
+ if ((RecordInDb->Context.Address <= StartAddress) &&
+ (RecordInDb->Context.Address + RecordInDb->Context.Length > EndAddress)) {
+ if (RecordInDb->Context.Type == ReadWriteTrap || RecordInDb->Context.Type == CurrentIoTrapRegisterData.Type) {
+ //
+ // Pass the IO trap context information
+ //
+ RecordInDb->Callback (&RecordInDb->Link, &CurrentIoTrapContextData,NULL,NULL);
+ }
+ //
+ // Break if the address is match
+ //
+ break;
+ } else {
+ LinkInDb = GetNextNode (&mIoTrapData.CallbackDataBase, &RecordInDb->Link);
+ if (IsNull (&mIoTrapData.CallbackDataBase, LinkInDb)) {
+ //
+ // An IO access was trapped that does not have a handler registered.
+ // This indicates an error condition.
+ //
+ ASSERT (FALSE);
+ }
+ }
+ }
+ }
+}
+
+/**
+ Pause IoTrap callback function.
+
+ This function disables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlPause (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IO_TRAP_RECORD *IoTrapRecord;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ BOOLEAN TempMergeDisable;
+
+ if (DispatchHandle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoTrapRecord = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+
+ if (IoTrapRecord->Context.Address) {
+ TempMergeDisable =TRUE;
+ }else {
+ TempMergeDisable = FALSE;
+ }
+
+ if ((IoTrapRecord->Signature != IO_TRAP_RECORD_SIGNATURE) ||
+ (TempMergeDisable != TRUE) ||
+ (IoTrapRecord->Context.Address == 0) ||
+ (IoTrapRecord->Context.Length == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // This IoTrap register should be merge disabled.
+ //
+ if (mIoTrapData.MergeDisable[TrapHandlerNum] != TRUE) {
+ continue;
+ }
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, &IoTrapRegLowDword);
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8 + 4, &IoTrapRegHighDword);
+ //
+ // Depending on the usage, we will obtain the UsedLength and BaseAddress differently
+ // If the registered trap length is less than 4, we obtain the length from Byte Enable Mask
+ // In the other hand, we obtain the length from Address Mask
+ //
+ if ((IoTrapRegHighDword & 0xF0) != 0xF0) {
+ UsedLength = (UINT32) (HighBitSet32 (IoTrapRegHighDword & 0xF0) - LowBitSet32 (IoTrapRegHighDword & 0xF0) + 1);
+ BaseAddress = (IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD) + LowBitSet32 ((IoTrapRegHighDword & 0xF0) >> 4);
+ } else {
+ UsedLength = ((IoTrapRegLowDword >> 16) & 0xFC) + 4;
+ BaseAddress = IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD;
+ }
+
+ //
+ // The address and length of record matches the IoTrap register's.
+ //
+ if ((BaseAddress == IoTrapRecord->Context.Address) &&
+ (UsedLength == IoTrapRecord->Context.Length )) {
+ //
+ // Check if status matched.
+ // If this is already Paused, return warning status.
+ //
+ if ((IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_TSE) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Clear IoTrap register SMI enable bit
+ //
+ IoTrapRegLowDword &= (~B_PCH_PCR_PSTH_TRPREG_TSE);
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, FALSE);
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Resume IoTrap callback function.
+
+ This function enables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady RESUMED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlResume (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IO_TRAP_RECORD *IoTrapRecord;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ BOOLEAN TempMergeDisable;
+
+ if (DispatchHandle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ IoTrapRecord = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+
+ if (IoTrapRecord->Context.Address) {
+ TempMergeDisable = TRUE;
+ }else {
+ TempMergeDisable = FALSE;
+ }
+
+ if ((IoTrapRecord->Signature != IO_TRAP_RECORD_SIGNATURE) ||
+ (TempMergeDisable != TRUE) ||
+ (IoTrapRecord->Context.Address == 0) ||
+ (IoTrapRecord->Context.Length == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // This IoTrap register should be merge disabled.
+ //
+ if (mIoTrapData.MergeDisable[TrapHandlerNum] != TRUE) {
+ continue;
+ }
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8, &IoTrapRegLowDword);
+ PchPcrRead32 (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0 + TrapHandlerNum * 8 + 4, &IoTrapRegHighDword);
+ //
+ // Depending on the usage, we will obtain the UsedLength and BaseAddress differently
+ // If the registered trap length is less than 4, we obtain the length from Byte Enable Mask
+ // In the other hand, we obtain the length from Address Mask
+ //
+ if ((IoTrapRegHighDword & 0xF0) != 0xF0) {
+ UsedLength = (UINT32) (HighBitSet32 (IoTrapRegHighDword & 0xF0) - LowBitSet32 (IoTrapRegHighDword & 0xF0) + 1);
+ BaseAddress = (IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD) + LowBitSet32 ((IoTrapRegHighDword & 0xF0) >> 4);
+ } else {
+ UsedLength = ((IoTrapRegLowDword >> 16) & 0xFC) + 4;
+ BaseAddress = IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_AD;
+ }
+
+ //
+ // The address and length of record matches the IoTrap register's.
+ //
+ if ((BaseAddress == IoTrapRecord->Context.Address) &&
+ (UsedLength == IoTrapRecord->Context.Length )) {
+ //
+ // Check if status matched.
+ // If this is already Resume, return warning status.
+ //
+ if ((IoTrapRegLowDword & B_PCH_PCR_PSTH_TRPREG_TSE) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Set IoTrap register SMI enable bit
+ //
+ IoTrapRegLowDword |= (B_PCH_PCR_PSTH_TRPREG_TSE);
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, FALSE);
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ The IoTrap module abstracts PCH I/O trapping capabilities for other drivers.
+ This driver manages the limited I/O trap resources.
+
+ @param[in] ImageHandle Image handle for this driver image
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallIoTrap (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ PCH_NVS_AREA_PROTOCOL *PchNvsAreaProtocol;
+
+
+ //
+ // Initialize the EFI SMM driver library
+ //
+ mDriverImageHandle = ImageHandle;
+
+ //
+ // Initialize the IO TRAP protocol we produce
+ //
+ mIoTrapData.Signature = IO_TRAP_INSTANCE_SIGNATURE;
+ mIoTrapData.EfiSmmIoTrapDispatchProtocol.Register = IoTrapRegister;
+ mIoTrapData.EfiSmmIoTrapDispatchProtocol.UnRegister = IoTrapUnRegister;
+
+ //
+ // Initialize the IO TRAP control protocol.
+ //
+ mIoTrapData.PchSmmIoTrapControlProtocol.Pause = IoTrapControlPause;
+ mIoTrapData.PchSmmIoTrapControlProtocol.Resume = IoTrapControlResume;
+
+ //
+ // Initialize IO TRAP Callback DataBase
+ //
+ InitializeListHead (&mIoTrapData.CallbackDataBase);
+
+ //
+ // Get address of PchNvs structure for later use
+ //
+ Status = gBS->LocateProtocol (&gPchNvsAreaProtocolGuid, NULL, (VOID **) &PchNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mPchNvsArea = PchNvsAreaProtocol->Area;
+
+ //
+ // Install protocol interface
+ //
+ mIoTrapData.Handle = NULL;
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mIoTrapData.Handle,
+ &gEfiSmmIoTrapDispatch2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mIoTrapData.EfiSmmIoTrapDispatchProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mIoTrapData.Handle,
+ &gPchSmmIoTrapControlGuid,
+ EFI_NATIVE_INTERFACE,
+ &mIoTrapData.PchSmmIoTrapControlProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h
new file mode 100644
index 0000000000..99bb3527f7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h
@@ -0,0 +1,193 @@
+/** @file
+ Defines and prototypes for the IoTrap SMM driver
+
+Copyright (c) 2017, 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 that 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 _IO_TRAP_H_
+#define _IO_TRAP_H_
+
+//
+// Include files
+//
+#include <Library/S3BootScriptLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Protocol/SmmIoTrapDispatch2.h>
+#include <Protocol/PchSmmIoTrapControl.h>
+#define IO_TRAP_HANDLER_NUM 4
+
+//
+// Driver private data
+//
+#define IO_TRAP_INSTANCE_SIGNATURE SIGNATURE_32 ('I', 'O', 'T', 'P')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL EfiSmmIoTrapDispatchProtocol;
+ EFI_HANDLE IoTrapHandle[IO_TRAP_HANDLER_NUM];
+ LIST_ENTRY CallbackDataBase;
+ UINT32 TrapUsedLength[IO_TRAP_HANDLER_NUM];
+ BOOLEAN MergeDisable[IO_TRAP_HANDLER_NUM]; ///< Determine if IoTrap can be merged with other IoTrap
+ PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PchSmmIoTrapControlProtocol; ///< Protocol for runtime control the IoTrap state
+ BOOLEAN TrackIoResource[IO_TRAP_HANDLER_NUM];
+} IO_TRAP_INSTANCE;
+
+#define IO_TRAP_INSTANCE_FROM_THIS(a) CR (a, IO_TRAP_INSTANCE, EfiSmmIoTrapDispatchProtocol, IO_TRAP_INSTANCE_SIGNATURE)
+
+///
+/// "IOTRAP" RECORD
+/// Linked list data structures
+///
+#define IO_TRAP_RECORD_SIGNATURE SIGNATURE_32 ('I', 'T', 'R', 'C')
+
+typedef struct _IO_TRAP_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT Context;
+ EFI_SMM_HANDLER_ENTRY_POINT2 Callback;
+} IO_TRAP_RECORD;
+
+#define IO_TRAP_RECORD_FROM_LINK(_record) CR (_record, IO_TRAP_RECORD, Link, IO_TRAP_RECORD_SIGNATURE)
+
+//
+// Prototypes
+//
+/**
+ The IoTrap module abstracts PCH I/O trapping capabilities for other drivers.
+ This driver manages the limited I/O trap resources.
+
+ @param[in] ImageHandle Image handle for this driver image
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallIoTrap (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ Register a new IO Trap SMI dispatch function with a parent SMM driver.
+ The caller will provide information about the IO trap characteristics via
+ the context. This includes base address, length, read vs. r/w, etc.
+ This function will autoallocate IO base address from a common pool if the base address is 0,
+ and the RegisterContext Address field will be updated.
+ The service will not perform GCD allocation if the base address is non-zero.
+ In this case, the caller is responsible for the existence and allocation of the
+ specific IO range.
+ This function looks for the suitable handler and Register a new IoTrap handler
+ if the IO Trap handler is not used. It also enable the IO Trap Range to generate
+ SMI.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source.
+ @param[in, out] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the IO trap SMI source for which the dispatch
+ function should be invoked. This may not be NULL.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record. This may not be NULL.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources are available
+ @retval EFI_INVALID_PARAMETER Address requested is already in use.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN OUT EFI_SMM_IO_TRAP_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapUnRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ This I/O Trap SMI handler invokes the ACPI reference code to handle the SMI.
+ It currently assumes it owns all of the IO trap SMI.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+IoTrapCallback (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Pause IoTrap callback function.
+
+ This function disables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlPause (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL * This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Resume IoTrap callback function.
+
+ This function enables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady RESUMED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlResume (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL * This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
new file mode 100644
index 0000000000..24773560e5
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
@@ -0,0 +1,2497 @@
+/** @file
+ This function handle the register/unregister of PCH specific SMI events.
+
+Copyright (c) 2017, 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 that 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 "PchSmmHelpers.h"
+
+/**
+ The internal function used to create and insert a database record
+ for SMI record of Pch Smi types.
+
+ @param[in] SrcDesc The pointer to the SMI source description
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] PchSmiType Specific SMI type of PCH SMI
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchSmiRecordInsert (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc,
+ IN PCH_SMI_CALLBACK_FUNCTIONS DispatchFunction,
+ IN PCH_SMI_TYPES PchSmiType,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+ PCH_SMM_SOURCE_DESC NullSourceDesc;
+
+ //
+ // Initialize NullSourceDesc
+ //
+ NullInitSourceDesc (&NullSourceDesc);
+
+ if (CompareSources (SrcDesc, &NullSourceDesc)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (DATABASE_RECORD), (VOID **) &Record);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SetMem (Record, sizeof (DATABASE_RECORD), 0);
+ //
+ // Gather information about the registration request
+ //
+ Record->Signature = DATABASE_RECORD_SIGNATURE;
+ Record->PchSmiCallback = DispatchFunction;
+ Record->ProtocolType = PchSmiDispatchType;
+ Record->PchSmiType = PchSmiType;
+
+ Record->ContextFunctions.GetContext = NULL;
+ Record->ContextFunctions.CmpContext = NULL;
+ Record->ContextFunctions.GetCommBuffer = NULL;
+ Record->ClearSource = NULL;
+
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) (SrcDesc), sizeof (PCH_SMM_SOURCE_DESC));
+
+ //
+ // After ensuring the source of event is not null, we will insert the record into the database
+ //
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+
+ //
+ // Child's handle will be the address linked list link in the record
+ //
+ *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+ return EFI_SUCCESS;
+}
+
+
+//
+// TCO_STS bit that needs to be cleared
+//
+PCH_SMM_SOURCE_DESC mDescSrcTcoSts = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+ },
+ NULL_BIT_DESC_INITIALIZER
+};
+
+/**
+ Clear the TCO SMI status bit and block after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSourceAndBlock (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PchSmmClearSourceAndBlock (SrcDesc);
+ //
+ // Any TCO-based status bits require special handling.
+ // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+ //
+ PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+ Clear the TCO SMI status bit after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSource (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PchSmmClearSource (SrcDesc);
+ //
+ // Any TCO-based status bits require special handling.
+ // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+ //
+ PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+ Initialize Source descriptor structure
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+NullInitSourceDesc (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ ZeroMem (SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
+ SrcDesc->En[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+ SrcDesc->En[1].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+ SrcDesc->Sts[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+ SrcDesc->PmcSmiSts.Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+}
+
+//
+// Mch srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescMch = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_DMISMI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of MCH event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiMchRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescMch,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiMchType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// TcoTimeout srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescTcoTimeout = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_TIMEOUT
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of TcoTimeout event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiTcoTimeoutRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescTcoTimeout,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiTcoTimeoutType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// OsTco srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescOsTco = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_SW_TCO_SMI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of OS TCO event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiOsTcoRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescOsTco,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiOsTcoType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// Nmi
+//
+PCH_SMM_SOURCE_DESC mSrcDescNmi = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_CNT}
+ },
+ S_PCH_TCO1_CNT,
+ N_PCH_TCO_CNT_NMI2SMI_EN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_NMI2SMI
+ }
+ },
+ //
+ // NOTE: The status of NMI2SMI won't reflect to PMC SMI_STS.
+ // So skip the top level status check and check the TCO1_STS directly.
+ //
+ NULL_BIT_DESC_INITIALIZER
+};
+
+/**
+ The register function used to register SMI handler of NMI event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiNmiRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescNmi,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiNmiType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// IntruderDetect srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescIntruderDet = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO2_CNT}
+ },
+ S_PCH_TCO2_CNT,
+ N_PCH_TCO2_CNT_INTRD_SEL
+ }
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO2_STS}
+ },
+ S_PCH_TCO2_STS,
+ N_PCH_TCO2_STS_INTRD_DET
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of Intruder Detect event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiIntruderDetRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescIntruderDet,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiIntruderDetectType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSourceAndBlock;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// SpiBiosWp srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescSpiBiosWp = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_PCH_SPI_BC
+ ) }
+ },
+ S_PCH_SPI_BC,
+ N_PCH_SPI_BC_BLE
+ },
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_PCH_SPI_BC
+ ) }
+ },
+ S_PCH_SPI_BC,
+ N_PCH_SPI_BC_SYNC_SS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ Special handling for SPI Write Protect
+
+ @param[in] SrcDesc Not used
+**/
+VOID
+EFIAPI
+PchTcoSpiWpClearSource (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN SpiRegBase;
+
+ SpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ MmioAndThenOr32 (
+ SpiRegBase + R_PCH_SPI_BC,
+ (UINT32) ~B_PCH_SPI_BC_ASYNC_SS,
+ B_PCH_SPI_BC_SYNC_SS
+ );
+
+ //
+ // Any TCO-based status bits require special handling.
+ // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+ //
+ PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+ Special handling to enable SPI Write Protect
+**/
+VOID
+PchTcoSpiWpEnableSource (
+ VOID
+ )
+{
+ UINTN SpiRegBase;
+
+ SpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ MmioAndThenOr32 (
+ SpiRegBase + R_PCH_SPI_BC,
+ (UINT32) ~(B_PCH_SPI_BC_ASYNC_SS | B_PCH_SPI_BC_SYNC_SS),
+ B_PCH_SPI_BC_LE
+ );
+
+ IoOr32 (mAcpiBaseAddr + R_PCH_SMI_EN, B_PCH_SMI_EN_TCO);
+
+ //
+ // Clear the source
+ //
+ PchTcoSpiWpClearSource (NULL);
+}
+
+/**
+ The register function used to register SMI handler of BIOS write protect event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiSpiBiosWpRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSpiBiosWp,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiSpiBiosWpType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSpiWpClearSource;
+ PchTcoSpiWpClearSource (NULL);
+ PchTcoSpiWpEnableSource ();
+ }
+ return Status;
+}
+
+//
+// LpcBiosWp srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_PCH_LPC_BC
+ ) }
+ },
+ S_PCH_LPC_BC,
+ N_PCH_LPC_BC_LE
+ }
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_BIOSWR
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of LPC BIOS write protect event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiLpcBiosWpRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescLpcBiosWp,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiLpcBiosWpType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+//
+// NEWCENTURY_STS bit that needs to be cleared
+//
+PCH_SMM_SOURCE_DESC mSrcDescNewCentury = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_PCH_TCO1_STS}
+ },
+ S_PCH_TCO1_STS,
+ N_PCH_TCO1_STS_NEWCENTURY
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ Check and clear NEWCENTURY_STS.
+ It will clear the SMI status once it happens.
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+**/
+VOID
+EFIAPI
+PchTcoClearNewCenturySts (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINT16 TcoSts1;
+ TcoSts1 = IoRead16 (mTcoBaseAddr + R_PCH_TCO1_STS);
+
+ if (TcoSts1 & B_PCH_TCO1_STS_NEWCENTURY) {
+ PchTcoSmiClearSourceAndBlock (&mSrcDescNewCentury);
+ }
+}
+
+/**
+ The register function used to register SMI handler of NEW CENTURY event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiNewCenturyRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescNewCentury,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiNewCenturyType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoClearNewCenturySts;
+ PchTcoClearNewCenturySts (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ }
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiUnRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *Record;
+
+ Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ if ((Record->SrcDesc.En[1].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Dev == PCI_DEVICE_NUMBER_PCH_SPI) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == PCI_FUNCTION_NUMBER_PCH_SPI) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_PCH_SPI_BC) &&
+ (Record->SrcDesc.En[1].Bit == N_PCH_SPI_BC_BLE)) {
+ //
+ // SPI Write Protect cannot be disabled
+ //
+ return EFI_ACCESS_DENIED;
+ } else if ((Record->SrcDesc.En[1].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Dev == PCI_DEVICE_NUMBER_PCH_LPC) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == PCI_FUNCTION_NUMBER_PCH_LPC) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_PCH_LPC_BC) &&
+ (Record->SrcDesc.En[1].Bit == N_PCH_LPC_BC_LE)) {
+ //
+ // eSPI/LPC Write Protect cannot be disabled
+ //
+ return EFI_ACCESS_DENIED;
+ }
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
+
+
+//
+// PcieRpHotPlug srcdesc
+//
+PCH_SMM_SOURCE_DESC PchPcieSmiRpHotPlugTemplate = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_MPC}
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_SMSCS}
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPPDM
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PCI_EXP
+ }
+};
+
+/**
+ The register function used to register SMI handler of PCIE RP hotplug event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] RpIndex Indicate the RP index (0-based)
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiHotPlugRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN RpDev;
+ UINTN RpFun;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ GetPchPcieRpDevFun (RpIndex, &RpDev, &RpFun);
+ //
+ // Patch the RP device number and function number of srcdesc.
+ //
+ PchPcieSmiRpHotPlugTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpHotPlugTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+ PchPcieSmiRpHotPlugTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpHotPlugTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+
+ Status = PchSmiRecordInsert (
+ &PchPcieSmiRpHotPlugTemplate,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchPcieSmiRpHotplugType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&PchPcieSmiRpHotPlugTemplate);
+ PchSmmEnableSource (&PchPcieSmiRpHotPlugTemplate);
+
+ return Status;
+}
+
+//
+// PcieRpLinkActive srcdesc
+//
+PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkActiveTemplate = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_MPC}
+ },
+ S_PCH_PCIE_MPC,
+ N_PCH_PCIE_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_SMSCS}
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_HPLAS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PCI_EXP
+ }
+};
+
+/**
+ The register function used to register SMI handler of PCIE RP link active event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] RpIndex Indicate the RP index (0-based)
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiLinkActiveRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN RpDev;
+ UINTN RpFun;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ GetPchPcieRpDevFun (RpIndex, &RpDev, &RpFun);
+ //
+ // Patch the RP device number and function number of srcdesc.
+ //
+ PchPcieSmiRpLinkActiveTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkActiveTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+ PchPcieSmiRpLinkActiveTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkActiveTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+
+ Status = PchSmiRecordInsert (
+ &PchPcieSmiRpLinkActiveTemplate,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchPcieSmiRpLinkActiveType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&PchPcieSmiRpLinkActiveTemplate);
+ PchSmmEnableSource (&PchPcieSmiRpLinkActiveTemplate);
+
+ return Status;
+}
+
+//
+// PcieRpLinkEq srcdesc
+//
+PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkEqTemplate = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_EQCFG1}
+ },
+ S_PCH_PCIE_EQCFG1,
+ N_PCH_PCIE_EQCFG1_LERSMIE
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_SMSCS}
+ },
+ S_PCH_PCIE_SMSCS,
+ N_PCH_PCIE_SMSCS_LERSMIS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PCI_EXP
+ }
+};
+
+/**
+ The register function used to register SMI handler of PCIE RP Link Equalization Request event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] RpIndex Indicate the RP index (0-based)
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiLinkEqRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ UINTN RpDev;
+ UINTN RpFun;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ GetPchPcieRpDevFun (RpIndex, &RpDev, &RpFun);
+ //
+ // Patch the RP device number and function number of srcdesc.
+ //
+ PchPcieSmiRpLinkEqTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkEqTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+ PchPcieSmiRpLinkEqTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkEqTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+
+ return PchSmiRecordInsert (
+ &PchPcieSmiRpLinkEqTemplate,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchPcieSmiRpLinkEqType,
+ DispatchHandle
+ );
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiUnRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
+
+//
+// Pme srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescPme = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_GPE0_EN_127_96}
+ },
+ S_PCH_ACPI_GPE0_EN_127_96,
+ N_PCH_ACPI_GPE0_EN_127_96_PME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_GPE0_STS_127_96}
+ },
+ S_PCH_ACPI_GPE0_STS_127_96,
+ N_PCH_ACPI_GPE0_STS_127_96_PME
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPE0
+ }
+};
+
+/**
+ The register function used to register SMI handler of PME event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiPmeRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescPme,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiPmeType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescPme);
+ PchSmmEnableSource (&mSrcDescPme);
+
+ return Status;
+}
+
+//
+// PmeB0 srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescPmeB0 = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_GPE0_EN_127_96}
+ },
+ S_PCH_ACPI_GPE0_EN_127_96,
+ N_PCH_ACPI_GPE0_EN_127_96_PME_B0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_GPE0_STS_127_96}
+ },
+ S_PCH_ACPI_GPE0_STS_127_96,
+ N_PCH_ACPI_GPE0_STS_127_96_PME_B0
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPE0
+ }
+};
+
+/**
+ The register function used to register SMI handler of PME B0 event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiPmeB0Register (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescPmeB0,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiPmeB0Type,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescPmeB0);
+ PchSmmEnableSource (&mSrcDescPmeB0);
+
+ return Status;
+}
+
+//
+// RtcAlarm srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescRtcAlarm = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_EN}
+ },
+ S_PCH_ACPI_PM1_EN,
+ N_PCH_ACPI_PM1_EN_RTC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_STS}
+ },
+ S_PCH_ACPI_PM1_STS,
+ N_PCH_ACPI_PM1_STS_RTC
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PM1_STS_REG
+ }
+};
+
+/**
+ The register function used to register SMI handler of RTC alarm event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiRtcAlarmRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescRtcAlarm,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiRtcAlarmType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescRtcAlarm);
+ PchSmmEnableSource (&mSrcDescRtcAlarm);
+
+ return Status;
+}
+
+//
+// TmrOverflow srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescTmrOverflow = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_EN}
+ },
+ S_PCH_ACPI_PM1_EN,
+ N_PCH_ACPI_PM1_EN_TMROF
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_STS}
+ },
+ S_PCH_ACPI_PM1_STS,
+ N_PCH_ACPI_PM1_STS_TMROF
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PM1_STS_REG
+ }
+};
+
+/**
+ The register function used to register SMI handler of Timer Overflow event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiTmrOverflowRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescTmrOverflow,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiTmrOverflowType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescTmrOverflow);
+ PchSmmEnableSource (&mSrcDescTmrOverflow);
+
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiUnRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
+
+//
+// GpioUnlock srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescGpioUnlock = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_GPIO_UNLOCK
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPIO_UNLOCK
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPIO_UNLOCK
+ }
+};
+
+/**
+ The register function used to register SMI handler of GPIO Unlock event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchGpioUnlockSmiRegister (
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescGpioUnlock,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchGpioUnlockSmiType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescGpioUnlock);
+ PchSmmEnableSource (&mSrcDescGpioUnlock);
+
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent GPIO UNLOCK SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchGpioUnlockSmiUnRegister (
+ IN PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
+
+//
+// SerialIrq srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescSerialIrq = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SERIRQ
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SERIRQ
+ }
+};
+
+/**
+ The register function used to register SMI handler of Serial IRQ event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSerialIrqRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSerialIrq,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiSerialIrqType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescSerialIrq);
+ PchSmmEnableSource (&mSrcDescSerialIrq);
+
+ return Status;
+}
+
+//
+// McSmi srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescMcSmi = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_MCSMI
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MCSMI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MCSMI
+ }
+};
+
+/**
+ The register function used to register SMI handler of MCSMI event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiMcSmiRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescMcSmi,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiMcSmiType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescMcSmi);
+ PchSmmEnableSource (&mSrcDescMcSmi);
+
+ return Status;
+}
+
+//
+// SmBus srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescSmbus = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SMBUS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SMBUS
+ }
+};
+
+/**
+ The register function used to register SMI handler of SMBUS event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSmbusRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSmbus,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiSmBusType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescSmbus);
+ PchSmmEnableSource (&mSrcDescSmbus);
+
+ return Status;
+}
+
+//
+// SpiAsyncSmi srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescSpiAsyncSmi = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_PCH_SPI_BC
+ ) }
+ },
+ S_PCH_SPI_BC,
+ N_PCH_SPI_BC_ASE_BWP
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_PCH_SPI_BC
+ ) }
+ },
+ S_PCH_SPI_BC,
+ N_PCH_SPI_BC_ASYNC_SS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SPI
+ }
+};
+
+/**
+ Special handling for SPI Asynchronous SMI.
+ If SPI ASYNC SMI is enabled, De-assert SMI is sent when Flash Cycle Done
+ transitions from 1 to 0 or when the SMI enable becomes false.
+
+ @param[in] SrcDesc Not used
+**/
+VOID
+EFIAPI
+PchSmiSpiAsyncClearSource (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN SpiRegBase;
+ UINT32 SpiBar0;
+
+ SpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ SpiBar0 = MmioRead32 (SpiRegBase + R_PCH_SPI_BAR0) & ~(B_PCH_SPI_BAR0_MASK);
+ if (SpiBar0 != PCH_SPI_BASE_ADDRESS) {
+ //
+ // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+ //
+ SpiBar0 = PCH_SPI_BASE_ADDRESS;
+ MmioAnd8 (SpiRegBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (SpiRegBase + R_PCH_SPI_BAR0, SpiBar0);
+ MmioOr8 (SpiRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+
+ MmioOr32 (SpiBar0 + R_PCH_SPI_HSFSC, B_PCH_SPI_HSFSC_FDONE);
+}
+
+/**
+ Special handling to enable SPI Asynchronous SMI
+**/
+VOID
+PchSmiSpiAsyncEnableSource (
+ VOID
+ )
+{
+ UINTN SpiRegBase;
+ SpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ MmioAndThenOr32 (
+ SpiRegBase + R_PCH_SPI_BC,
+ (UINT32) ~B_PCH_SPI_BC_SYNC_SS,
+ B_PCH_SPI_BC_ASE_BWP
+ );
+
+ //
+ // Clear the source
+ //
+ PchSmiSpiAsyncClearSource (NULL);
+}
+
+/**
+ The register function used to register SMI handler of SPI Asynchronous event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSpiAsyncRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSpiAsyncSmi,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiSpiAsyncType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchSmiSpiAsyncClearSource;
+ PchSmiSpiAsyncClearSource (NULL);
+ PchSmiSpiAsyncEnableSource ();
+ }
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval EFI_ACCESS_DENIED Return access denied since SPI aync SMI handler is not able to disabled.
+**/
+EFI_STATUS
+EFIAPI
+PchSmiUnRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *Record;
+ UINTN SpiRegBase;
+
+ Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ if ((Record->SrcDesc.En[0].Reg.Type == PCIE_ADDR_TYPE) &&
+ (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev == PCI_DEVICE_NUMBER_PCH_SPI) &&
+ (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc == PCI_FUNCTION_NUMBER_PCH_SPI) &&
+ (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Reg == R_PCH_SPI_BC) &&
+ (Record->SrcDesc.En[0].Bit == N_PCH_SPI_BC_ASE_BWP)) {
+ SpiRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ if (MmioRead8 (SpiRegBase + R_PCH_SPI_BC) & B_PCH_SPI_BC_BILD) {
+ //
+ // SPI Asynchronous SMI cannot be disabled
+ //
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
+
+
+/**
+ Declaration of PCH TCO SMI DISPATCH PROTOCOL instance
+**/
+PCH_TCO_SMI_DISPATCH_PROTOCOL mPchTcoSmiDispatchProtocol = {
+ PCH_TCO_SMI_DISPATCH_REVISION, // Revision
+ PchTcoSmiUnRegister, // Unregister
+ PchTcoSmiMchRegister, // Mch
+ PchTcoSmiTcoTimeoutRegister, // TcoTimeout
+ PchTcoSmiOsTcoRegister, // OsTco
+ PchTcoSmiNmiRegister, // Nmi
+ PchTcoSmiIntruderDetRegister, // IntruderDectect
+ PchTcoSmiSpiBiosWpRegister, // SpiBiosWp
+ PchTcoSmiLpcBiosWpRegister, // LpcBiosWp
+ PchTcoSmiNewCenturyRegister // NewCentury
+};
+
+/**
+ Declaration of PCH PCIE SMI DISPATCH PROTOCOL instance
+**/
+PCH_PCIE_SMI_DISPATCH_PROTOCOL mPchPcieSmiDispatchProtocol = {
+ PCH_PCIE_SMI_DISPATCH_REVISION, // Revision
+ PchPcieSmiUnRegister, // Unregister
+ PchPcieSmiHotPlugRegister, // PcieRpXHotPlug
+ PchPcieSmiLinkActiveRegister, // PcieRpXLinkActive
+ PchPcieSmiLinkEqRegister // PcieRpXLinkEq
+};
+
+/**
+ Declaration of PCH ACPI SMI DISPATCH PROTOCOL instance
+**/
+PCH_ACPI_SMI_DISPATCH_PROTOCOL mPchAcpiSmiDispatchProtocol = {
+ PCH_ACPI_SMI_DISPATCH_REVISION, // Revision
+ PchAcpiSmiUnRegister, // Unregister
+ PchAcpiSmiPmeRegister, // Pme
+ PchAcpiSmiPmeB0Register, // PmeB0
+ PchAcpiSmiRtcAlarmRegister, // RtcAlarm
+ PchAcpiSmiTmrOverflowRegister // TmrOverflow
+};
+
+/**
+ Declaration of PCH GPIO UNLOCK SMI DISPATCH PROTOCOL instance
+**/
+PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL mPchGpioUnlockSmiDispatchProtocol = {
+ PCH_GPIO_UNLOCK_SMI_DISPATCH_REVISION,// Revision
+ PchGpioUnlockSmiUnRegister, // Unregister
+ PchGpioUnlockSmiRegister // GpioUnlock
+};
+
+/**
+ Declaration of MISC PCH SMI DISPATCH PROTOCOL instance
+**/
+PCH_SMI_DISPATCH_PROTOCOL mPchSmiDispatchProtocol = {
+ PCH_SMI_DISPATCH_REVISION, // Revision
+ PchSmiUnRegister, // Unregister
+ PchSmiSerialIrqRegister, // SerialIrq
+ PchSmiMcSmiRegister, // McSmi
+ PchSmiSmbusRegister, // SmBus
+ PchSmiSpiAsyncRegister // SpiAsync
+};
+
+/**
+ Install protocols of PCH specifics SMI types, including
+ PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
+
+ @retval the result of protocol installation
+**/
+EFI_STATUS
+InstallPchSmiDispatchProtocols (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ Handle = NULL;
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchTcoSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchTcoSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchPcieSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchPcieSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchAcpiSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchAcpiSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchGpioUnlockSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchGpioUnlockSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchSmiDispatchProtocol
+ );
+
+ return Status;
+}
+
+/**
+ The function to dispatch all callback function of PCH SMI types.
+
+ @retval EFI_SUCCESS Function successfully completed
+ @retval EFI_UNSUPPORTED no
+**/
+EFI_STATUS
+PchSmiTypeCallbackDispatcher (
+ IN DATABASE_RECORD *Record
+ )
+{
+ EFI_STATUS Status;
+ PCH_SMI_TYPES PchSmiType;
+ UINTN RpIndex;
+ PCH_PCIE_SMI_RP_CONTEXT RpContext;
+
+ PchSmiType = Record->PchSmiType;
+ Status = EFI_SUCCESS;
+
+ switch (PchSmiType) {
+ case PchTcoSmiMchType:
+ case PchTcoSmiTcoTimeoutType:
+ case PchTcoSmiOsTcoType:
+ case PchTcoSmiNmiType:
+ case PchTcoSmiIntruderDetectType:
+ case PchTcoSmiSpiBiosWpType:
+ case PchTcoSmiLpcBiosWpType:
+ case PchTcoSmiNewCenturyType:
+ ((PCH_TCO_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchPcieSmiRpHotplugType:
+ case PchPcieSmiRpLinkActiveType:
+ case PchPcieSmiRpLinkEqType:
+ RpContext.BusNum = DEFAULT_PCI_BUS_NUMBER_PCH;
+ RpContext.DevNum = (UINT8) Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev;
+ RpContext.FuncNum = (UINT8) Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc;
+ GetPchPcieRpNumber (RpContext.DevNum, RpContext.FuncNum, &RpIndex);
+ RpContext.RpIndex = (UINT8) RpIndex;
+ ((PCH_PCIE_SMI_RP_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link, &RpContext);
+ break;
+ case PchAcpiSmiPmeType:
+ case PchAcpiSmiPmeB0Type:
+ case PchAcpiSmiRtcAlarmType:
+ case PchAcpiSmiTmrOverflowType:
+ ((PCH_ACPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchGpioUnlockSmiType:
+ ((PCH_GPIO_UNLOCK_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchEspiSmiEspiSlaveType:
+ ((PCH_ESPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchSmiSerialIrqType:
+ case PchSmiMcSmiType:
+ case PchSmiSmBusType:
+ case PchSmiSpiAsyncType:
+ case PchIoTrapSmiType: ///< internal type for IoTrap
+ ((PCH_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ default:
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ return Status;
+}
+
+PCH_SMM_SOURCE_DESC mSrcDescIoTrap[4] = {
+ //
+ // PCH I/O Trap register 0 monitor
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG0) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) }
+ },
+ 1,
+ 0
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MONITOR
+ }
+ },
+ //
+ // PCH I/O Trap register 1 monitor
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG1) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) }
+ },
+ 1,
+ 1
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MONITOR
+ }
+ },
+ //
+ // PCH I/O Trap register 2 monitor
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG2) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) }
+ },
+ 1,
+ 2
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MONITOR
+ }
+ },
+ //
+ // PCH I/O Trap register 3 monitor,
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPREG3) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PCH_PCR_PSTH_TRPST) }
+ },
+ 1,
+ 3
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_MONITOR
+ }
+ }
+};
+
+/**
+ The register function used to register SMI handler of IoTrap event.
+ This is internal function and only used by Iotrap module.
+
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] IoTrapIndex Index number of IOTRAP register
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiRegister (
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN IoTrapIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescIoTrap[IoTrapIndex],
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchIoTrapSmiType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescIoTrap[IoTrapIndex]);
+ PchSmmEnableSource (&mSrcDescIoTrap[IoTrapIndex]);
+
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiUnRegister (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
new file mode 100644
index 0000000000..b6fc2b95fd
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
@@ -0,0 +1,113 @@
+## @file
+# Component description file for the Pch SMI Dispatch Handlers module
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PchSmiDispatcher
+FILE_GUID = B0D6ED53-B844-43f5-BD2F-61095264E77E
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = InitializePchSmmDispatcher
+
+
+[LibraryClasses]
+UefiBootServicesTableLib
+UefiDriverEntryPoint
+IoLib
+DebugLib
+PcdLib
+BaseLib
+BaseMemoryLib
+HobLib
+DevicePathLib
+PchCycleDecodingLib
+PchPcieRpLib
+PchPcrLib
+SmmServicesTableLib
+ReportStatusCodeLib
+PerformanceLib
+DxeServicesTableLib
+GpioLib
+GpioPrivateLib
+S3BootScriptLib
+ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+# Progress Code for S3 Suspend end.
+# PROGRESS_CODE_S3_SUSPEND_END = (EFI_SOFTWARE_SMM_DRIVER | (EFI_OEM_SPECIFIC | 0x00000001)) = 0x03078001
+gSiPkgTokenSpaceGuid.PcdProgressCodeS3SuspendEnd
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[Sources]
+PchSmm.h
+PchSmmCore.c
+PchSmmHelpers.h
+PchSmmHelpers.c
+PchxSmmHelpers.h
+PchxSmmHelpers.c
+PchSmmUsb.c
+PchSmmGpi.c
+PchSmmPowerButton.c
+PchSmmSw.c
+PchSmmSx.c
+PchSmmPeriodicTimer.c
+IoTrap.c
+PchSmiDispatch.c
+PchSmmEspi.c
+
+
+[Protocols]
+gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
+gEfiSmmGpiDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmSxDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmSwDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmUsbDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmPowerButtonDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmPeriodicTimerDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmBase2ProtocolGuid ## CONSUMES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+gEfiSmmReadyToLockProtocolGuid ## CONSUMES
+gEfiSmmIoTrapDispatch2ProtocolGuid ## PRODUCES
+gPchSmmIoTrapControlGuid ## PRODUCES
+gPchTcoSmiDispatchProtocolGuid ## PRODUCES
+gPchPcieSmiDispatchProtocolGuid ## PRODUCES
+gPchAcpiSmiDispatchProtocolGuid ## PRODUCES
+gPchGpioUnlockSmiDispatchProtocolGuid ## PRODUCES
+gPchSmiDispatchProtocolGuid ## PRODUCES
+gPchEspiSmiDispatchProtocolGuid ## PRODUCES
+gPchSmmPeriodicTimerControlGuid ## PRODUCES
+gPchNvsAreaProtocolGuid ## CONSUMES
+
+
+[Guids]
+
+
+[Depex]
+gEfiPciRootBridgeIoProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND ## This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiSmmCpuProtocolGuid AND
+gEfiSmmBase2ProtocolGuid AND ## This is for SmmServicesTableLib
+gPchNvsAreaProtocolGuid
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
new file mode 100644
index 0000000000..7e4cce83f3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
@@ -0,0 +1,949 @@
+/** @file
+ Prototypes and defines for the PCH SMM Dispatcher.
+
+Copyright (c) 2017, 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 that 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 PCH_SMM_H
+#define PCH_SMM_H
+
+#include <Uefi.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SmmControl2.h>
+#include <Protocol/SmmUsbDispatch2.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmGpiDispatch2.h>
+#include <Protocol/SmmPowerButtonDispatch2.h>
+#include <Protocol/SmmPeriodicTimerDispatch2.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PerformanceLib.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchEspiLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Protocol/PchTcoSmiDispatch.h>
+#include <Protocol/PchPcieSmiDispatch.h>
+#include <Protocol/PchAcpiSmiDispatch.h>
+#include <Protocol/PchGpioUnlockSmiDispatch.h>
+#include <Protocol/PchSmiDispatch.h>
+#include <Protocol/PchEspiSmiDispatch.h>
+#include "IoTrap.h"
+
+#define EFI_BAD_POINTER 0xAFAFAFAFAFAFAFAFULL
+
+extern BOOLEAN mReadyToLock;
+
+///
+/// Define an enumeration for all the supported protocols
+///
+#define PCH_SMM_PROTOCOL_TYPE_MAX 6
+
+typedef enum {
+ UsbType,
+ SxType,
+ SwType,
+ GpiType,
+ PowerButtonType,
+ PeriodicTimerType,
+ PchSmiDispatchType,
+ PchSmmProtocolTypeMax
+} PCH_SMM_PROTOCOL_TYPE;
+
+///
+/// Define all the supported types of PCH SMI
+///
+typedef enum {
+ PchTcoSmiMchType,
+ PchTcoSmiTcoTimeoutType,
+ PchTcoSmiOsTcoType,
+ PchTcoSmiNmiType,
+ PchTcoSmiIntruderDetectType,
+ PchTcoSmiSpiBiosWpType,
+ PchTcoSmiLpcBiosWpType,
+ PchTcoSmiNewCenturyType,
+ PchPcieSmiRpHotplugType,
+ PchPcieSmiRpLinkActiveType,
+ PchPcieSmiRpLinkEqType,
+ PchAcpiSmiPmeType,
+ PchAcpiSmiPmeB0Type,
+ PchAcpiSmiRtcAlarmType,
+ PchAcpiSmiTmrOverflowType,
+ PchGpioUnlockSmiType,
+ PchEspiSmiEspiSlaveType,
+ PchSmiSerialIrqType,
+ PchSmiMcSmiType,
+ PchSmiSmBusType,
+ PchSmiSpiAsyncType,
+ PchIoTrapSmiType ///< internal SMI type
+} PCH_SMI_TYPES;
+
+///
+/// Generic funciton pointer to cover all Pch SMI function pointer types
+///
+typedef
+VOID
+(EFIAPI *PCH_SMI_CALLBACK_FUNCTIONS) (
+ IN EFI_HANDLE DispatchHandle,
+ ...
+ );
+
+
+///
+/// SPECIFYING A REGISTER
+/// We want a general way of referring to addresses. For this case, we'll only
+/// need addresses in the ACPI table (and the TCO entries within the ACPI table).
+/// However, it's interesting to consider what it would take to support other types
+/// of addresses. To address Will's concern, I think it prudent to accommodate it
+/// early on in the design.
+///
+/// Addresses we need to consider:
+///
+/// Type: Required:
+/// I/O Yes
+/// ACPI (special case of I/O) Only if we want to
+/// TCO (special case of I/O) Only if we want to
+/// GPIO (special case of MMIO) Only if we want to
+/// Memory (or Memory Mapped I/O) Only if we want to
+/// PCIE Yes, for BiosWp
+///
+typedef enum {
+ ///
+ /// IO_ADDR_TYPE, /// unimplemented
+ ///
+ ACPI_ADDR_TYPE,
+ TCO_ADDR_TYPE,
+ ///
+ /// MEMORY_ADDR_TYPE, /// unimplemented
+ ///
+ GPIO_ADDR_TYPE,
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCIE_ADDR_TYPE,
+ PCR_ADDR_TYPE,
+ NUM_ADDR_TYPES, ///< count of items in this enum
+ PCH_SMM_ADDR_TYPE_NULL = -1 ///< sentinel to indicate NULL or to signal end of arrays
+} ADDR_TYPE;
+
+//
+// Assumption: 32-bits -- enum's evaluate to integer
+// Assumption: This code will only run on IA-32. Justification: IA-64 doesn't have SMIs.
+// We don't have to worry about 64-bit addresses.
+// Typedef the size of addresses in case the numbers I'm using are wrong or in case
+// this changes. This is a good idea because PCI_ADDR will change, for example, when
+// we add support for PciExpress.
+//
+typedef UINT16 IO_ADDR;
+typedef IO_ADDR ACPI_ADDR; ///< can omit
+typedef IO_ADDR TCO_ADDR; ///< can omit
+typedef UINTN MEM_ADDR;
+typedef MEM_ADDR *MEMORY_MAPPED_IO_ADDRESS;
+typedef MEM_ADDR *GPIO_ADDR;
+typedef union {
+ UINT32 Raw;
+ struct {
+ UINT32 Reg: 16;
+ UINT32 Fnc: 3;
+ UINT32 Dev: 5;
+ UINT32 Bus: 8;
+ } Fields;
+} PCIE_ADDR;
+
+typedef union {
+ UINT32 Raw;
+ struct {
+ UINT16 Offset;
+ UINT8 Pid;
+ UINT8 Base;
+ } Fields;
+} PCR_ADDR;
+
+typedef struct {
+ ADDR_TYPE Type;
+ union {
+ ///
+ /// used to initialize during declaration/definition
+ ///
+ UINT32 raw;
+
+ ///
+ /// used to access useful data
+ ///
+ IO_ADDR io;
+ ACPI_ADDR acpi;
+ TCO_ADDR tco;
+ GPIO_ADDR gpio;
+ MEM_ADDR mem;
+ MEMORY_MAPPED_IO_ADDRESS Mmio;
+ PCIE_ADDR pcie;
+ PCR_ADDR Pcr;
+
+ } Data;
+
+} PCH_SMM_ADDRESS;
+
+///
+/// SPECIFYING BITS WITHIN A REGISTER
+/// Here's a struct that helps us specify a source or enable bit.
+///
+typedef struct {
+ PCH_SMM_ADDRESS Reg;
+ UINT8 SizeInBytes; ///< of the register
+ UINT8 Bit;
+} PCH_SMM_BIT_DESC;
+
+//
+// Sometimes, we'll have bit descriptions that are unused. It'd be great to have a
+// way to easily identify them:
+//
+#define IS_BIT_DESC_NULL(BitDesc) ((BitDesc).Reg.Type == PCH_SMM_ADDR_TYPE_NULL) ///< "returns" true when BitDesc is NULL
+#define NULL_THIS_BIT_DESC(BitDesc) ((BitDesc).Reg.Type = PCH_SMM_ADDR_TYPE_NULL) ///< will "return" an integer w/ value of 0
+#define NULL_BIT_DESC_INITIALIZER \
+ { \
+ { \
+ PCH_SMM_ADDR_TYPE_NULL, \
+ { \
+ 0 \
+ } \
+ }, \
+ 0, 0 \
+ }
+//
+// I'd like a type to specify the callback's Sts & En bits because they'll
+// be commonly used together:
+//
+#define NUM_EN_BITS 2
+#define NUM_STS_BITS 1
+
+//
+// Flags
+//
+typedef UINT8 PCH_SMM_SOURCE_FLAGS;
+
+//
+// Flags required to describe the event source
+//
+#define PCH_SMM_NO_FLAGS 0
+#define PCH_SMM_SCI_EN_DEPENDENT 1
+
+typedef struct {
+ PCH_SMM_SOURCE_FLAGS Flags;
+ PCH_SMM_BIT_DESC En[NUM_EN_BITS]; ///< Describes the enable bit(s) for the SMI event
+ PCH_SMM_BIT_DESC Sts[NUM_STS_BITS]; ///< Describes the secondary status bit for the SMI event. Might be the same as TopLevelSmi
+ PCH_SMM_BIT_DESC PmcSmiSts; ///< Refereing to the top level status bit in PMC SMI_STS, i.e. R_PCH_SMI_STS
+} PCH_SMM_SOURCE_DESC;
+
+///
+/// Used to initialize null source descriptor
+///
+#define NULL_SOURCE_DESC_INITIALIZER \
+ { \
+ PCH_SMM_NO_FLAGS, \
+ { \
+ NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER \
+ }, \
+ { \
+ NULL_BIT_DESC_INITIALIZER \
+ }, \
+ NULL_BIT_DESC_INITIALIZER \
+ }
+
+///
+/// CHILD CONTEXTS
+/// To keep consistent w/ the architecture, we'll need to provide the context
+/// to the child when we call its callback function. After talking with Will,
+/// we agreed that we'll need functions to "dig" the context out of the hardware
+/// in many cases (Sx, Trap, Gpi, etc), and we'll need a function to compare those
+/// contexts to prevent unnecessary dispatches. I'd like a general type for these
+/// "GetContext" functions, so I'll need a union of all the protocol contexts for
+/// our internal use:
+///
+typedef union {
+ //
+ // (in no particular order)
+ //
+ EFI_SMM_SX_REGISTER_CONTEXT Sx;
+ EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT PeriodicTimer;
+ EFI_SMM_SW_REGISTER_CONTEXT Sw;
+ EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT PowerButton;
+ EFI_SMM_USB_REGISTER_CONTEXT Usb;
+ EFI_SMM_GPI_REGISTER_CONTEXT Gpi;
+} PCH_SMM_CONTEXT;
+
+///
+/// Misc data for PchDispatcher usage.
+/// For PeriodicTimer, since the ElapsedTime is removed from EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT of EDKII,
+/// and PchDispatcher needs it for every record. Thus move it here to support ElapsedTime.
+///
+typedef union {
+ UINTN ElapsedTime;
+} PCH_SMM_MISC_DATA;
+
+//
+// Assumption: PeriodicTimer largest at 3x64-bits or 24 bytes
+//
+typedef struct _DATABASE_RECORD DATABASE_RECORD;
+
+///
+/// Assumption: the GET_CONTEXT function will be as small and simple as possible.
+/// Assumption: We don't need to pass in an enumeration for the protocol because each
+/// GET_CONTEXT function is written for only one protocol.
+/// We also need a function to compare contexts to see if the child should be dispatched
+/// In addition, we need a function to acquire CommBuffer and CommBufferSize for
+/// dispatch callback function of EDKII native support.
+///
+typedef
+VOID
+(EFIAPI *GET_CONTEXT) (
+ IN DATABASE_RECORD * Record,
+ OUT PCH_SMM_CONTEXT * Context
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *CMP_CONTEXT) (
+ IN PCH_SMM_CONTEXT * Context1,
+ IN PCH_SMM_CONTEXT * Context2
+ );
+
+typedef
+VOID
+(EFIAPI *GET_COMMBUFFER) (
+ IN DATABASE_RECORD * Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN * CommBufferSize
+ );
+
+///
+/// Finally, every protocol will require a "Get Context" and "Compare Context" call, so
+/// we may as well wrap that up in a table, too.
+///
+typedef struct {
+ GET_CONTEXT GetContext;
+ CMP_CONTEXT CmpContext;
+ GET_COMMBUFFER GetCommBuffer;
+} CONTEXT_FUNCTIONS;
+
+extern CONTEXT_FUNCTIONS ContextFunctions[PCH_SMM_PROTOCOL_TYPE_MAX];
+
+///
+/// MAPPING CONTEXT TO BIT DESCRIPTIONS
+/// I'd like to have a general approach to mapping contexts to bit descriptions.
+/// Sometimes, we'll find that we can use table lookups or constant assignments;
+/// other times, we'll find that we'll need to use a function to perform the mapping.
+/// If we define a macro to mask that process, we'll never have to change the code.
+/// I don't know if this is desirable or not -- if it isn't, then we can get rid
+/// of the macros and just use function calls or variable assignments. Doesn't matter
+/// to me.
+/// Mapping complex contexts requires a function
+///
+
+/**
+ Maps a USB context to a source description.
+
+ @param[in] Context The context we need to map. Type must be USB.
+ @param[out] SrcDesc The source description that corresponds to the given context.
+
+**/
+VOID
+MapUsbToSrcDesc (
+ IN PCH_SMM_CONTEXT *Context,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Figure out which timer the child is requesting and
+ send back the source description
+
+ @param[in] DispatchContext The pointer to the Dispatch Context instances
+ @param[out] SrcDesc The pointer to the source description
+
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+//
+// Mapping simple contexts can be done by assignment or lookup table
+//
+extern CONST PCH_SMM_SOURCE_DESC SW_SOURCE_DESC;
+extern CONST PCH_SMM_SOURCE_DESC SX_SOURCE_DESC;
+extern CONST PCH_SMM_SOURCE_DESC POWER_BUTTON_SOURCE_DESC;
+
+//
+// With the changes we've made to the protocols, we can now use table
+// lookups for the following protocols:
+//
+extern CONST PCH_SMM_SOURCE_DESC PCH_GPI_SOURCE_DESC_TEMPLATE;
+
+///
+/// For PCHx, APMC is UINT8 port, so the MAX SWI Value is 0xFF.
+///
+#define MAXIMUM_SWI_VALUE 0xFF
+///
+/// Open: Need to make sure this kind of type cast will actually work.
+/// May need an intermediate form w/ two VOID* arguments. I'll figure
+/// that out when I start compiling.
+///
+typedef
+VOID
+(EFIAPI *PCH_SMM_CLEAR_SOURCE) (
+ PCH_SMM_SOURCE_DESC * SrcDesc
+ );
+
+///
+/// "DATABASE" RECORD
+/// Linked list data structures
+///
+#define DATABASE_RECORD_SIGNATURE SIGNATURE_32 ('D', 'B', 'R', 'C')
+
+struct _DATABASE_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ BOOLEAN Processed;
+ ///
+ /// Status and Enable bit description
+ ///
+ PCH_SMM_SOURCE_DESC SrcDesc;
+
+ ///
+ /// Callback function
+ ///
+ EFI_SMM_HANDLER_ENTRY_POINT2 Callback;
+ PCH_SMM_CONTEXT ChildContext;
+
+ ///
+ /// Special handling hooks -- init them to NULL if unused/unneeded
+ ///
+ PCH_SMM_CLEAR_SOURCE ClearSource; ///< needed for SWSMI timer
+
+ ///
+ /// Functions required to make callback code general
+ ///
+ CONTEXT_FUNCTIONS ContextFunctions;
+
+ ///
+ /// The protocol that this record dispatches
+ ///
+ PCH_SMM_PROTOCOL_TYPE ProtocolType;
+
+ ///
+ /// Misc data for private usage
+ ///
+ PCH_SMM_MISC_DATA MiscData;
+
+ ///
+ /// PCH SMI callback function
+ ///
+ PCH_SMI_CALLBACK_FUNCTIONS PchSmiCallback;
+ ///
+ /// Indicate the PCH SMI types.
+ ///
+ PCH_SMI_TYPES PchSmiType;
+};
+
+#define DATABASE_RECORD_FROM_LINK(_record) CR (_record, DATABASE_RECORD, Link, DATABASE_RECORD_SIGNATURE)
+#define DATABASE_RECORD_FROM_CHILDCONTEXT(_record) CR (_record, DATABASE_RECORD, ChildContext, DATABASE_RECORD_SIGNATURE)
+
+///
+/// HOOKING INTO THE ARCHITECTURE
+///
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_REGISTER) (
+ IN VOID **This,
+ IN VOID *DispatchFunction,
+ IN VOID *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_UNREGISTER) (
+ IN VOID **This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+///
+/// Define a memory "stamp" equivalent in size and function to most of the protocols
+///
+typedef struct {
+ PCH_SMM_GENERIC_REGISTER Register;
+ PCH_SMM_GENERIC_UNREGISTER Unregister;
+ UINTN Extra1;
+ UINTN Extra2; ///< may not need this one
+} PCH_SMM_GENERIC_PROTOCOL;
+
+/**
+ Register a child SMI dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source.
+ @param[in] DispatchContext Pointer to the dispatch function's context.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database record
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+PchSmmCoreRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchSmmCoreUnRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE *DispatchHandle
+ );
+
+typedef union {
+ PCH_SMM_GENERIC_PROTOCOL Generic;
+ EFI_SMM_USB_DISPATCH2_PROTOCOL Usb;
+ EFI_SMM_SX_DISPATCH2_PROTOCOL Sx;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL Sw;
+ EFI_SMM_GPI_DISPATCH2_PROTOCOL Gpi;
+ EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL PowerButton;
+ EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL PeriodicTimer;
+} PCH_SMM_PROTOCOL;
+
+///
+/// Define a structure to help us identify the generic protocol
+///
+#define PROTOCOL_SIGNATURE SIGNATURE_32 ('P', 'R', 'O', 'T')
+
+typedef struct {
+ UINTN Signature;
+
+ PCH_SMM_PROTOCOL_TYPE Type;
+ EFI_GUID *Guid;
+ PCH_SMM_PROTOCOL Protocols;
+} PCH_SMM_QUALIFIED_PROTOCOL;
+
+#define QUALIFIED_PROTOCOL_FROM_GENERIC(_generic) \
+ CR ( \
+ _generic, \
+ PCH_SMM_QUALIFIED_PROTOCOL, \
+ Protocols, \
+ PROTOCOL_SIGNATURE \
+ )
+
+///
+/// Create private data for the protocols that we'll publish
+///
+typedef struct {
+ LIST_ENTRY CallbackDataBase;
+ EFI_HANDLE SmiHandle;
+ EFI_HANDLE InstallMultProtHandle;
+ PCH_SMM_QUALIFIED_PROTOCOL Protocols[PCH_SMM_PROTOCOL_TYPE_MAX];
+} PRIVATE_DATA;
+
+extern PRIVATE_DATA mPrivateData;
+extern UINT16 mAcpiBaseAddr;
+extern UINT16 mTcoBaseAddr;
+/**
+ Get the Software Smi value
+
+ @param[in] Record No use
+ @param[out] Context The context that includes Software Smi value to be filled
+
+**/
+VOID
+EFIAPI
+SwGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether software SMI value of two contexts match
+
+ @param[in] Context1 Context 1 that includes software SMI value 1
+ @param[in] Context2 Context 2 that includes software SMI value 2
+
+ @retval FALSE Software SMI value match
+ @retval TRUE Software SMI value don't match
+**/
+BOOLEAN
+EFIAPI
+SwCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Gather the CommBuffer information of SmmSwDispatch2.
+
+ @param[in] Record No use
+ @param[out] CommBuffer Point to the CommBuffer structure
+ @param[out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+SwGetCommBuffer (
+ IN DATABASE_RECORD *Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN *CommBufferSize
+ );
+
+/**
+ Get the Sleep type
+
+ @param[in] Record No use
+ @param[out] Context The context that includes SLP_TYP bits to be filled
+
+**/
+VOID
+EFIAPI
+SxGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Init required protocol for Pch Sw Dispatch protocol.
+
+
+**/
+VOID
+PchSwDispatchInit (
+ VOID
+ );
+
+/**
+ Check whether sleep type of two contexts match
+
+ @param[in] Context1 Context 1 that includes sleep type 1
+ @param[in] Context2 Context 2 that includes sleep type 2
+
+ @retval FALSE Sleep types match
+ @retval TRUE Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Update the elapsed time from the Interval data of DATABASE_RECORD
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] HwContext The Context to be updated.
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether Periodic Timer of two contexts match
+
+ @param[in] Context1 Context 1 that includes Periodic Timer 1
+ @param[in] Context2 Context 2 that includes Periodic Timer 2
+
+ @retval FALSE Periodic Timer match
+ @retval TRUE Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Gather the CommBuffer information of SmmPeriodicTimerDispatch2.
+
+ @param[in] Record No use
+ @param[out] CommBuffer Point to the CommBuffer structure
+ @param[out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetCommBuffer (
+ IN DATABASE_RECORD *Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN *CommBufferSize
+ );
+
+/**
+ Get the power button status.
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] Context Calling context from the hardware, will be updated with the current power button status.
+
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether Power Button status of two contexts match
+
+ @param[in] Context1 Context 1 that includes Power Button status 1
+ @param[in] Context2 Context 2 that includes Power Button status 2
+
+ @retval FALSE Power Button status match
+ @retval TRUE Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ This function is responsible for calculating and enabling any timers that are required
+ to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ This services returns the next SMI tick period that is supported by the chipset.
+ The order returned is from longest to shortest interval period.
+
+ @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+ @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+ @retval EFI_SUCCESS The service returned successfully.
+ @retval EFI_INVALID_PARAMETER The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+ IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This,
+ IN OUT UINT64 **SmiTickInterval
+ );
+
+/**
+ Install PCH SMM periodic timer control protocol
+
+ @param[in] Handle handle for this driver
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSmmPeriodicTimerControlProtocol (
+ IN EFI_HANDLE Handle
+ );
+
+/**
+ When we get an SMI that indicates that we are transitioning to a sleep state,
+ we need to actually transition to that state. We do this by disabling the
+ "SMI on sleep enable" feature, which generates an SMI when the operating system
+ tries to put the system to sleep, and then physically putting the system to sleep.
+**/
+VOID
+PchSmmSxGoToSleep (
+ VOID
+ );
+
+/**
+ Check and clear NEWCENTURY_STS.
+ It will clear the SMI status once it happens.
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+**/
+VOID
+EFIAPI
+PchTcoClearNewCenturySts (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Install protocols of PCH specifics SMI types, including
+ PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
+
+ @retval the result of protocol installation
+**/
+EFI_STATUS
+InstallPchSmiDispatchProtocols (
+ VOID
+ );
+
+/**
+ The function to dispatch all callback function of PCH SMI types.
+
+ @retval EFI_SUCCESS Function successfully completed
+ @retval EFI_UNSUPPORTED no
+**/
+EFI_STATUS
+PchSmiTypeCallbackDispatcher (
+ IN DATABASE_RECORD *Record
+ );
+
+/**
+ The register function used to register SMI handler of IoTrap event.
+ This is internal function and only used by Iotrap module.
+
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] IoTrapIndex Index number of IOTRAP register
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiRegister (
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN IoTrapIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiUnRegister (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register an eSPI SMI handler based on the type
+
+ @param[in] DispatchFunction Callback in an event of eSPI SMI
+ @param[in] PchSmiTypes The eSPI type published by PchSmiDispatch
+ @param[out] DispatchHandle The callback handle
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS Registration is successful.
+**/
+EFI_STATUS
+PchInternalEspiSmiRegister (
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN PCH_SMI_TYPES PchSmiTypes,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister an eSPI SMI handler
+
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchInternalEspiSmiUnRegister (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ The internal function used to create and insert a database record
+ for SMI record of Pch Smi types.
+
+ @param[in] SrcDesc The pointer to the SMI source description
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] PchSmiType Specific SMI type of PCH SMI
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchSmiRecordInsert (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc,
+ IN PCH_SMI_CALLBACK_FUNCTIONS DispatchFunction,
+ IN PCH_SMI_TYPES PchSmiType,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+extern PCH_SMM_SOURCE_DESC mSrcDescSerialIrq;
+
+/**
+ Clear the TCO SMI status bit after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSource (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Initialize Source descriptor structure
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+NullInitSourceDesc (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
new file mode 100644
index 0000000000..977a7ec57c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
@@ -0,0 +1,952 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+Copyright (c) 2017, 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 that 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 "PchSmm.h"
+#include "PchSmmHelpers.h"
+#include "PchSmmEspi.h"
+
+//
+// MODULE / GLOBAL DATA
+//
+// Module variables used by the both the main dispatcher and the source dispatchers
+// Declared in PchSmm.h
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mAcpiBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mTcoBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mReadyToLock;
+
+GLOBAL_REMOVE_IF_UNREFERENCED PRIVATE_DATA mPrivateData = {
+ {
+ NULL,
+ NULL
+ }, ///< CallbackDataBase linked list head
+ NULL, ///< EFI handle returned when calling InstallMultipleProtocolInterfaces
+ NULL, //
+ { ///< protocol arrays
+ ///
+ /// elements within the array
+ ///
+ {
+ PROTOCOL_SIGNATURE,
+ UsbType,
+ &gEfiSmmUsbDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ SxType,
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ SwType,
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ (UINTN) MAXIMUM_SWI_VALUE
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ GpiType,
+ &gEfiSmmGpiDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ (UINTN) V_PCH_GPIO_NUM_SUPPORTED_GPIS
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ PowerButtonType,
+ &gEfiSmmPowerButtonDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ PeriodicTimerType,
+ &gEfiSmmPeriodicTimerDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSmmCoreUnRegister,
+ (UINTN) PchSmmPeriodicTimerDispatchGetNextShorterInterval
+ }}
+ },
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONTEXT_FUNCTIONS mContextFunctions[PCH_SMM_PROTOCOL_TYPE_MAX] = {
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ SxGetContext,
+ SxCmpContext,
+ NULL
+ },
+ {
+ SwGetContext,
+ SwCmpContext,
+ SwGetCommBuffer
+ },
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ PowerButtonGetContext,
+ PowerButtonCmpContext,
+ NULL
+ },
+ {
+ PeriodicTimerGetContext,
+ PeriodicTimerCmpContext,
+ PeriodicTimerGetCommBuffer
+ },
+};
+
+//
+// PROTOTYPES
+//
+// Functions use only in this file
+//
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+ IN EFI_HANDLE SmmImageHandle,
+ IN CONST VOID *PchSmmCore, OPTIONAL
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ );
+
+//
+// FUNCTIONS
+//
+/**
+ SMM ready to lock notification event handler.
+
+ @param Protocol Points to the protocol's unique identifier
+ @param Interface Points to the interface instance
+ @param Handle The handle on which the interface was installed
+
+ @retval EFI_SUCCESS SmmReadyToLockCallback runs successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SmmReadyToLockCallback (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ mReadyToLock = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ <b>PchSmiDispatcher SMM Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchSmiDispatcher module is an SMM driver which provides SMI handler registration
+ services for PCH generated SMIs.
+
+ - <b>Details</b>\n
+ This module provides SMI handler registration servicies for PCH SMIs.
+ NOTE: All the register/unregister functions will be locked after SMM ready to boot signal event.
+ Please make sure no handler is installed after that.
+
+ - @pre
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in the System Management Mode Core Interface Specification
+ - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ - Documented in the UEFI 2.0 Specification and above
+ - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+ - EFI_SMM_CPU_PROTOCOL
+
+ - @result
+ The PchSmiDispatcher driver produces:
+ - EFI_SMM_USB_DISPATCH2_PROTOCOL
+ - EFI_SMM_SX_DISPATCH2_PROTOCOL
+ - EFI_SMM_SW_DISPATCH2_PROTOCOL
+ - EFI_SMM_GPI_DISPATCH2_PROTOCOL
+ - EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL
+ - EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL
+ - EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL
+ - @link _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_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_ACPI_SMI_DISPATCH_PROTOCOL PCH_ACPI_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL PCH_GPIO_UNLOCK_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_ESPI_SMI_DISPATCH_PROTOCOL PCH_ESPI_SMI_DISPATCH_PROTOCOL @endlink
+
+ @param[in] ImageHandle Pointer to the loaded image protocol for this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS PchSmmDispatcher Initialization completed.
+**/
+EFI_STATUS
+EFIAPI
+InitializePchSmmDispatcher (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINTN LpcBaseAddress;
+ EFI_STATUS Status;
+ VOID *SmmReadyToLockRegistration;
+
+ ///
+ /// Access ACPI Base Addresses Register
+ ///
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ PchAcpiBaseGet (&mAcpiBaseAddr);
+ ASSERT (mAcpiBaseAddr != 0);
+
+ ///
+ /// Access TCO Base Addresses Register
+ ///
+ PchTcoBaseGet (&mTcoBaseAddr);
+ ASSERT (mTcoBaseAddr != 0);
+
+
+ PchSwDispatchInit ();
+
+ ///
+ /// Register a callback function to handle subsequent SMIs. This callback
+ /// will be called by SmmCoreDispatcher.
+ ///
+ Status = gSmst->SmiHandlerRegister (PchSmmCoreDispatcher, NULL, &mPrivateData.SmiHandle);
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Initialize Callback DataBase
+ ///
+ InitializeListHead (&mPrivateData.CallbackDataBase);
+
+ ///
+ /// Enable SMIs on the PCH now that we have a callback
+ ///
+ PchSmmInitHardware ();
+
+ //
+ // Install and initialize all the needed protocols
+ //
+ PchSmmPublishDispatchProtocols ();
+ InstallPchSmiDispatchProtocols ();
+ InstallIoTrap (ImageHandle);
+ InstallEspiSmi (ImageHandle);
+ InstallPchSmmPeriodicTimerControlProtocol (mPrivateData.InstallMultProtHandle);
+
+ //
+ // Register EFI_SMM_READY_TO_LOCK_PROTOCOL_GUID notify function.
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmReadyToLockProtocolGuid,
+ SmmReadyToLockCallback,
+ &SmmReadyToLockRegistration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check the Fed SwSmiInputValue to see if there is a duplicated one in the database
+
+ @param[in] FedSwSmiInputValue Fed SwSmiInputValue
+
+ @retval EFI_SUCCESS There is no duplicated SwSmiInputValue
+ @retval EFI_INVALID_PARAMETER There is a duplicated SwSmiInputValue
+**/
+EFI_STATUS
+SmiInputValueDuplicateCheck (
+ UINTN FedSwSmiInputValue
+ )
+{
+
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+ if (RecordInDb->ProtocolType == SwType) {
+ if (RecordInDb->ChildContext.Sw.SwSmiInputValue == FedSwSmiInputValue) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Register a child SMI dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source.
+ @param[in] DispatchContext Pointer to the dispatch function's context.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database record
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+PchSmmCoreRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+ PCH_SMM_QUALIFIED_PROTOCOL *Qualified;
+ PCH_SMM_SOURCE_DESC NullSourceDesc;
+ UINTN Index;
+ GPIO_PAD GpioPad;
+ UINT8 GpiSmiBitOffset;
+ UINT32 GpiSmiEnRegAddress;
+ UINT32 GpiSmiStsRegAddress;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ //
+ // Initialize NullSourceDesc
+ //
+ NullInitSourceDesc (&NullSourceDesc);
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the EndOfDxe event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Index = 0;
+ ///
+ /// Create database record and add to database
+ ///
+
+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (DATABASE_RECORD), (VOID **) &Record);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ZeroMem (Record, sizeof (DATABASE_RECORD));
+
+ ///
+ /// Gather information about the registration request
+ ///
+ Record->Callback = DispatchFunction;
+
+ Qualified = QUALIFIED_PROTOCOL_FROM_GENERIC (This);
+
+ Record->ProtocolType = Qualified->Type;
+
+ Record->ContextFunctions = mContextFunctions[Qualified->Type];
+ ///
+ /// Perform linked list housekeeping
+ ///
+ Record->Signature = DATABASE_RECORD_SIGNATURE;
+
+ switch (Qualified->Type) {
+ ///
+ /// By the end of this switch statement, we'll know the
+ /// source description the child is registering for
+ ///
+ case UsbType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_USB_REGISTER_CONTEXT));
+ ///
+ /// Check the validity of Context Type
+ ///
+ if ((Record->ChildContext.Usb.Type < UsbLegacy) || (Record->ChildContext.Usb.Type > UsbWake)) {
+ goto Error;
+ }
+
+ MapUsbToSrcDesc (DispatchContext, &(Record->SrcDesc));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case SxType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_SX_REGISTER_CONTEXT));
+ ///
+ /// Check the validity of Context Type and Phase
+ ///
+ if ((Record->ChildContext.Sx.Type < SxS0) ||
+ (Record->ChildContext.Sx.Type >= EfiMaximumSleepType) ||
+ (Record->ChildContext.Sx.Phase < SxEntry) ||
+ (Record->ChildContext.Sx.Phase >= EfiMaximumPhase)
+ ) {
+ goto Error;
+ }
+
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) (&SX_SOURCE_DESC), sizeof (PCH_SMM_SOURCE_DESC));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case SwType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_SW_REGISTER_CONTEXT));
+ ///
+ /// Check the validity of Context Value
+ ///
+ if (Record->ChildContext.Sw.SwSmiInputValue == (UINTN) -1) {
+ for (Index = 1; Index < MAXIMUM_SWI_VALUE; Index++) {
+ if (!EFI_ERROR (SmiInputValueDuplicateCheck (Index))) {
+ Record->ChildContext.Sw.SwSmiInputValue = Index;
+ break;
+ }
+ }
+ if (Record->ChildContext.Sw.SwSmiInputValue == (UINTN) -1) {
+ goto Error;
+ }
+ }
+ if (Record->ChildContext.Sw.SwSmiInputValue > MAXIMUM_SWI_VALUE) {
+ goto Error;
+ }
+
+ if (EFI_ERROR (SmiInputValueDuplicateCheck (Record->ChildContext.Sw.SwSmiInputValue))) {
+ goto Error;
+ }
+ CopyMem (DispatchContext, &Record->ChildContext, sizeof (EFI_SMM_SW_REGISTER_CONTEXT));
+
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) (&SW_SOURCE_DESC), sizeof (PCH_SMM_SOURCE_DESC));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case GpiType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_GPI_REGISTER_CONTEXT));
+
+ Index = Record->ChildContext.Gpi.GpiNum;
+
+ Status = GpioGetPadAndSmiRegs (
+ (UINT32) Index,
+ &GpioPad,
+ &GpiSmiBitOffset,
+ &GpiSmiEnRegAddress,
+ &GpiSmiStsRegAddress
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ CopyMem (
+ (VOID *) &(Record->SrcDesc),
+ (VOID *) &(PCH_GPI_SOURCE_DESC_TEMPLATE),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+ Record->SrcDesc.En[0].Reg.Data.raw = GpiSmiEnRegAddress; // GPI SMI Enable register
+ Record->SrcDesc.En[0].Bit = GpiSmiBitOffset; // Bit position for selected pad
+ Record->SrcDesc.Sts[0].Reg.Data.raw = GpiSmiStsRegAddress; // GPI SMI Status register
+ Record->SrcDesc.Sts[0].Bit = GpiSmiBitOffset; // Bit position for selected pad
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ ///
+ /// Add GPI_SMI_EN programming into S3 boot script
+ ///
+ Data32Or = (1u << GpiSmiBitOffset);
+ Data32And = 0xFFFFFFFF;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, GpiSmiEnRegAddress, &Data32Or, &Data32And);
+
+ break;
+
+ case PowerButtonType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT));
+ ///
+ /// Check the validity of Context Phase
+ ///
+ if ((Record->ChildContext.PowerButton.Phase < EfiPowerButtonEntry) ||
+ (Record->ChildContext.PowerButton.Phase > EfiPowerButtonExit)
+ ) {
+ goto Error;
+ }
+
+ CopyMem ((VOID *) &(Record->SrcDesc), (VOID *) &POWER_BUTTON_SOURCE_DESC, sizeof (PCH_SMM_SOURCE_DESC));
+ Record->ClearSource = NULL;
+ ///
+ /// use default clear source function
+ ///
+ break;
+
+ case PeriodicTimerType:
+ CopyMem (&Record->ChildContext, DispatchContext, sizeof (EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT));
+ ///
+ /// Check the validity of timer value
+ ///
+ if (DispatchContext->PeriodicTimer.SmiTickInterval <= 0) {
+ goto Error;
+ }
+
+ MapPeriodicTimerToSrcDesc (DispatchContext, &(Record->SrcDesc));
+ Record->ClearSource = PchSmmPeriodicTimerClearSource;
+ break;
+
+ default:
+ goto Error;
+ break;
+ }
+
+ if (CompareSources (&Record->SrcDesc, &NullSourceDesc)) {
+ goto Error;
+ }
+
+ ///
+ /// After ensuring the source of event is not null, we will insert the record into the database
+ ///
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+
+ if (Record->ClearSource == NULL) {
+ ///
+ /// Clear the SMI associated w/ the source using the default function
+ ///
+ PchSmmClearSource (&Record->SrcDesc);
+ } else {
+ ///
+ /// This source requires special handling to clear
+ ///
+ Record->ClearSource (&Record->SrcDesc);
+ }
+
+ PchSmmEnableSource (&Record->SrcDesc);
+
+ ///
+ /// Child's handle will be the address linked list link in the record
+ ///
+ *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+ return EFI_SUCCESS;
+
+Error:
+ Status = gSmst->SmmFreePool (Record);
+ ///
+ /// DEBUG((DEBUG_ERROR,"Free pool status %d\n", Status ));
+ ///
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchSmmCoreUnRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN NeedClearEnable;
+ UINTN DescIndex;
+ DATABASE_RECORD *RecordToDelete;
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+
+ if (DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+
+ //
+ // Take the entry out of the linked list
+ //
+ if (RecordToDelete->Link.ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RemoveEntryList (&RecordToDelete->Link);
+
+ //
+ // Loop through all the souces in record linked list to see if any source enable is equal.
+ // If any source enable is equal, we do not want to disable it.
+ //
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; ++DescIndex) {
+ if (IS_BIT_DESC_NULL (RecordToDelete->SrcDesc.En[DescIndex])) {
+ continue;
+ }
+ NeedClearEnable = TRUE;
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (IsBitEqualToAnySourceEn (&RecordToDelete->SrcDesc.En[DescIndex], &RecordInDb->SrcDesc)) {
+ NeedClearEnable = FALSE;
+ break;
+ }
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+ if (NeedClearEnable == FALSE) {
+ continue;
+ }
+ WriteBitDesc (&RecordToDelete->SrcDesc.En[DescIndex], 0, FALSE);
+ }
+
+ Status = gSmst->SmmFreePool (RecordToDelete);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return Status;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function clears the pending SMI status before set EOS.
+ NOTE: This only clears the pending SMI with known reason.
+ Please do not clear unknown pending SMI status since that will hide potential issues.
+
+ @param[in] SmiStsValue SMI status
+**/
+static
+VOID
+ClearPendingSmiStatus (
+ UINT32 SmiStsValue
+ )
+{
+ //
+ // Clear NewCentury status if it's not handled.
+ //
+ if (SmiStsValue & B_PCH_SMI_STS_TCO) {
+ PchTcoClearNewCenturySts (NULL);
+ }
+ // Clear PWRBTNOR_STS if it's not handled.
+ //
+ if (IoRead16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS) & B_PCH_ACPI_PM1_STS_PRBTNOR) {
+ IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_PRBTNOR);
+ }
+ //
+ // Clear SWSMI if this is triggered by SmmControl.
+ //
+ if (SmiStsValue & B_PCH_SMI_STS_APM) {
+ IoWrite32 (mAcpiBaseAddr + R_PCH_SMI_STS, B_PCH_SMI_STS_APM);
+ }
+}
+
+/**
+ The callback function to handle subsequent SMIs. This callback will be called by SmmCoreDispatcher.
+
+ @param[in] SmmImageHandle Not used
+ @param[in] PchSmmCore Not used
+ @param[in, out] CommunicationBuffer Not used
+ @param[in, out] SourceSize Not used
+
+ @retval EFI_SUCCESS Function successfully completed
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+ IN EFI_HANDLE SmmImageHandle,
+ IN CONST VOID *PchSmmCore,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ )
+{
+ ///
+ /// Used to prevent infinite loops
+ ///
+ UINTN EscapeCount;
+
+ BOOLEAN ContextsMatch;
+ BOOLEAN EosSet;
+ BOOLEAN SxChildWasDispatched;
+
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ DATABASE_RECORD *RecordToExhaust;
+ LIST_ENTRY *LinkToExhaust;
+
+ PCH_SMM_CONTEXT Context;
+ VOID *CommBuffer;
+ UINTN CommBufferSize;
+
+ EFI_STATUS Status;
+ BOOLEAN SciEn;
+ UINT32 SmiEnValue;
+ UINT32 SmiStsValue;
+ UINT8 Port74Save;
+ UINT8 Port76Save;
+
+ PCH_SMM_SOURCE_DESC ActiveSource;
+
+ //
+ // Initialize ActiveSource
+ //
+ NullInitSourceDesc (&ActiveSource);
+
+ EscapeCount = 3;
+ ContextsMatch = FALSE;
+ EosSet = FALSE;
+ SxChildWasDispatched = FALSE;
+ Status = EFI_SUCCESS;
+
+ //
+ // Save IO index registers
+ // @note: Save/Restore port 70h directly might break NMI_EN# setting,
+ // then save/restore 74h/76h instead.
+ // @note: CF8 is not saved. Prefer method is to use MMIO instead of CF8
+ //
+ Port76Save = IoRead8 (R_PCH_RTC_EXT_INDEX_ALT);
+ Port74Save = IoRead8 (R_PCH_RTC_INDEX_ALT);
+
+ if (!IsListEmpty (&mPrivateData.CallbackDataBase)) {
+ ///
+ /// We have children registered w/ us -- continue
+ ///
+ while ((!EosSet) && (EscapeCount > 0)) {
+ EscapeCount--;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+
+ ///
+ /// Cache SciEn, SmiEnValue and SmiStsValue to determine if source is active
+ ///
+ SciEn = PchSmmGetSciEn ();
+ SmiEnValue = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+ SmiStsValue = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS));
+
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+ ///
+ /// look for the first active source
+ ///
+ if (!SourceIsActive (&RecordInDb->SrcDesc, SciEn, SmiEnValue, SmiStsValue)) {
+ ///
+ /// Didn't find the source yet, keep looking
+ ///
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+
+ ///
+ /// if it's the last one, try to clear EOS
+ ///
+ if (IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ //
+ // Clear pending SMI status before EOS
+ //
+ ClearPendingSmiStatus (SmiStsValue);
+ EosSet = PchSmmSetAndCheckEos ();
+ }
+ } else {
+ ///
+ /// We found a source. If this is a sleep type, we have to go to
+ /// appropriate sleep state anyway.No matter there is sleep child or not
+ ///
+ if (RecordInDb->ProtocolType == SxType) {
+ SxChildWasDispatched = TRUE;
+ }
+ ///
+ /// "cache" the source description and don't query I/O anymore
+ ///
+ CopyMem ((VOID *) &ActiveSource, (VOID *) &(RecordInDb->SrcDesc), sizeof (PCH_SMM_SOURCE_DESC));
+ LinkToExhaust = LinkInDb;
+
+ ///
+ /// exhaust the rest of the queue looking for the same source
+ ///
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkToExhaust)) {
+ RecordToExhaust = DATABASE_RECORD_FROM_LINK (LinkToExhaust);
+ ///
+ /// RecordToExhaust->Link might be removed (unregistered) by Callback function, and then the
+ /// system will hang in ASSERT() while calling GetNextNode().
+ /// To prevent the issue, we need to get next record in DB here (before Callback function).
+ ///
+ LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, &RecordToExhaust->Link);
+
+ if (CompareSources (&RecordToExhaust->SrcDesc, &ActiveSource)) {
+ ///
+ /// These source descriptions are equal, so this callback should be
+ /// dispatched.
+ ///
+ if (RecordToExhaust->ContextFunctions.GetContext != NULL) {
+ ///
+ /// This child requires that we get a calling context from
+ /// hardware and compare that context to the one supplied
+ /// by the child.
+ ///
+ ASSERT (RecordToExhaust->ContextFunctions.CmpContext != NULL);
+
+ ///
+ /// Make sure contexts match before dispatching event to child
+ ///
+ RecordToExhaust->ContextFunctions.GetContext (RecordToExhaust, &Context);
+ ContextsMatch = RecordToExhaust->ContextFunctions.CmpContext (&Context, &RecordToExhaust->ChildContext);
+
+ } else {
+ ///
+ /// This child doesn't require any more calling context beyond what
+ /// it supplied in registration. Simply pass back what it gave us.
+ ///
+ Context = RecordToExhaust->ChildContext;
+ ContextsMatch = TRUE;
+ }
+
+ if (ContextsMatch) {
+ if (RecordToExhaust->ProtocolType == PchSmiDispatchType) {
+ //
+ // For PCH SMI dispatch protocols
+ //
+ PchSmiTypeCallbackDispatcher (RecordToExhaust);
+ } else {
+ //
+ // For EFI standard SMI dispatch protocols
+ //
+ if (RecordToExhaust->Callback != NULL) {
+ if (RecordToExhaust->ContextFunctions.GetCommBuffer != NULL) {
+ ///
+ /// This callback function needs CommBuffer and CommBufferSize.
+ /// Get those from child and then pass to callback function.
+ ///
+ RecordToExhaust->ContextFunctions.GetCommBuffer (RecordToExhaust, &CommBuffer, &CommBufferSize);
+ } else {
+ ///
+ /// Child doesn't support the CommBuffer and CommBufferSize.
+ /// Just pass NULL value to callback function.
+ ///
+ CommBuffer = NULL;
+ CommBufferSize = 0;
+ }
+
+ PERF_START_EX (NULL, "SmmFunction", NULL, AsmReadTsc (), RecordToExhaust->ProtocolType);
+ RecordToExhaust->Callback ((EFI_HANDLE) & RecordToExhaust->Link, &Context, CommBuffer, &CommBufferSize);
+ PERF_END_EX (NULL, "SmmFunction", NULL, AsmReadTsc (), RecordToExhaust->ProtocolType);
+ if (RecordToExhaust->ProtocolType == SxType) {
+ SxChildWasDispatched = TRUE;
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ }
+ }
+ }
+
+ if (RecordInDb->ClearSource == NULL) {
+ ///
+ /// Clear the SMI associated w/ the source using the default function
+ ///
+ PchSmmClearSource (&ActiveSource);
+ } else {
+ ///
+ /// This source requires special handling to clear
+ ///
+ RecordInDb->ClearSource (&ActiveSource);
+ }
+ //
+ // Clear pending SMI status before EOS
+ //
+ ClearPendingSmiStatus (SmiStsValue);
+ ///
+ /// Also, try to clear EOS
+ ///
+ EosSet = PchSmmSetAndCheckEos ();
+ ///
+ /// Queue is empty, reset the search
+ ///
+ break;
+ }
+ }
+ }
+ }
+ ///
+ /// If you arrive here, there are two possible reasons:
+ /// (1) you've got problems with clearing the SMI status bits in the
+ /// ACPI table. If you don't properly clear the SMI bits, then you won't be able to set the
+ /// EOS bit. If this happens too many times, the loop exits.
+ /// (2) there was a SMM communicate for callback messages that was received prior
+ /// to this driver.
+ /// If there is an asynchronous SMI that occurs while processing the Callback, let
+ /// all of the drivers (including this one) have an opportunity to scan for the SMI
+ /// and handle it.
+ /// If not, we don't want to exit and have the foreground app. clear EOS without letting
+ /// these other sources get serviced.
+ ///
+ /// This assert is not valid with CSM legacy solution because it generates software SMI
+ /// to test for legacy USB support presence.
+ /// This may not be illegal, so we cannot assert at this time.
+ ///
+ /// ASSERT (EscapeCount > 0);
+ ///
+ if (SxChildWasDispatched) {
+ ///
+ /// A child of the SmmSxDispatch protocol was dispatched during this call;
+ /// put the system to sleep.
+ ///
+ PchSmmSxGoToSleep ();
+ }
+ //
+ // Restore IO index registers
+ // @note: Save/Restore port 70h directly might break NMI_EN# setting,
+ // then save/restore 74h/76h instead.
+ //
+ IoWrite8 (R_PCH_RTC_EXT_INDEX_ALT, Port76Save);
+ IoWrite8 (R_PCH_RTC_INDEX_ALT, Port74Save);
+
+ return Status;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c
new file mode 100644
index 0000000000..8484be18ea
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c
@@ -0,0 +1,1385 @@
+/** @file
+ eSPI SMI implementation
+
+Copyright (c) 2017, 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 that 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 "PchSmmEspi.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED ESPI_SMI_INSTANCE mEspiSmiInstance = {
+ //
+ // Signature
+ //
+ ESPI_SMI_INSTANCE_SIGNATURE,
+ //
+ // Handle
+ //
+ NULL,
+ //
+ // PchEspiSmiDispatchProtocol
+ //
+ {
+ PCH_ESPI_SMI_DISPATCH_REVISION,
+ EspiSmiUnRegister,
+ BiosWrProtectRegister,
+ BiosWrReportRegister,
+ PcNonFatalErrRegister,
+ PcFatalErrRegister,
+ VwNonFatalErrRegister,
+ VwFatalErrRegister,
+ FlashNonFatalErrRegister,
+ FlashFatalErrRegister,
+ LnkType1ErrRegister,
+ EspiSlaveSmiRegister
+ },
+ //
+ // PchSmiEspiHandle[EspiTopLevelTypeMax]
+ //
+ {
+ NULL, NULL, NULL
+ },
+ //
+ // CallbackDataBase[EspiSmiTypeMax]
+ //
+ {
+ {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL},
+ {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL}
+ },
+ //
+ // EspiSmiEventCounter[EspiSmiTypeMax]
+ //
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ //
+ // Barrier[EspiTopLevelTypeMax]
+ //
+ {
+ {
+ BiosWrProtect,
+ BiosWrProtect
+ },
+ {
+ BiosWrReport,
+ LnkType1Err
+ },
+ {
+ EspiSlaveSmi,
+ EspiSlaveSmi
+ }
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST ESPI_DESCRIPTOR mEspiDescriptor[EspiSmiTypeMax] = {
+ //
+ // BiosWrProtect
+ //
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_PCH_ESPI_PCBC
+ ) }
+ },
+ //
+ // SourceIsActiveAndMask and SourceIsActiveValue
+ //
+ B_PCH_ESPI_PCBC_BWPDS | B_PCH_ESPI_PCBC_LE,
+ B_PCH_ESPI_PCBC_BWPDS | B_PCH_ESPI_PCBC_LE,
+ //
+ // ClearStatusAndMask and ClearStatusOrMask
+ //
+ (UINT32) ~B_PCH_ESPI_PCBC_BWRS,
+ B_PCH_ESPI_PCBC_BWPDS
+ },
+ //
+ // BiosWrReport
+ //
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_PCH_ESPI_PCBC
+ ) }
+ },
+ B_PCH_ESPI_PCBC_BWRS | B_PCH_ESPI_PCBC_BWRE,
+ B_PCH_ESPI_PCBC_BWRS | B_PCH_ESPI_PCBC_BWRE,
+ (UINT32) ~B_PCH_ESPI_PCBC_BWPDS,
+ B_PCH_ESPI_PCBC_BWRS
+ },
+ //
+ // PcNonFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_PCERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ (B_PCH_PCR_ESPI_XERR_XNFES | (V_PCH_PCR_ESPI_XERR_XNFEE_SMI << N_PCH_PCR_ESPI_XERR_XNFEE)),
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XNFES
+ },
+ //
+ // PcFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_PCERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ (B_PCH_PCR_ESPI_XERR_XFES | (V_PCH_PCR_ESPI_XERR_XFEE_SMI << N_PCH_PCR_ESPI_XERR_XFEE)),
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XNFES),
+ B_PCH_PCR_ESPI_XERR_XFES
+ },
+ //
+ // VwNonFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_VWERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ (B_PCH_PCR_ESPI_XERR_XNFES | (V_PCH_PCR_ESPI_XERR_XNFEE_SMI << N_PCH_PCR_ESPI_XERR_XNFEE)),
+ (UINT32) ~B_PCH_PCR_ESPI_XERR_XFES,
+ B_PCH_PCR_ESPI_XERR_XNFES
+ },
+ //
+ // VwFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_VWERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ (B_PCH_PCR_ESPI_XERR_XFES | (V_PCH_PCR_ESPI_XERR_XFEE_SMI << N_PCH_PCR_ESPI_XERR_XFEE)),
+ (UINT32) ~B_PCH_PCR_ESPI_XERR_XNFES,
+ B_PCH_PCR_ESPI_XERR_XFES
+ },
+ //
+ // FlashNonFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_FCERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ (B_PCH_PCR_ESPI_XERR_XNFES | (V_PCH_PCR_ESPI_XERR_XNFEE_SMI << N_PCH_PCR_ESPI_XERR_XNFEE)),
+ (UINT32) ~B_PCH_PCR_ESPI_XERR_XFES,
+ B_PCH_PCR_ESPI_XERR_XNFES
+ },
+ //
+ // FlashFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_FCERR_SLV0) }
+ },
+ (B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ (B_PCH_PCR_ESPI_XERR_XFES | (V_PCH_PCR_ESPI_XERR_XFEE_SMI << N_PCH_PCR_ESPI_XERR_XFEE)),
+ (UINT32) ~B_PCH_PCR_ESPI_XERR_XNFES,
+ B_PCH_PCR_ESPI_XERR_XFES
+ },
+ //
+ // LnkType1Err
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_PCH_PCR_ESPI_LNKERR_SLV0) }
+ },
+ B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S | B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E,
+ B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S | (V_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E_SMI << N_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E),
+ (UINT32) ~B_PCH_PCR_ESPI_LNKERR_SLV0_SLCRR,
+ B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S
+ },
+};
+
+/**
+ Enable eSPI SMI source
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+VOID
+EspiSmiEnableSource (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ EFI_STATUS Status;
+ UINTN PciBaseAddress;
+
+ switch (EspiSmiType) {
+ case BiosWrProtect:
+ PciBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ MmioAndThenOr32 (
+ PciBaseAddress + R_PCH_ESPI_PCBC,
+ (UINT32) ~(B_PCH_ESPI_PCBC_BWRS | B_PCH_ESPI_PCBC_BWPDS),
+ B_PCH_ESPI_PCBC_LE
+ );
+ break;
+ case BiosWrReport:
+ PciBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ MmioAndThenOr32 (
+ PciBaseAddress + R_PCH_ESPI_PCBC,
+ (UINT32) ~(B_PCH_ESPI_PCBC_BWRS | B_PCH_ESPI_PCBC_BWPDS),
+ B_PCH_ESPI_PCBC_BWRE
+ );
+ break;
+ case PcNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_PCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XNFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case PcFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_PCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case VwNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_VWERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XNFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case VwFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_VWERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case FlashNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_FCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XNFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case FlashFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_FCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES),
+ B_PCH_PCR_ESPI_XERR_XFEE);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case LnkType1Err:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_LNKERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_LNKERR_SLV0_SLCRR | B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S),
+ B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1E);
+ ASSERT_EFI_ERROR (Status);
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported EspiSmiType \n"));
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+
+/**
+ Disable eSPI SMI source
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+VOID
+EspiSmiDisableSource (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ EFI_STATUS Status;
+
+ switch (EspiSmiType) {
+ case BiosWrProtect:
+ case BiosWrReport:
+ DEBUG ((DEBUG_ERROR, "Bit is write lock, thus BWRE/BWPDS source cannot be disabled \n"));
+ ASSERT (FALSE);
+ break;
+ case PcNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_PCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case PcFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_PCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_PCERR_SLV0_PCURD | B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case VwNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_VWERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case VwFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_VWERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case FlashNonFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_FCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XNFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case FlashFatalErr:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_FCERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_XERR_XNFES | B_PCH_PCR_ESPI_XERR_XFES | B_PCH_PCR_ESPI_XERR_XFEE),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case LnkType1Err:
+ Status = PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_PCH_PCR_ESPI_LNKERR_SLV0,
+ (UINT32) ~(B_PCH_PCR_ESPI_LNKERR_SLV0_SLCRR | B_PCH_PCR_ESPI_LNKERR_SLV0_LFET1S),
+ 0);
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported EspiSmiType \n"));
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Clear a status for the SMI event
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+VOID
+EspiSmiClearStatus (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINT32 PciBaseAddress;
+ CONST ESPI_DESCRIPTOR *Desc;
+
+ Desc = &mEspiDescriptor[EspiSmiType];
+
+ switch (Desc->Address.Type) {
+ case PCIE_ADDR_TYPE:
+ PciBus = Desc->Address.Data.pcie.Fields.Bus;
+ PciDev = Desc->Address.Data.pcie.Fields.Dev;
+ PciFun = Desc->Address.Data.pcie.Fields.Fnc;
+ PciReg = Desc->Address.Data.pcie.Fields.Reg;
+ PciBaseAddress = (UINT32) MmPciBase (PciBus, PciDev, PciFun);
+ MmioAndThenOr32 (PciBaseAddress + PciReg, Desc->ClearStatusAndMask, Desc->ClearStatusOrMask);
+ break;
+ case PCR_ADDR_TYPE:
+ Status = PchPcrAndThenOr32 (
+ Desc->Address.Data.Pcr.Fields.Pid,
+ Desc->Address.Data.Pcr.Fields.Offset,
+ Desc->ClearStatusAndMask,
+ Desc->ClearStatusOrMask
+ );
+ ASSERT_EFI_ERROR (Status);
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Address type for eSPI SMI is invalid \n"));
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Checks if a source is active by looking at the enable and status bits
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+BOOLEAN
+EspiSmiSourceIsActive (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Active;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINT32 PciBaseAddress;
+ UINT32 Data32;
+ CONST ESPI_DESCRIPTOR *Desc;
+
+ Desc = &mEspiDescriptor[EspiSmiType];
+
+ Active = FALSE;
+ switch (Desc->Address.Type) {
+ case PCIE_ADDR_TYPE:
+ PciBus = Desc->Address.Data.pcie.Fields.Bus;
+ PciDev = Desc->Address.Data.pcie.Fields.Dev;
+ PciFun = Desc->Address.Data.pcie.Fields.Fnc;
+ PciReg = Desc->Address.Data.pcie.Fields.Reg;
+ PciBaseAddress = (UINT32) MmPciBase (PciBus, PciDev, PciFun);
+ Data32 = MmioRead32 (PciBaseAddress + PciReg);
+ break;
+
+ case PCR_ADDR_TYPE:
+ Status = PchPcrRead32 (
+ Desc->Address.Data.Pcr.Fields.Pid,
+ Desc->Address.Data.Pcr.Fields.Offset,
+ &Data32
+ );
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ default:
+ Data32 = 0;
+ DEBUG ((DEBUG_ERROR, "Address type for eSPI SMI is invalid \n"));
+ ASSERT (FALSE);
+ break;
+ }
+
+ if ((Data32 & Desc->SourceIsActiveAndMask) == Desc->SourceIsActiveValue) {
+ Active = TRUE;
+ }
+
+ return Active;
+}
+
+/**
+ Insert a handler into the corresponding linked list based on EspiSmiType
+
+ @param[in] DispatchFunction The callback to execute
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE to determine which linked list to use
+ @param[out] DispatchHandle The link to the record in the database
+
+ @retval EFI_SUCCESS Record was successfully inserted into master database
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate pool to insert record
+**/
+STATIC
+EFI_STATUS
+InsertEspiRecord (
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN ESPI_SMI_TYPE EspiSmiType,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ ESPI_SMI_RECORD *Record;
+
+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (ESPI_SMI_RECORD), (VOID **) &Record);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SetMem (Record, sizeof (ESPI_SMI_RECORD), 0);
+
+ Record->Callback = DispatchFunction;
+ Record->Signature = ESPI_SMI_RECORD_SIGNATURE;
+
+ InsertTailList (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], &Record->Link);
+ EspiSmiClearStatus (EspiSmiType);
+ EspiSmiEnableSource (EspiSmiType);
+
+ ++mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType];
+
+ *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This callback is registered to PchSmiDispatch
+
+ @param[in] DispatchHandle Used to determine which source have been triggered
+**/
+VOID
+EspiSmiCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *PchSmiRecord;
+ ESPI_TOP_LEVEL_TYPE EspiTopLevelType;
+ ESPI_SMI_TYPE EspiSmiType;
+ ESPI_SMI_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ PchSmiRecord = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+
+ if (PchSmiRecord->PchSmiType == PchTcoSmiLpcBiosWpType) {
+ EspiTopLevelType = EspiBiosWrProtect;
+ } else if (PchSmiRecord->PchSmiType == PchSmiSerialIrqType) {
+ EspiTopLevelType = EspiSerialIrq;
+ } else {
+ DEBUG ((DEBUG_ERROR, "EspiSmiCallback was dispatched with a wrong DispatchHandle"));
+ ASSERT (FALSE);
+ return;
+ }
+
+ for (EspiSmiType = mEspiSmiInstance.Barrier[EspiTopLevelType].Start; EspiSmiType <= mEspiSmiInstance.Barrier[EspiTopLevelType].End; ++EspiSmiType) {
+ if (!EspiSmiSourceIsActive (EspiSmiType)) {
+ continue;
+ }
+ //
+ // The source is active, so walk the callback database and dispatch
+ //
+ if (!IsListEmpty (&mEspiSmiInstance.CallbackDataBase[EspiSmiType])) {
+ //
+ // We have children registered w/ us -- continue
+ //
+ LinkInDb = GetFirstNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType]);
+
+ while (!IsNull (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], LinkInDb)) {
+ RecordInDb = ESPI_RECORD_FROM_LINK (LinkInDb);
+
+ //
+ // RecordInDb->Link might be removed (unregistered) by Callback function, and then the
+ // system will hang in ASSERT() while calling GetNextNode().
+ // To prevent the issue, we need to get next record in DB here (before Callback function).
+ //
+ LinkInDb = GetNextNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], &RecordInDb->Link);
+
+ //
+ // Callback
+ //
+ if (RecordInDb->Callback != NULL) {
+ RecordInDb->Callback ((EFI_HANDLE) &RecordInDb->Link);
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ }
+ //
+ // Finish walking the linked list for the EspiSmiType, so clear status
+ //
+ EspiSmiClearStatus (EspiSmiType);
+ }
+}
+
+//
+// EspiBiosWp srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescEspiBiosWp = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_PCH_ESPI_PCBC
+ ) }
+ },
+ S_PCH_ESPI_PCBC,
+ N_PCH_ESPI_PCBC_LE
+ }
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_PCH_ESPI_PCBC
+ ) }
+ },
+ S_PCH_ESPI_PCBC,
+ N_PCH_ESPI_PCBC_BWPDS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_TCO
+ }
+};
+
+/**
+ This function will register EspiSmiCallback with mSrcDescEspiBiosWp source decriptor
+ This function make sure there is only one BIOS WP SMI handler is registered.
+ While any ESPI sub BIOS WP SMI type is registered, all the BIOS WP SMI
+ will go to callback function EspiSmiCallback first, and then dispatchs the callbacks
+ recorded in mEspiSmiInstance.
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval others Registration failed
+**/
+STATIC
+EFI_STATUS
+RegisterBiosWrProtectIfNull (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiBiosWrProtect] == NULL) {
+ Status = PchSmiRecordInsert (
+ &mSrcDescEspiBiosWp,
+ (PCH_SMI_CALLBACK_FUNCTIONS) EspiSmiCallback,
+ PchTcoSmiLpcBiosWpType,
+ &mEspiSmiInstance.PchSmiEspiHandle[EspiBiosWrProtect]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to register BIOS WP SMI handler \n"));
+ return Status;
+ }
+ Record = DATABASE_RECORD_FROM_LINK (mEspiSmiInstance.PchSmiEspiHandle[EspiBiosWrProtect]);
+ Record->ClearSource = PchTcoSmiClearSource;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will register EspiSmiCallback with mSrcDescSerialIrq source decriptor
+ This function make sure there is only one Serial IRQ SMI handler is registered.
+ While any ESPI sub Serial IRQ SMI type is registered, all the Serial IRQ SMI
+ will go to callback function EspiSmiCallback first, and then dispatchs the callbacks
+ recorded in mEspiSmiInstance.
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval others Registration failed
+**/
+STATIC
+EFI_STATUS
+RegisterSerialIrqIfNull (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiSerialIrq] == NULL) {
+ Status = PchSmiRecordInsert (
+ &mSrcDescSerialIrq,
+ (PCH_SMI_CALLBACK_FUNCTIONS) EspiSmiCallback,
+ PchSmiSerialIrqType,
+ &mEspiSmiInstance.PchSmiEspiHandle[EspiSerialIrq]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to register Serial IRQ SMI handler \n"));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Installs and initialize this protocol
+
+ @param[in] ImageHandle Not used
+
+ @retval EFI_SUCCESS Installation succeed
+ @retval others Installation failed
+**/
+EFI_STATUS
+EFIAPI
+InstallEspiSmi (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ ESPI_SMI_TYPE EspiType;
+
+ //
+ // InitializeListHead for mEspiSmiInstance.CallBackDataBase[EspiTopLevelTypeMax]
+ //
+ for (EspiType = 0; EspiType < EspiSmiTypeMax; ++EspiType) {
+ InitializeListHead (&mEspiSmiInstance.CallbackDataBase[EspiType]);
+ }
+
+ //
+ // Install EfiEspiSmiDispatchProtocol
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mEspiSmiInstance.Handle,
+ &gPchEspiSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mEspiSmiInstance.PchEspiSmiDispatchProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to install eSPI SMI Dispatch Protocol \n"));
+ ASSERT (FALSE);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Protect event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrProtectRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterBiosWrProtectIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, BiosWrProtect, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Report event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrReportRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, BiosWrReport, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, PcNonFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, PcFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, VwNonFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, VwFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, FlashNonFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, FlashFatalErr, DispatchHandle);
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Link Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+LnkType1ErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert a record
+ //
+ return InsertEspiRecord (DispatchFunction, LnkType1Err, DispatchHandle);
+}
+
+//
+// EspiSlave srcdesc
+//
+PCH_SMM_SOURCE_DESC mSrcDescEspiSlave = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_ESPI
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_ESPI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_ESPI
+ }
+};
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a eSPI slave SMI
+ This routine will also lock down ESPI_SMI_LOCK bit after registration and prevent
+ this handler from unregistration.
+ On platform that supports more than 1 device through another chip select (SPT-H),
+ the SMI handler itself needs to inspect both the eSPI devices' interrupt status registers
+ (implementation specific for each Slave) in order to identify and service the cause.
+ After servicing it, it has to clear the Slaves' internal SMI# status registers
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval EFI_ACCESS_DENIED The ESPI_SMI_LOCK is set and register is blocked.
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+EspiSlaveSmiRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ UINT32 GenPmConA;
+ UINTN PmcBaseAddress;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // If ESPI_SMI_LOCK is set, the register is blocked.
+ //
+ PmcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ GenPmConA = MmioRead32 (PmcBaseAddress + R_PCH_PMC_GEN_PMCON_A);
+ if (GenPmConA & B_PCH_PMC_GEN_PMCON_A_ESPI_SMI_LOCK) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // @note: This service doesn't utilize the data base of mEspiSmiInstance.
+ // While SMI is triggered it directly goes to the registing DispatchFunction
+ // instead of EspiSmiCallback.
+ //
+ Status = PchSmiRecordInsert (
+ &mSrcDescEspiSlave,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchEspiSmiEspiSlaveType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescEspiSlave);
+ PchSmmEnableSource (&mSrcDescEspiSlave);
+
+ //
+ // Lock down the ESPI_SMI_LOCK after ESPI SMI is enabled.
+ //
+ MmioOr8 (PmcBaseAddress + R_PCH_PMC_GEN_PMCON_A, B_PCH_PMC_GEN_PMCON_A_ESPI_SMI_LOCK);
+ //
+ // Keep the DispatchHandle which will be used for unregister function.
+ //
+ mEspiSmiInstance.PchSmiEspiHandle[EspiPmc] = *DispatchHandle;
+
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to unregister a callback based on handle
+
+ @param[in] This Not used
+ @param[in] DispatchHandle Handle acquired during registration
+
+ @retval EFI_SUCCESS Unregister successful
+ @retval EFI_INVALID_PARAMETER DispatchHandle is null
+ @retval EFI_INVALID_PARAMETER DispatchHandle's forward link has bad pointer
+ @retval EFI_INVALID_PARAMETER DispatchHandle does not exist in database
+ @retval EFI_ACCESS_DENIED Unregistration is done after end of DXE
+ @retval EFI_ACCESS_DENIED DispatchHandle is not allowed to unregistered
+**/
+EFI_STATUS
+EFIAPI
+EspiSmiUnRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ ESPI_TOP_LEVEL_TYPE EspiTopLevelType;
+ ESPI_SMI_TYPE EspiSmiType;
+ BOOLEAN SafeToDisable;
+ LIST_ENTRY *LinkInDb;
+ ESPI_SMI_RECORD *RecordPointer;
+
+ if (DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (((LIST_ENTRY *) DispatchHandle)->ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For DispatchHandle belongs to Espi Slave SMI, refuses the request of unregistration.
+ //
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiPmc] == DispatchHandle) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed for ESPI Slave SMI handle! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Iterate through all the database to find the record
+ //
+ for (EspiSmiType = 0; EspiSmiType < EspiSmiTypeMax; ++EspiSmiType) {
+ LinkInDb = GetFirstNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType]);
+
+ while (!IsNull (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], LinkInDb)) {
+ if (LinkInDb != (LIST_ENTRY *) DispatchHandle) {
+ LinkInDb = GetNextNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], LinkInDb);
+
+ } else {
+ //
+ // Found the source to be from this list
+ //
+ RemoveEntryList (LinkInDb);
+ RecordPointer = (ESPI_RECORD_FROM_LINK (LinkInDb));
+
+ if (mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType] != 0) {
+ if (--mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType] == 0) {
+ EspiSmiDisableSource (EspiSmiType);
+ }
+ }
+
+ Status = gSmst->SmmFreePool (RecordPointer);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ }
+
+ goto EspiSmiUnRegisterEnd;
+ }
+ }
+ }
+ //
+ // If the code reach here, the handle passed in cannot be found
+ //
+ DEBUG ((DEBUG_ERROR, "eSPI SMI handle is not in record database \n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+
+EspiSmiUnRegisterEnd:
+
+ //
+ // Unregister and clear the handle from PchSmiDispatch
+ //
+ for (EspiTopLevelType = 0; EspiTopLevelType < EspiTopLevelTypeMax; ++EspiTopLevelType) {
+ SafeToDisable = TRUE;
+ //
+ // Checks all the child events that belongs to a top level status in PMC
+ //
+ for (EspiSmiType = mEspiSmiInstance.Barrier[EspiTopLevelType].Start; EspiSmiType <= mEspiSmiInstance.Barrier[EspiTopLevelType].End; ++EspiSmiType) {
+ if (mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType] != 0) {
+ SafeToDisable = FALSE;
+ }
+ }
+ //
+ // Finally, disable the top level event in PMC
+ //
+ if (SafeToDisable) {
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiTopLevelType] != NULL) {
+ Status = PchSmmCoreUnRegister (NULL, mEspiSmiInstance.PchSmiEspiHandle[EspiTopLevelType]);
+ ASSERT_EFI_ERROR (Status);
+ mEspiSmiInstance.PchSmiEspiHandle[EspiTopLevelType] = NULL;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h
new file mode 100644
index 0000000000..2e4f407181
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h
@@ -0,0 +1,337 @@
+/** @file
+ eSPI SMI Dispatch header
+
+Copyright (c) 2017, 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 that 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 _PCH_SMM_ESPI_H_
+#define _PCH_SMM_ESPI_H_
+
+#include "PchSmmHelpers.h"
+
+#define ESPI_SMI_INSTANCE_SIGNATURE SIGNATURE_32 ('E', 'S', 'P', 'I')
+#define ESPI_SMI_RECORD_SIGNATURE SIGNATURE_32 ('E', 'S', 'R', 'C')
+
+#define ESPI_INSTANCE_FROM_THIS(_this) CR (_this, ESPI_SMI_INSTANCE, EfiEspiSmiDispatchProtocol, ESPI_SMI_INSTANCE_SIGNATURE)
+#define ESPI_RECORD_FROM_LINK(_link) CR (_link, ESPI_SMI_RECORD, Link, ESPI_SMI_RECORD_SIGNATURE)
+
+typedef enum {
+ EspiBiosWrProtect, ///< BIOS Write Protect
+ EspiSerialIrq, ///< eSPI Master Asserted SMI
+ EspiPmc, ///< eSPI PMC SMI
+ EspiTopLevelTypeMax
+} ESPI_TOP_LEVEL_TYPE;
+
+typedef enum {
+ BiosWrProtect, ///< BIOS Write Protect
+ BiosWrReport, ///< Peripheral Channel BIOS Write Protect
+ PcNonFatalErr, ///< Peripheral Channel Non Fatal Error
+ PcFatalErr, ///< Peripheral Channel Fatal Error
+ VwNonFatalErr, ///< Virtual Wire Non Fatal Error
+ VwFatalErr, ///< Virtual Wire Fatal Error
+ FlashNonFatalErr, ///< Flash Channel Non Fatal Error
+ FlashFatalErr, ///< Flash Channel Fatal Error
+ LnkType1Err, ///< Link Error
+ EspiSlaveSmi, ///< Espi Slave SMI
+ EspiSmiTypeMax
+} ESPI_SMI_TYPE;
+
+///
+/// This is used to classify ESPI_SMI_TYPE to ESPI_TOP_LEVEL_TYPE.
+/// Used during dispatching and unregistering
+///
+typedef struct {
+ ESPI_SMI_TYPE Start;
+ ESPI_SMI_TYPE End;
+} ESPI_SMI_TYPE_BARRIER;
+
+typedef struct _ESPI_SMI_INSTANCE {
+ ///
+ /// Signature associated with this instance
+ ///
+ UINT32 Signature;
+ ///
+ /// EFI_HANDLE acquired when installing PchEspiSmiDispatchProtocol
+ ///
+ EFI_HANDLE Handle;
+ ///
+ /// The protocol to register or unregister eSPI SMI callbacks
+ ///
+ PCH_ESPI_SMI_DISPATCH_PROTOCOL PchEspiSmiDispatchProtocol;
+ ///
+ /// The handle acquired when registering eSPI SMI callback to PchSmiDispatch
+ ///
+ EFI_HANDLE PchSmiEspiHandle[EspiTopLevelTypeMax];
+ ///
+ /// The linked list for record database.
+ ///
+ LIST_ENTRY CallbackDataBase[EspiSmiTypeMax];
+ ///
+ /// This is an internal counter to track the number of eSPI master events have been registered.
+ /// When unregistering, we can disable the SMI if the counter is zero
+ ///
+ UINTN EspiSmiEventCounter[EspiSmiTypeMax];
+ ///
+ /// Instance of barrier
+ ///
+ CONST ESPI_SMI_TYPE_BARRIER Barrier[EspiTopLevelTypeMax];
+} ESPI_SMI_INSTANCE;
+
+typedef struct _ESPI_DESCRIPTOR {
+ PCH_SMM_ADDRESS Address;
+ UINT32 SourceIsActiveAndMask;
+ UINT32 SourceIsActiveValue;
+ UINT32 ClearStatusAndMask;
+ UINT32 ClearStatusOrMask;
+} ESPI_DESCRIPTOR;
+
+///
+/// A simple record to store the callbacks associated with an eSPI SMI source
+///
+typedef struct _ESPI_SMI_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ PCH_ESPI_SMI_DISPATCH_CALLBACK Callback;
+} ESPI_SMI_RECORD;
+
+/**
+ Installs and initialize this protocol
+
+ @param[in] ImageHandle Not used
+
+ @retval EFI_SUCCESS Installation succeed
+ @retval others Installation failed
+**/
+EFI_STATUS
+EFIAPI
+InstallEspiSmi (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Protect event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrProtectRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Report event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrReportRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Link Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+LnkType1ErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a eSPI slave SMI
+ NOTE: The register function is not available when the ESPI_SMI_LOCK bit is set.
+ This runtine will also lock donw ESPI_SMI_LOCK bit after registration and
+ prevent this handler from unregistration.
+ On platform that supports more than 1 device through another chip select (SPT-H),
+ the SMI handler itself needs to inspect both the eSPI devices' interrupt status registers
+ (implementation specific for each Slave) in order to identify and service the cause.
+ After servicing it, it has to clear the Slaves' internal SMI# status registers
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval EFI_ACCESS_DENIED The ESPI_SMI_LOCK is set and register is blocked.
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+EspiSlaveSmiRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to unregister a callback based on handle
+
+ @param[in] This Not used
+ @param[in] DispatchHandle Handle acquired during registration
+
+ @retval EFI_SUCCESS Unregister successful
+ @retval EFI_INVALID_PARAMETER DispatchHandle is null
+ @retval EFI_INVALID_PARAMETER DispatchHandle's forward link has bad pointer
+ @retval EFI_INVALID_PARAMETER DispatchHandle does not exist in database
+ @retval EFI_ACCESS_DENIED Unregistration is done after end of DXE
+ @retval EFI_ACCESS_DENIED DispatchHandle is not allowed to unregistered
+**/
+EFI_STATUS
+EFIAPI
+EspiSmiUnRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
new file mode 100644
index 0000000000..fd79538d3a
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
@@ -0,0 +1,49 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Gpi dispatch protocol.
+
+Copyright (c) 2017, 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 that 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 "PchSmmHelpers.h"
+
+//
+// Structure for GPI SMI is a template which needs to have
+// GPI Smi bit offset and Smi Status & Enable registers updated (accordingly
+// to choosen group and pad number) after adding it to SMM Callback database
+//
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC PCH_GPI_SOURCE_DESC_TEMPLATE = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ GPIO_ADDR_TYPE, {0x0}
+ },
+ S_PCH_GPIO_GP_SMI_EN, 0x0,
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ GPIO_ADDR_TYPE, {0x0}
+ },
+ S_PCH_GPIO_GP_SMI_STS, 0x0,
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_GPIO_SMI
+ }
+};
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
new file mode 100644
index 0000000000..fea1ac9165
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
@@ -0,0 +1,333 @@
+/** @file
+ Helper functions for PCH SMM dispatcher.
+
+Copyright (c) 2017, 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 that 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 "PchSmmHelpers.h"
+
+///
+/// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+///
+
+/**
+ Compare 2 SMM source descriptors' enable settings.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The enable settings of the 2 SMM source descriptors are identical.
+ @retval FALSE The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN DescIndex;
+
+ IsEqual = TRUE;
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ ///
+ /// It's okay to compare a NULL bit description to a non-NULL bit description.
+ /// They are unequal and these tests will generate the correct result.
+ ///
+ if (Src1->En[DescIndex].Bit != Src2->En[DescIndex].Bit ||
+ Src1->En[DescIndex].Reg.Type != Src2->En[DescIndex].Reg.Type ||
+ Src1->En[DescIndex].Reg.Data.raw != Src2->En[DescIndex].Reg.Data.raw
+ ) {
+ IsEqual = FALSE;
+ break;
+ ///
+ /// out of for loop
+ ///
+ }
+ }
+
+ return IsEqual;
+}
+
+/**
+ Compare a bit descriptor to the enables of source descriptor. Includes null address type.
+
+ @param[in] BitDesc Pointer to the PCH SMI bit descriptor
+ @param[in] Src Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The bit desc is equal to any of the enables in source descriptor
+ @retval FALSE The bid desc is not equal to all of the enables in source descriptor
+**/
+BOOLEAN
+IsBitEqualToAnySourceEn (
+ CONST IN PCH_SMM_BIT_DESC *BitDesc,
+ CONST IN PCH_SMM_SOURCE_DESC *Src
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN DescIndex;
+
+ IsEqual = FALSE;
+
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; ++DescIndex) {
+ if ((BitDesc->Reg.Type == Src->En[DescIndex].Reg.Type) &&
+ (BitDesc->Reg.Data.raw == Src->En[DescIndex].Reg.Data.raw) &&
+ (BitDesc->Bit == Src->En[DescIndex].Bit)) {
+ IsEqual = TRUE;
+ break;
+ }
+ }
+ return IsEqual;
+}
+
+/**
+ Compare 2 SMM source descriptors' statuses.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The statuses of the 2 SMM source descriptors are identical.
+ @retval FALSE The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN DescIndex;
+
+ IsEqual = TRUE;
+
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ ///
+ /// It's okay to compare a NULL bit description to a non-NULL bit description.
+ /// They are unequal and these tests will generate the correct result.
+ ///
+ if (Src1->Sts[DescIndex].Bit != Src2->Sts[DescIndex].Bit ||
+ Src1->Sts[DescIndex].Reg.Type != Src2->Sts[DescIndex].Reg.Type ||
+ Src1->Sts[DescIndex].Reg.Data.raw != Src2->Sts[DescIndex].Reg.Data.raw
+ ) {
+ IsEqual = FALSE;
+ break;
+ ///
+ /// out of for loop
+ ///
+ }
+ }
+
+ return IsEqual;
+}
+
+/**
+ Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The 2 SMM source descriptors are identical.
+ @retval FALSE The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ return (BOOLEAN) (CompareEnables (Src1, Src2) && CompareStatuses (Src1, Src2));
+}
+
+/**
+ Check if an SMM source is active.
+
+ @param[in] Src Pointer to the PCH SMI source description table
+ @param[in] SciEn Indicate if SCI is enabled or not
+ @param[in] SmiEnValue Value from R_PCH_SMI_EN
+ @param[in] SmiStsValue Value from R_PCH_SMI_STS
+
+ @retval TRUE It is active.
+ @retval FALSE It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+ CONST IN PCH_SMM_SOURCE_DESC *Src,
+ CONST IN BOOLEAN SciEn,
+ CONST IN UINT32 SmiEnValue,
+ CONST IN UINT32 SmiStsValue
+ )
+{
+ UINTN DescIndex;
+
+ ///
+ /// This source is dependent on SciEn, and SciEn == 1. An ACPI OS is present,
+ /// so we shouldn't do anything w/ this source until SciEn == 0.
+ ///
+ if ((Src->Flags == PCH_SMM_SCI_EN_DEPENDENT) && (SciEn)) {
+ return FALSE;
+ }
+
+ ///
+ /// Checking top level SMI status. If the status is not active, return false immediately
+ ///
+ if (!IS_BIT_DESC_NULL (Src->PmcSmiSts)) {
+ if ((Src->PmcSmiSts.Reg.Type == ACPI_ADDR_TYPE) &&
+ (Src->PmcSmiSts.Reg.Data.acpi == R_PCH_SMI_STS) &&
+ ((SmiStsValue & (1u << Src->PmcSmiSts.Bit)) == 0)) {
+ return FALSE;
+ }
+ }
+
+ ///
+ /// Read each bit desc from hardware and make sure it's a one
+ ///
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (Src->En[DescIndex])) {
+ if ((Src->En[DescIndex].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Src->En[DescIndex].Reg.Data.acpi == R_PCH_SMI_EN) &&
+ ((SmiEnValue & (1u << Src->En[DescIndex].Bit)) == 0)) {
+ return FALSE;
+ } else if (ReadBitDesc (&Src->En[DescIndex]) == 0) {
+ return FALSE;
+ }
+ }
+ }
+
+ ///
+ /// Read each bit desc from hardware and make sure it's a one
+ ///
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (Src->Sts[DescIndex])) {
+ if ((Src->Sts[DescIndex].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Src->Sts[DescIndex].Reg.Data.acpi == R_PCH_SMI_STS) &&
+ ((SmiStsValue & (1u << Src->Sts[DescIndex].Bit)) == 0)) {
+ return FALSE;
+ } else if (ReadBitDesc (&Src->Sts[DescIndex]) == 0) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+ status bit to make initial state is correct
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmEnableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+
+ ///
+ /// Set enables to 1 by writing a 1
+ ///
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->En[DescIndex])) {
+ WriteBitDesc (&SrcDesc->En[DescIndex], 1, FALSE);
+ }
+ }
+ ///
+ /// Clear statuses to 0 by writing a 1
+ ///
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+ WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+ }
+ }
+}
+
+/**
+ Disable the SMI source event by clear the SMI enable bit
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmDisableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->En[DescIndex])) {
+ WriteBitDesc (&SrcDesc->En[DescIndex], 0, FALSE);
+ }
+ }
+}
+
+/**
+ Clear the SMI status bit by set the source bit of SMI status register
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+ WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+ }
+ }
+}
+
+/**
+ Sets the source to a 1 and then waits for it to clear.
+ Be very careful when calling this function -- it will not
+ ASSERT. An acceptable case to call the function is when
+ waiting for the NEWCENTURY_STS bit to clear (which takes
+ 3 RTCCLKs).
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSourceAndBlock (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+ BOOLEAN IsSet;
+
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+ ///
+ /// Write the bit
+ ///
+ WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+
+ ///
+ /// Don't return until the bit actually clears.
+ ///
+ IsSet = TRUE;
+ while (IsSet) {
+ IsSet = ReadBitDesc (&SrcDesc->Sts[DescIndex]);
+ ///
+ /// IsSet will eventually clear -- or else we'll have
+ /// an infinite loop.
+ ///
+ }
+ }
+ }
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
new file mode 100644
index 0000000000..44a8936790
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
@@ -0,0 +1,162 @@
+/** @file
+ Helper functions for PCH SMM
+
+Copyright (c) 2017, 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 that 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 PCH_SMM_HELPERS_H
+#define PCH_SMM_HELPERS_H
+
+#include "PchSmm.h"
+#include "PchxSmmHelpers.h"
+//
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+//
+
+/**
+ Publish SMI Dispatch protocols.
+
+
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+ VOID
+ );
+
+/**
+ Compare 2 SMM source descriptors' enable settings.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The enable settings of the 2 SMM source descriptors are identical.
+ @retval FALSE The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Compare a bit descriptor to the enables of source descriptor. Includes null address type.
+
+ @param[in] BitDesc Pointer to the PCH SMI bit descriptor
+ @param[in] Src Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The bit desc is equal to any of the enables in source descriptor
+ @retval FALSE The bid desc is not equal to all of the enables in source descriptor
+**/
+BOOLEAN
+IsBitEqualToAnySourceEn (
+ CONST IN PCH_SMM_BIT_DESC *BitDesc,
+ CONST IN PCH_SMM_SOURCE_DESC *Src
+ );
+
+/**
+ Compare 2 SMM source descriptors' statuses.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The statuses of the 2 SMM source descriptors are identical.
+ @retval FALSE The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The 2 SMM source descriptors are identical.
+ @retval FALSE The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Check if an SMM source is active.
+
+ @param[in] Src Pointer to the PCH SMI source description table
+ @param[in] SciEn Indicate if SCI is enabled or not
+ @param[in] SmiEnValue Value from R_PCH_SMI_EN
+ @param[in] SmiStsValue Value from R_PCH_SMI_STS
+
+ @retval TRUE It is active.
+ @retval FALSE It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+ CONST IN PCH_SMM_SOURCE_DESC *Src,
+ CONST IN BOOLEAN SciEn,
+ CONST IN UINT32 SmiEnValue,
+ CONST IN UINT32 SmiStsValue
+ );
+
+/**
+ Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+ status bit to make initial state is correct
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmEnableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Disable the SMI source event by clear the SMI enable bit
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmDisableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Clear the SMI status bit by set the source bit of SMI status register
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Sets the source to a 1 and then waits for it to clear.
+ Be very careful when calling this function -- it will not
+ ASSERT. An acceptable case to call the function is when
+ waiting for the NEWCENTURY_STS bit to clear (which takes
+ 3 RTCCLKs).
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSourceAndBlock (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
new file mode 100644
index 0000000000..324eaeb7e8
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
@@ -0,0 +1,702 @@
+/** @file
+ File to contain all the hardware specific stuff for the Periodical Timer dispatch protocol.
+
+Copyright (c) 2017, 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 that 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 "PchSmmHelpers.h"
+#include <Protocol/PchSmmPeriodicTimerControl.h>
+
+//
+// There is only one instance for PeriodicTimerCommBuffer.
+// It's safe in SMM since there is no re-entry for the function.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_PERIODIC_TIMER_CONTEXT mPchPeriodicTimerCommBuffer;
+
+typedef enum {
+ PERIODIC_TIMER= 0,
+ SWSMI_TIMER,
+ NUM_TIMERS
+} SUPPORTED_TIMER;
+
+typedef struct _TIMER_INTERVAL {
+ UINT64 Interval;
+ UINT8 AssociatedTimer;
+} TIMER_INTERVAL;
+
+#define NUM_INTERVALS 8
+
+//
+// Time constants, in 100 nano-second units
+//
+#define TIME_64s 640000000 ///< 64 s
+#define TIME_32s 320000000 ///< 32 s
+#define TIME_16s 160000000 ///< 16 s
+#define TIME_8s 80000000 ///< 8 s
+#define TIME_64ms 640000 ///< 64 ms
+#define TIME_32ms 320000 ///< 32 ms
+#define TIME_16ms 160000 ///< 16 ms
+#define TIME_1_5ms 15000 ///< 1.5 ms
+
+typedef enum {
+ INDEX_TIME_64s = 0,
+ INDEX_TIME_32s,
+ INDEX_TIME_16s,
+ INDEX_TIME_8s,
+ INDEX_TIME_64ms,
+ INDEX_TIME_32ms,
+ INDEX_TIME_16ms,
+ INDEX_TIME_1_5ms,
+ INDEX_TIME_MAX
+} TIMER_INTERVAL_INDEX;
+
+static TIMER_INTERVAL mSmmPeriodicTimerIntervals[NUM_INTERVALS] = {
+ {
+ TIME_64s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_32s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_16s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_8s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_64ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_32ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_16ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_1_5ms,
+ SWSMI_TIMER
+ },
+};
+
+typedef struct _TIMER_INFO {
+ UINTN NumChildren; ///< number of children using this timer
+ UINT64 MinReqInterval; ///< minimum interval required by children
+ UINTN CurrentSetting; ///< interval this timer is set at right now (index into interval table)
+} TIMER_INFO;
+
+GLOBAL_REMOVE_IF_UNREFERENCED TIMER_INFO mTimers[NUM_TIMERS];
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mTIMER_SOURCE_DESCS[NUM_TIMERS] = {
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_PERIODIC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PERIODIC
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PERIODIC
+ }
+ },
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_SWSMI_TMR
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SWSMI_TMR
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_SWSMI_TMR
+ }
+ }
+};
+
+/**
+ Program Smm Periodic Timer
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Convert the dispatch context to the timer interval, this function will assert if then either:
+ (1) The context contains an invalid interval
+ (2) The timer interval table is corrupt
+
+ @param[in] DispatchContext The pointer to the Dispatch Context
+
+ @retval TIMER_INTERVAL The timer interval of input dispatch context
+**/
+TIMER_INTERVAL *
+ContextToTimerInterval (
+ IN PCH_SMM_CONTEXT *DispatchContext
+ )
+{
+ UINTN loopvar;
+
+ ///
+ /// Determine which timer this child is using
+ ///
+ for (loopvar = 0; loopvar < NUM_INTERVALS; loopvar++) {
+ if (((DispatchContext->PeriodicTimer.SmiTickInterval == 0) &&
+ (DispatchContext->PeriodicTimer.Period >= mSmmPeriodicTimerIntervals[loopvar].Interval)) ||
+ (DispatchContext->PeriodicTimer.SmiTickInterval == mSmmPeriodicTimerIntervals[loopvar].Interval)) {
+ return &mSmmPeriodicTimerIntervals[loopvar];
+ }
+ }
+ ///
+ /// If this assertion fires, then either:
+ /// (1) the context contains an invalid interval
+ /// (2) the timer interval table is corrupt
+ ///
+ ASSERT (FALSE);
+
+ return NULL;
+}
+
+/**
+ Figure out which timer the child is requesting and
+ send back the source description
+
+ @param[in] DispatchContext The pointer to the Dispatch Context instances
+ @param[out] SrcDesc The pointer to the source description
+
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ TIMER_INTERVAL *TimerInterval;
+
+ ///
+ /// Figure out which timer the child is requesting and
+ /// send back the source description
+ ///
+ TimerInterval = ContextToTimerInterval (DispatchContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+
+ CopyMem (
+ (VOID *) SrcDesc,
+ (VOID *) (&mTIMER_SOURCE_DESCS[TimerInterval->AssociatedTimer]),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+
+ ///
+ /// Program the value of the interval into hardware
+ ///
+ PchSmmPeriodicTimerProgramTimers (SrcDesc);
+}
+
+/**
+ Update the elapsed time from the Interval data of DATABASE_RECORD
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] HwContext The Context to be updated.
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *HwContext
+ )
+{
+ TIMER_INTERVAL *TimerInterval;
+
+ ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+ TimerInterval = ContextToTimerInterval (&Record->ChildContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+ ///
+ /// Ignore the hardware context. It's not required for this protocol.
+ /// Instead, just increment the child's context.
+ /// Update the elapsed time w/ the data from our tables
+ ///
+ Record->MiscData.ElapsedTime += mTimers[TimerInterval->AssociatedTimer].MinReqInterval;
+ *HwContext = Record->ChildContext;
+}
+
+/**
+ Check whether Periodic Timer of two contexts match
+
+ @param[in] Context1 Context 1 that includes Periodic Timer 1
+ @param[in] Context2 Context 2 that includes Periodic Timer 2
+
+ @retval FALSE Periodic Timer match
+ @retval TRUE Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+ IN PCH_SMM_CONTEXT *HwContext,
+ IN PCH_SMM_CONTEXT *ChildContext
+ )
+{
+ DATABASE_RECORD *Record;
+ Record = DATABASE_RECORD_FROM_CHILDCONTEXT (ChildContext);
+
+ if (Record->MiscData.ElapsedTime >= ChildContext->PeriodicTimer.Period) {
+ ///
+ /// For EDKII, the ElapsedTime is reset when PeriodicTimerGetCommBuffer
+ ///
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Gather the CommBuffer information of SmmPeriodicTimerDispatch2.
+
+ @param[in] Record No use
+ @param[out] CommBuffer Point to the CommBuffer structure
+ @param[out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetCommBuffer (
+ IN DATABASE_RECORD *Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN *CommBufferSize
+ )
+{
+ ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+ mPchPeriodicTimerCommBuffer.ElapsedTime = Record->MiscData.ElapsedTime;
+
+ ///
+ /// For EDKII, the ElapsedTime is reset here
+ ///
+ Record->MiscData.ElapsedTime = 0;
+
+ ///
+ /// Return the CommBuffer
+ ///
+ *CommBuffer = (VOID *) &mPchPeriodicTimerCommBuffer;
+ *CommBufferSize = sizeof (EFI_SMM_PERIODIC_TIMER_CONTEXT);
+}
+
+/**
+ Program Smm Periodic Timer
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ SUPPORTED_TIMER Timer;
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ TIMER_INTERVAL *TimerInterval;
+ UINT8 GenPmConA;
+ UINT8 GenPmConB;
+ UINTN PciPmcRegBase;
+
+ PciPmcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+
+ ///
+ /// Find the minimum required interval for each timer
+ ///
+ for (Timer = 0; Timer < NUM_TIMERS; Timer++) {
+ mTimers[Timer].MinReqInterval = ~ (UINT64) 0x0;
+ mTimers[Timer].NumChildren = 0;
+ }
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (RecordInDb->ProtocolType == PeriodicTimerType) {
+ ///
+ /// This child is registerd with the PeriodicTimer protocol
+ ///
+ TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+
+ Timer = TimerInterval->AssociatedTimer;
+ if (Timer < 0 || Timer >= NUM_TIMERS) {
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ return;
+ }
+
+ if (mTimers[Timer].MinReqInterval > RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval) {
+ mTimers[Timer].MinReqInterval = RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval;
+ }
+
+ mTimers[Timer].NumChildren++;
+ }
+
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+ ///
+ /// Program the hardware
+ ///
+ if (mTimers[PERIODIC_TIMER].NumChildren > 0) {
+ GenPmConA = MmioRead8 (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_A);
+ GenPmConA &= (UINT8) ~B_PCH_PMC_GEN_PMCON_A_PER_SMI_SEL;
+ switch (mTimers[PERIODIC_TIMER].MinReqInterval) {
+ case TIME_64s:
+ GenPmConA |= V_PCH_PMC_GEN_PMCON_A_PER_SMI_64S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64s;
+ break;
+
+ case TIME_32s:
+ GenPmConA |= V_PCH_PMC_GEN_PMCON_A_PER_SMI_32S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32s;
+ break;
+
+ case TIME_16s:
+ GenPmConA |= V_PCH_PMC_GEN_PMCON_A_PER_SMI_16S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16s;
+ break;
+
+ case TIME_8s:
+ GenPmConA |= V_PCH_PMC_GEN_PMCON_A_PER_SMI_8S;
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_8s;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ MmioWrite8 (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_A, GenPmConA);
+ ///
+ /// Restart the timer here, just need to clear the SMI
+ ///
+ if (SrcDesc->Sts[0].Bit == N_PCH_SMI_STS_PERIODIC) {
+ PchSmmClearSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
+ }
+ } else {
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
+ }
+
+ if (mTimers[SWSMI_TIMER].NumChildren > 0) {
+ ///
+ /// ICH9, ICH10 and PCH share the same bit positions for SW SMI Rate settings
+ ///
+ GenPmConB = MmioRead8 (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_B);
+ //
+ // Don't clear B_PCH_PMC_GEN_PMCON_B_PWR_FLR by accident since it's RW/1C.
+ //
+ GenPmConB &= ~B_PCH_PMC_GEN_PMCON_B_PWR_FLR;
+
+ GenPmConB &= ~B_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL;
+ switch (mTimers[SWSMI_TIMER].MinReqInterval) {
+ case TIME_64ms:
+ GenPmConB |= V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_64MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_64ms;
+ break;
+
+ case TIME_32ms:
+ GenPmConB |= V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_32MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_32ms;
+ break;
+
+ case TIME_16ms:
+ GenPmConB |= V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_16MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_16ms;
+ break;
+
+ case TIME_1_5ms:
+ GenPmConB |= V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_1_5MS;
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_1_5ms;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ ///
+ /// SWSMI_RATE_SEL BIT (PMC PCI offset A4h[7:6]) bits are in RTC well
+ ///
+ MmioWrite8 (PciPmcRegBase + R_PCH_PMC_GEN_PMCON_B, GenPmConB);
+
+ ///
+ /// Restart the timer here, need to disable, clear, then enable to restart this timer
+ ///
+ if (SrcDesc->Sts[0].Bit == N_PCH_SMI_STS_SWSMI_TMR) {
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ PchSmmClearSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ PchSmmEnableSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ }
+ } else {
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[SWSMI_TIMER]);
+ }
+}
+
+/**
+ This services returns the next SMI tick period that is supported by the chipset.
+ The order returned is from longest to shortest interval period.
+
+ @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+ @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+ @retval EFI_SUCCESS The service returned successfully.
+ @retval EFI_INVALID_PARAMETER The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+ IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This,
+ IN OUT UINT64 **SmiTickInterval
+ )
+{
+ TIMER_INTERVAL *IntervalPointer;
+
+ ASSERT (SmiTickInterval != NULL);
+
+ IntervalPointer = (TIMER_INTERVAL *) *SmiTickInterval;
+
+ if (IntervalPointer == NULL) {
+ ///
+ /// The first time child requesting an interval
+ ///
+ IntervalPointer = &mSmmPeriodicTimerIntervals[0];
+ } else if (IntervalPointer == &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1]) {
+ ///
+ /// At end of the list
+ ///
+ IntervalPointer = NULL;
+ } else {
+ if ((IntervalPointer >= &mSmmPeriodicTimerIntervals[0]) &&
+ (IntervalPointer < &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1])
+ ) {
+ ///
+ /// Get the next interval in the list
+ ///
+ IntervalPointer++;
+ } else {
+ ///
+ /// Input is out of range
+ ///
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (IntervalPointer != NULL) {
+ *SmiTickInterval = &IntervalPointer->Interval;
+ } else {
+ *SmiTickInterval = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is responsible for calculating and enabling any timers that are required
+ to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+ IN PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PchSmmPeriodicTimerProgramTimers (SrcDesc);
+}
+
+
+/**
+ Check if the handle is in type of PeriodicTimer
+
+ @retval TRUE The handle is in type of PeriodicTimer.
+ @retval FALSE The handle is not in type of PeriodicTimer.
+**/
+BOOLEAN
+IsSmmPeriodicTimerHandle (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ if (DispatchHandle == (EFI_HANDLE) LinkInDb) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (RecordInDb->ProtocolType == PeriodicTimerType) {
+ return TRUE;
+ }
+ }
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, LinkInDb);
+ }
+ return FALSE;
+}
+
+/**
+ Pause SMM periodic timer callback function.
+
+ This function disable the SMI enable of SMI timer according to the DispatchHandle,
+ which is returned by SMM periodic timer callback registration.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmPeriodicTimerControlPause (
+ IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordInDb;
+ TIMER_INTERVAL *TimerInterval;
+
+ if (IsSmmPeriodicTimerHandle (DispatchHandle) == FALSE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RecordInDb = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ TimerInterval = NULL;
+ TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+ if (TimerInterval == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PchSmmDisableSource (&mTIMER_SOURCE_DESCS[TimerInterval->AssociatedTimer]);
+ return EFI_SUCCESS;
+}
+
+/**
+ Resume SMM periodic timer callback function.
+
+ This function enable the SMI enable of SMI timer according to the DispatchHandle,
+ which is returned by SMM periodic timer callback registration.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmPeriodicTimerControlResume (
+ IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordInDb;
+ TIMER_INTERVAL *TimerInterval;
+
+ if (IsSmmPeriodicTimerHandle (DispatchHandle) == FALSE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RecordInDb = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ TimerInterval = NULL;
+ TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+ if (TimerInterval == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PchSmmEnableSource (&mTIMER_SOURCE_DESCS[TimerInterval->AssociatedTimer]);
+ return EFI_SUCCESS;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL mPchSmmPeriodicTimerControlProtocol = {
+ PchSmmPeriodicTimerControlPause,
+ PchSmmPeriodicTimerControlResume
+};
+
+/**
+ Install PCH SMM periodic timer control protocol
+
+ @param[in] Handle handle for this driver
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSmmPeriodicTimerControlProtocol (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install protocol interface
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchSmmPeriodicTimerControlGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchSmmPeriodicTimerControlProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
new file mode 100644
index 0000000000..404d2a31bc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
@@ -0,0 +1,96 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Power Button dispatch protocol.
+
+Copyright (c) 2017, 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 that 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 <PchSmmHelpers.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC POWER_BUTTON_SOURCE_DESC = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_EN}
+ },
+ S_PCH_ACPI_PM1_EN,
+ N_PCH_ACPI_PM1_EN_PWRBTN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_ACPI_PM1_STS}
+ },
+ S_PCH_ACPI_PM1_STS,
+ N_PCH_ACPI_PM1_STS_PWRBTN
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_PM1_STS_REG
+ }
+};
+
+/**
+ Get the power button status.
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] Context Calling context from the hardware, will be updated with the current power button status.
+
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ UINT32 GenPmConA;
+ UINTN PmcBaseAddress;
+
+ PmcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ GenPmConA = MmioRead32 (PmcBaseAddress + R_PCH_PMC_GEN_PMCON_A);
+ if ((GenPmConA & B_PCH_PMC_GEN_PMCON_A_PWRBTN_LVL) != 0) {
+ Context->PowerButton.Phase = EfiPowerButtonExit;
+ } else {
+ Context->PowerButton.Phase = EfiPowerButtonEntry;
+ }
+}
+
+/**
+ Check whether Power Button status of two contexts match
+
+ @param[in] Context1 Context 1 that includes Power Button status 1
+ @param[in] Context2 Context 2 that includes Power Button status 2
+
+ @retval FALSE Power Button status match
+ @retval TRUE Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->PowerButton.Phase == Context2->PowerButton.Phase);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
new file mode 100644
index 0000000000..c285c677f1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
@@ -0,0 +1,169 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Sw dispatch protocol.
+
+Copyright (c) 2017, 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 that 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 "PchSmmHelpers.h"
+
+#include <Protocol/SmmCpu.h>
+//
+// There is only one instance for SwCommBuffer.
+// It's safe in SMM since there is no re-entry for the function.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SW_CONTEXT mPchSwCommBuffer;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC SW_SOURCE_DESC = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_APMC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_APM
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_APM
+ }
+};
+
+/**
+ Get the Software Smi value
+
+ @param[in] Record No use
+ @param[out] Context The context that includes Software Smi value to be filled
+
+**/
+VOID
+EFIAPI
+SwGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ UINT8 ApmCnt;
+
+ ApmCnt = IoRead8 ((UINTN) R_PCH_APM_CNT);
+
+ Context->Sw.SwSmiInputValue = ApmCnt;
+}
+
+/**
+ Check whether software SMI value of two contexts match
+
+ @param[in] Context1 Context 1 that includes software SMI value 1
+ @param[in] Context2 Context 2 that includes software SMI value 2
+
+ @retval FALSE Software SMI value match
+ @retval TRUE Software SMI value don't match
+**/
+BOOLEAN
+EFIAPI
+SwCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->Sw.SwSmiInputValue == Context2->Sw.SwSmiInputValue);
+}
+
+/**
+ Gather the CommBuffer information of SmmSwDispatch2.
+
+ @param[in] Record No use
+ @param[out] CommBuffer Point to the CommBuffer structure
+ @param[out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+SwGetCommBuffer (
+ IN DATABASE_RECORD *Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN *CommBufferSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMM_SAVE_STATE_IO_INFO SmiIoInfo;
+ UINTN Index;
+
+ ASSERT (Record->ProtocolType == SwType);
+
+ mPchSwCommBuffer.CommandPort = IoRead8 (R_PCH_APM_CNT);
+ mPchSwCommBuffer.DataPort = IoRead8 (R_PCH_APM_STS);
+
+ //
+ // Try to find which CPU trigger SWSMI
+ //
+ mPchSwCommBuffer.SwSmiCpuIndex = 0;
+ for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
+ Status = mSmmCpuProtocol->ReadSaveState (
+ mSmmCpuProtocol,
+ sizeof (EFI_SMM_SAVE_STATE_IO_INFO),
+ EFI_SMM_SAVE_STATE_REGISTER_IO,
+ Index,
+ &SmiIoInfo
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if (SmiIoInfo.IoPort == R_PCH_APM_CNT) {
+ //
+ // Find matched CPU.
+ //
+ mPchSwCommBuffer.SwSmiCpuIndex = Index;
+ break;
+ }
+ }
+
+ ///
+ /// Return the CommBuffer
+ ///
+ *CommBuffer = (VOID *) &mPchSwCommBuffer;
+ *CommBufferSize = sizeof (EFI_SMM_SW_CONTEXT);
+}
+
+/**
+ Init required protocol for Pch Sw Dispatch protocol.
+
+
+**/
+VOID
+PchSwDispatchInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ //
+ // Locate PI SMM CPU protocol
+ //
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&mSmmCpuProtocol);
+ ASSERT_EFI_ERROR (Status);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
new file mode 100644
index 0000000000..523cea27aa
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
@@ -0,0 +1,235 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.
+
+Copyright (c) 2017, 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 that 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 "PchSmmHelpers.h"
+
+#define PROGRESS_CODE_S3_SUSPEND_END PcdGet32 (PcdProgressCodeS3SuspendEnd)
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC SX_SOURCE_DESC = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_ON_SLP_EN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_ON_SLP_EN
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_ON_SLP_EN
+ }
+};
+
+/**
+ Get the Sleep type
+
+ @param[in] Record No use
+ @param[out] Context The context that includes SLP_TYP bits to be filled
+
+**/
+VOID
+EFIAPI
+SxGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ UINT32 Pm1Cnt;
+
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+
+ ///
+ /// By design, the context phase will always be ENTRY
+ ///
+ Context->Sx.Phase = SxEntry;
+
+ ///
+ /// Map the PM1_CNT register's SLP_TYP bits to the context type
+ ///
+ switch (Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) {
+ case V_PCH_ACPI_PM1_CNT_S0:
+ Context->Sx.Type = SxS0;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S1:
+ Context->Sx.Type = SxS1;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S3:
+ Context->Sx.Type = SxS3;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S4:
+ Context->Sx.Type = SxS4;
+ break;
+
+ case V_PCH_ACPI_PM1_CNT_S5:
+ Context->Sx.Type = SxS5;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Check whether sleep type of two contexts match
+
+ @param[in] Context1 Context 1 that includes sleep type 1
+ @param[in] Context2 Context 2 that includes sleep type 2
+
+ @retval FALSE Sleep types match
+ @retval TRUE Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->Sx.Type == Context2->Sx.Type);
+}
+
+/**
+ For each PCIE RP clear PME SCI status and disable SCI, then PCIEXP_WAKE_STS from PMC.
+ This prevents platform from waking more than one time due to a single PCIE wake event.
+ Normally it's up to OS to clear SCI statuses. But in a scenario where platform wakes
+ and goes to S5 instead of booting to OS, the SCI status would remain set and would trigger another wake.
+**/
+VOID
+ClearPcieSci (
+ VOID
+ )
+{
+ UINT32 MaxPorts;
+ UINT32 RpIndex;
+ UINTN RpBase;
+
+ MaxPorts = GetPchMaxPciePortNum ();
+ for (RpIndex = 0; RpIndex < MaxPorts; RpIndex++) {
+ RpBase = PchPcieBase (RpIndex);
+ if (MmioRead16 (RpBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF) {
+ MmioAnd8 ((RpBase + R_PCH_PCIE_MPC + 3), (UINT8)~((UINT8)(B_PCH_PCIE_MPC_PMCE >> 24)));
+ MmioWrite32 (RpBase + R_PCH_PCIE_SMSCS, B_PCH_PCIE_SMSCS_PMCS);
+ }
+ }
+ IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_PCIEXP_WAKE_STS);
+}
+
+
+/**
+ When we get an SMI that indicates that we are transitioning to a sleep state,
+ we need to actually transition to that state. We do this by disabling the
+ "SMI on sleep enable" feature, which generates an SMI when the operating system
+ tries to put the system to sleep, and then physically putting the system to sleep.
+
+
+**/
+VOID
+PchSmmSxGoToSleep (
+ VOID
+ )
+{
+ UINT32 Pm1Cnt;
+ UINT32 PchPwrmBase;
+
+ ClearPcieSci ();
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ ///
+ /// Flush cache into memory before we go to sleep. It is necessary for S3 sleep
+ /// because we may update memory in SMM Sx sleep handlers -- the updates are in cache now
+ ///
+ AsmWbinvd ();
+
+ ///
+ /// Disable SMIs
+ ///
+ PchSmmClearSource (&SX_SOURCE_DESC);
+ PchSmmDisableSource (&SX_SOURCE_DESC);
+
+ ///
+ /// Get Power Management 1 Control Register Value
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+
+ ///
+ /// Record S3 suspend performance data
+ ///
+ if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
+ ///
+ /// Report status code before goto S3 sleep
+ ///
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PROGRESS_CODE_S3_SUSPEND_END);
+
+ ///
+ /// Flush cache into memory before we go to sleep.
+ ///
+ AsmWbinvd ();
+ }
+
+ ///
+ /// Now that SMIs are disabled, write to the SLP_EN bit again to trigger the sleep
+ ///
+ Pm1Cnt |= B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT), Pm1Cnt);
+
+ ///
+ /// Should only proceed if wake event is generated.
+ ///
+ if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S1) {
+ while (((IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS))) & B_PCH_ACPI_PM1_STS_WAK) == 0x0);
+ } else {
+ CpuDeadLoop ();
+ }
+ ///
+ /// The system just went to sleep. If the sleep state was S1, then code execution will resume
+ /// here when the system wakes up.
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+
+ if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == 0) {
+ ///
+ /// An ACPI OS isn't present, clear the sleep information
+ ///
+ Pm1Cnt &= ~B_PCH_ACPI_PM1_CNT_SLP_TYP;
+ Pm1Cnt |= V_PCH_ACPI_PM1_CNT_S0;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT), Pm1Cnt);
+ }
+
+ PchSmmClearSource (&SX_SOURCE_DESC);
+ PchSmmEnableSource (&SX_SOURCE_DESC);
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
new file mode 100644
index 0000000000..71c11ed71d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
@@ -0,0 +1,232 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm USB dispatch protocol.
+
+Copyright (c) 2017, 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 that 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 "PchSmmHelpers.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mUSB1_LEGACY = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_LEGACY_USB
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mUSB3_LEGACY = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_EN}
+ },
+ S_PCH_SMI_EN,
+ N_PCH_SMI_EN_LEGACY_USB3
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB3
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_PCH_SMI_STS}
+ },
+ S_PCH_SMI_STS,
+ N_PCH_SMI_STS_LEGACY_USB3
+ }
+};
+
+typedef enum {
+ PchUsbControllerLpc0 = 0,
+ PchUsbControllerXhci,
+ PchUsbControllerTypeMax
+} PCH_USB_CONTROLLER_TYPE;
+
+typedef struct {
+ UINT8 Function;
+ UINT8 Device;
+ PCH_USB_CONTROLLER_TYPE UsbConType;
+} USB_CONTROLLER;
+
+GLOBAL_REMOVE_IF_UNREFERENCED USB_CONTROLLER mUsbControllersMap[] = {
+ {
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PchUsbControllerLpc0
+ },
+ {
+ PCI_FUNCTION_NUMBER_PCH_XHCI,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PchUsbControllerXhci
+ }
+};
+
+/**
+ Find the handle that best matches the input Device Path and return the USB controller type
+
+ @param[in] DevicePath Pointer to the device Path table
+ @param[out] Controller Returned with the USB controller type of the input device path
+
+ @retval EFI_SUCCESS Find the handle that best matches the input Device Path
+ @exception EFI_UNSUPPORTED Invalid device Path table or can't find any match USB device path
+ PCH_USB_CONTROLLER_TYPE The USB controller type of the input
+ device path
+**/
+EFI_STATUS
+DevicePathToSupportedController (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT PCH_USB_CONTROLLER_TYPE *Controller
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+ ACPI_HID_DEVICE_PATH *AcpiNode;
+ PCI_DEVICE_PATH *PciNode;
+ EFI_DEVICE_PATH_PROTOCOL *RemaingDevicePath;
+ UINT8 UsbIndex;
+ ///
+ /// Find the handle that best matches the Device Path. If it is only a
+ /// partial match the remaining part of the device path is returned in
+ /// RemainingDevicePath.
+ ///
+ RemaingDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath (
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &DevicePath,
+ &DeviceHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DevicePath = RemaingDevicePath;
+
+ ///
+ /// Get first node: Acpi Node
+ ///
+ AcpiNode = (ACPI_HID_DEVICE_PATH *) RemaingDevicePath;
+
+ if (AcpiNode->Header.Type != ACPI_DEVICE_PATH ||
+ AcpiNode->Header.SubType != ACPI_DP ||
+ DevicePathNodeLength (&AcpiNode->Header) != sizeof (ACPI_HID_DEVICE_PATH) ||
+ AcpiNode->HID != EISA_PNP_ID (0x0A03) ||
+ AcpiNode->UID != 0
+ ) {
+ return EFI_UNSUPPORTED;
+ } else {
+ ///
+ /// Get the next node: Pci Node
+ ///
+ RemaingDevicePath = NextDevicePathNode (RemaingDevicePath);
+ PciNode = (PCI_DEVICE_PATH *) RemaingDevicePath;
+ if (PciNode->Header.Type != HARDWARE_DEVICE_PATH ||
+ PciNode->Header.SubType != HW_PCI_DP ||
+ DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH)
+ ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (UsbIndex = 0; UsbIndex < sizeof (mUsbControllersMap) / sizeof (USB_CONTROLLER); UsbIndex++) {
+ if ((PciNode->Device == mUsbControllersMap[UsbIndex].Device) &&
+ (PciNode->Function == mUsbControllersMap[UsbIndex].Function)) {
+ *Controller = mUsbControllersMap[UsbIndex].UsbConType;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Maps a USB context to a source description.
+
+ @param[in] Context The context we need to map. Type must be USB.
+ @param[in] SrcDesc The source description that corresponds to the given context.
+
+**/
+VOID
+MapUsbToSrcDesc (
+ IN PCH_SMM_CONTEXT *Context,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PCH_USB_CONTROLLER_TYPE Controller;
+ EFI_STATUS Status;
+
+ Status = DevicePathToSupportedController (Context->Usb.Device, &Controller);
+ ///
+ /// Either the device path passed in by the child is incorrect or
+ /// the ones stored here internally are incorrect.
+ ///
+ ASSERT_EFI_ERROR (Status);
+
+ switch (Context->Usb.Type) {
+ case UsbLegacy:
+ switch (Controller) {
+ case PchUsbControllerLpc0:
+ CopyMem ((VOID *) SrcDesc, (VOID *) (&mUSB1_LEGACY), sizeof (PCH_SMM_SOURCE_DESC));
+ break;
+
+ case PchUsbControllerXhci:
+ CopyMem ((VOID *) SrcDesc, (VOID *) (&mUSB3_LEGACY), sizeof (PCH_SMM_SOURCE_DESC));
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case UsbWake:
+ ASSERT (FALSE);
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
new file mode 100644
index 0000000000..d4f4603eea
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
@@ -0,0 +1,790 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+Copyright (c) 2017, 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 that 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 "PchSmmHelpers.h"
+
+//
+// Help handle porting bit shifts to IA-64.
+//
+#define BIT_ZERO 0x00000001
+
+/**
+ Publish SMI Dispatch protocols.
+
+
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+ VOID
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN Index;
+ //
+ // Install protocol interfaces.
+ //
+ for (Index = 0; Index < PCH_SMM_PROTOCOL_TYPE_MAX; Index++) {
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mPrivateData.InstallMultProtHandle,
+ mPrivateData.Protocols[Index].Guid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.Protocols[Index].Protocols.Generic
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Initialize bits that aren't necessarily related to an SMI source.
+
+
+ @retval EFI_SUCCESS SMI source initialization completed.
+ @retval Asserts Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Clear all SMIs
+ ///
+ PchSmmClearSmi ();
+
+ Status = PchSmmEnableGlobalSmiBit ();
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Be *really* sure to clear all SMIs
+ ///
+ PchSmmClearSmi ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables the PCH to generate SMIs. Note that no SMIs will be generated
+ if no SMI sources are enabled. Conversely, no enabled SMI source will
+ generate SMIs if SMIs are not globally enabled. This is the main
+ switchbox for SMI generation.
+
+
+ @retval EFI_SUCCESS Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+ VOID
+ )
+{
+ UINT32 SmiEn;
+
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+
+ ///
+ /// Set the "global smi enable" bit
+ ///
+ SmiEn |= B_PCH_SMI_EN_GBL_SMI;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN), SmiEn);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clears the SMI after all SMI source have been processed.
+ Note that this function will not work correctly (as it is
+ written) unless all SMI sources have been processed.
+ A revision of this function could manually clear all SMI
+ status bits to guarantee success.
+
+
+ @retval EFI_SUCCESS Clears the SMIs completed
+ @retval Asserts EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+ VOID
+ )
+{
+ BOOLEAN EosSet;
+ BOOLEAN SciEn;
+ UINT32 Pm1Cnt;
+ UINT16 Pm1Sts;
+ UINT32 Gpe0Sts;
+ UINT32 SmiSts;
+ UINT16 DevActSts;
+ UINT16 Tco1Sts;
+
+ Gpe0Sts = 0;
+ ///
+ /// Determine whether an ACPI OS is present (via the SCI_EN bit)
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+ SciEn = (BOOLEAN) ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
+ if (!SciEn) {
+ ///
+ /// Clear any SMIs that double as SCIs (when SCI_EN==0)
+ ///
+ Pm1Sts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS));
+ Gpe0Sts = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96));
+
+ Pm1Sts |=
+ (
+ B_PCH_ACPI_PM1_STS_WAK |
+ B_PCH_ACPI_PM1_STS_PRBTNOR |
+ B_PCH_ACPI_PM1_STS_RTC |
+ B_PCH_ACPI_PM1_STS_PWRBTN |
+ B_PCH_ACPI_PM1_STS_GBL |
+ B_PCH_ACPI_PM1_STS_TMROF
+ );
+
+ Gpe0Sts |=
+ (
+ B_PCH_ACPI_GPE0_STS_127_96_PME_B0 |
+ B_PCH_ACPI_GPE0_STS_127_96_PME |
+ B_PCH_ACPI_GPE0_STS_127_96_BATLOW |
+ B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP |
+ B_PCH_ACPI_GPE0_STS_127_96_RI |
+ B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK |
+ B_PCH_ACPI_GPE0_STS_127_96_TC0SCI |
+ B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG |
+ B_PCH_ACPI_GPE0_STS_127_96_BATLOW |
+ B_PCH_ACPI_GPE0_STS_127_96_LAN_WAKE
+ );
+
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS), (UINT16) Pm1Sts);
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_GPE0_STS_127_96), (UINT32) Gpe0Sts);
+ }
+ ///
+ /// Clear all SMIs that are unaffected by SCI_EN
+ ///
+ SmiSts = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS));
+ DevActSts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_PCH_DEVACT_STS));
+ Tco1Sts = IoRead16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO1_STS));
+
+ SmiSts |=
+ (
+ B_PCH_SMI_STS_SMBUS |
+ B_PCH_SMI_STS_PERIODIC |
+ B_PCH_SMI_STS_TCO |
+ B_PCH_SMI_STS_MCSMI |
+ B_PCH_SMI_STS_SWSMI_TMR |
+ B_PCH_SMI_STS_APM |
+ B_PCH_SMI_STS_ON_SLP_EN |
+ B_PCH_SMI_STS_BIOS
+ );
+ DevActSts |=
+ (
+ B_PCH_DEVACT_STS_KBC |
+ B_PCH_DEVACT_STS_PIRQDH |
+ B_PCH_DEVACT_STS_PIRQCG |
+ B_PCH_DEVACT_STS_PIRQBF |
+ B_PCH_DEVACT_STS_PIRQAE
+ );
+ Tco1Sts |=
+ (
+ B_PCH_TCO1_STS_DMISERR |
+ B_PCH_TCO1_STS_DMISMI |
+ B_PCH_TCO1_STS_DMISCI |
+ B_PCH_TCO1_STS_BIOSWR |
+ B_PCH_TCO1_STS_NEWCENTURY |
+ B_PCH_TCO1_STS_TIMEOUT |
+ B_PCH_TCO1_STS_TCO_INT |
+ B_PCH_TCO1_STS_SW_TCO_SMI
+ );
+
+ GpioClearAllGpiSmiSts ();
+
+ //
+ // If NewCentury Sts is set here, it must clear the NewCentury Sts separately.
+ //
+ PchTcoClearNewCenturySts (NULL);
+
+ IoWrite16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO1_STS), Tco1Sts);
+
+ //
+ // We do not want to write 1 to clear INTRD_DET bit.
+ //
+ IoWrite16 ((UINTN) (mTcoBaseAddr + R_PCH_TCO2_STS), (UINT16) ~B_PCH_TCO2_STS_INTRD_DET);
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_STS), SmiSts);
+
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + R_PCH_DEVACT_STS), DevActSts);
+
+ ///
+ /// Try to clear the EOS bit. ASSERT on an error
+ ///
+ EosSet = PchSmmSetAndCheckEos ();
+ ASSERT (EosSet);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the SMI EOS bit after all SMI source have been processed.
+
+
+ @retval FALSE EOS was not set to a 1; this is an error
+ @retval TRUE EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+ VOID
+ )
+{
+ UINT32 SmiEn;
+
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+
+ ///
+ /// Reset the PCH to generate subsequent SMIs
+ ///
+ SmiEn |= B_PCH_SMI_EN_EOS;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN), SmiEn);
+
+ ///
+ /// Double check that the assert worked
+ ///
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_SMI_EN));
+
+ ///
+ /// Return TRUE if EOS is set correctly
+ ///
+ if ((SmiEn & B_PCH_SMI_EN_EOS) == 0) {
+ ///
+ /// EOS was not set to a 1; this is an error
+ ///
+ return FALSE;
+ } else {
+ ///
+ /// EOS was correctly set to a 1
+ ///
+ return TRUE;
+ }
+}
+
+/**
+ Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+
+ @retval TRUE ACPI OS is present
+ @retval FALSE ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+ VOID
+ )
+{
+ BOOLEAN SciEn;
+ UINT32 Pm1Cnt;
+
+ ///
+ /// Determine whether an ACPI OS is present (via the SCI_EN bit)
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT));
+ SciEn = (BOOLEAN) ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
+
+ return SciEn;
+}
+
+/**
+ Read a specifying bit with the register
+ These may or may not need to change w/ the PCH version; they're highly IA-32 dependent, though.
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+
+ @retval TRUE The bit is enabled
+ @retval FALSE The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Register;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINTN RegSize;
+ BOOLEAN BitWasOne;
+ UINTN ShiftCount;
+ UINTN RegisterOffset;
+ UINT32 BaseAddr;
+ UINTN PciBaseAddress;
+
+ ASSERT (BitDesc != NULL);
+ ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+ RegSize = 0;
+ Register = 0;
+ ShiftCount = 0;
+ BitWasOne = FALSE;
+
+ switch (BitDesc->Reg.Type) {
+
+ case ACPI_ADDR_TYPE:
+ case TCO_ADDR_TYPE:
+ if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
+ RegisterOffset = BitDesc->Reg.Data.acpi;
+ BaseAddr = mAcpiBaseAddr;
+ } else {
+ RegisterOffset = BitDesc->Reg.Data.tco;
+ BaseAddr = mTcoBaseAddr;
+ }
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized.
+ /// Check your assignments to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ RegSize = SMM_IO_UINT8;
+ break;
+
+ case 2:
+ RegSize = SMM_IO_UINT16;
+ break;
+
+ case 4:
+ RegSize = SMM_IO_UINT32;
+ break;
+
+ case 8:
+ RegSize = SMM_IO_UINT64;
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ ///
+ /// Double check that we correctly read in the acpi base address
+ ///
+ ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+ ShiftCount = BitDesc->Bit;
+ ///
+ /// As current CPU Smm Io can only support at most
+ /// 32-bit read/write,if Operation is 64 bit,
+ /// we do a 32 bit operation according to BitDesc->Bit
+ ///
+ if (RegSize == SMM_IO_UINT64) {
+ RegSize = SMM_IO_UINT32;
+ ///
+ /// If the operation is for high 32 bits
+ ///
+ if (BitDesc->Bit >= 32) {
+ RegisterOffset += 4;
+ ShiftCount -= 32;
+ }
+ }
+
+ Status = gSmst->SmmIo.Io.Read (
+ &gSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if ((Register & (LShiftU64 (BIT_ZERO, ShiftCount))) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case GPIO_ADDR_TYPE:
+ case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+ ///
+ /// Read the register, and it with the bit to read
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ Register = (UINT64) MmioRead8 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 2:
+ Register = (UINT64) MmioRead16 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 4:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 8:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+ if (Register) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case PCIE_ADDR_TYPE:
+ PciBus = BitDesc->Reg.Data.pcie.Fields.Bus;
+ PciDev = BitDesc->Reg.Data.pcie.Fields.Dev;
+ PciFun = BitDesc->Reg.Data.pcie.Fields.Fnc;
+ PciReg = BitDesc->Reg.Data.pcie.Fields.Reg;
+ PciBaseAddress = MmPciBase (PciBus, PciDev, PciFun);
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized.
+ /// Check your assignments to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ Register = (UINT64) MmioRead8 (PciBaseAddress + PciReg);
+ break;
+
+ case 2:
+ Register = (UINT64) MmioRead16 (PciBaseAddress + PciReg);
+ break;
+
+ case 4:
+ Register = (UINT64) MmioRead32 (PciBaseAddress + PciReg);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ if ((Register & (LShiftU64 (BIT_ZERO, BitDesc->Bit))) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case PCR_ADDR_TYPE:
+ ///
+ /// Read the register, and it with the bit to read
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ PchPcrRead8 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8*) &Register);
+ break;
+
+ case 2:
+ PchPcrRead16 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16*) &Register);
+ break;
+
+ case 4:
+ PchPcrRead32 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32*) &Register);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+ if (Register) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ default:
+ ///
+ /// This address type is not yet implemented
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+
+ return BitWasOne;
+}
+
+/**
+ Write a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+ @param[in] ValueToWrite The value to be wrote
+ @param[in] WriteClear If the rest bits of the register is write clear
+
+**/
+VOID
+WriteBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc,
+ CONST BOOLEAN ValueToWrite,
+ CONST BOOLEAN WriteClear
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Register;
+ UINT64 AndVal;
+ UINT64 OrVal;
+ UINT32 RegSize;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINTN RegisterOffset;
+ UINT32 BaseAddr;
+ UINTN PciBaseAddress;
+
+ ASSERT (BitDesc != NULL);
+ ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+ RegSize = 0;
+ Register = 0;
+
+ if (WriteClear) {
+ AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit);
+ } else {
+ AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit));
+ }
+
+ OrVal = (LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit));
+
+ switch (BitDesc->Reg.Type) {
+
+ case ACPI_ADDR_TYPE:
+ case TCO_ADDR_TYPE:
+ if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
+ RegisterOffset = BitDesc->Reg.Data.acpi;
+ BaseAddr = mAcpiBaseAddr;
+ } else {
+ RegisterOffset = BitDesc->Reg.Data.tco;
+ BaseAddr = mTcoBaseAddr;
+ }
+
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized.
+ /// Check your assignments to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ RegSize = SMM_IO_UINT8;
+ break;
+
+ case 2:
+ RegSize = SMM_IO_UINT16;
+ break;
+
+ case 4:
+ RegSize = SMM_IO_UINT32;
+ break;
+
+ case 8:
+ RegSize = SMM_IO_UINT64;
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ ///
+ /// Double check that we correctly read in the acpi base address
+ ///
+ ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+ ///
+ /// As current CPU Smm Io can only support at most
+ /// 32-bit read/write,if Operation is 64 bit,
+ /// we do a 32 bit operation according to BitDesc->Bit
+ ///
+ if (RegSize == SMM_IO_UINT64) {
+ RegSize = SMM_IO_UINT32;
+ ///
+ /// If the operation is for high 32 bits
+ ///
+ if (BitDesc->Bit >= 32) {
+ RegisterOffset += 4;
+
+ if (WriteClear) {
+ AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit - 32);
+ } else {
+ AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit - 32));
+ }
+
+ OrVal = LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit - 32);
+ }
+ }
+
+ Status = gSmst->SmmIo.Io.Read (
+ &gSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Register &= AndVal;
+ Register |= OrVal;
+
+ Status = gSmst->SmmIo.Io.Write (
+ &gSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case GPIO_ADDR_TYPE:
+ case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+ ///
+ /// Read the register, or it with the bit to set, then write it back.
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ MmioAndThenOr8 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ MmioAndThenOr16 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ MmioAndThenOr32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ case 8:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+ Register &= AndVal;
+ Register |= OrVal;
+ MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) Register);
+ MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio + 4, *((UINT32 *) (&Register) + 1));
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case PCIE_ADDR_TYPE:
+ PciBus = BitDesc->Reg.Data.pcie.Fields.Bus;
+ PciDev = BitDesc->Reg.Data.pcie.Fields.Dev;
+ PciFun = BitDesc->Reg.Data.pcie.Fields.Fnc;
+ PciReg = BitDesc->Reg.Data.pcie.Fields.Reg;
+ PciBaseAddress = MmPciBase (PciBus, PciDev, PciFun);
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ ///
+ /// Chances are that this field didn't get initialized -- check your assignments
+ /// to bit descriptions.
+ ///
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ MmioAndThenOr8 (PciBaseAddress + PciReg, (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ MmioAndThenOr16 (PciBaseAddress + PciReg, (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ MmioAndThenOr32 (PciBaseAddress + PciReg, (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case PCR_ADDR_TYPE:
+ ///
+ /// Read the register, or it with the bit to set, then write it back.
+ ///
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ PchPcrAndThenOr8 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ PchPcrAndThenOr16 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ PchPcrAndThenOr32 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ default:
+ ///
+ /// Unsupported or invalid register size
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ default:
+ ///
+ /// This address type is not yet implemented
+ ///
+ ASSERT (FALSE);
+ break;
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
new file mode 100644
index 0000000000..273bed32bc
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
@@ -0,0 +1,114 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+Copyright (c) 2017, 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 that 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 _PCHX_SMM_HELPERS_H_
+#define _PCHX_SMM_HELPERS_H_
+
+#include "PchSmm.h"
+
+/**
+ Initialize bits that aren't necessarily related to an SMI source.
+
+
+ @retval EFI_SUCCESS SMI source initialization completed.
+ @retval Asserts Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+ VOID
+ );
+
+/**
+ Enables the PCH to generate SMIs. Note that no SMIs will be generated
+ if no SMI sources are enabled. Conversely, no enabled SMI source will
+ generate SMIs if SMIs are not globally enabled. This is the main
+ switchbox for SMI generation.
+
+
+ @retval EFI_SUCCESS Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+ VOID
+ );
+
+/**
+ Clears the SMI after all SMI source have been processed.
+ Note that this function will not work correctly (as it is
+ written) unless all SMI sources have been processed.
+ A revision of this function could manually clear all SMI
+ status bits to guarantee success.
+
+
+ @retval EFI_SUCCESS Clears the SMIs completed
+ @retval Asserts EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+ VOID
+ );
+
+/**
+ Set the SMI EOS bit after all SMI source have been processed.
+
+
+ @retval FALSE EOS was not set to a 1; this is an error
+ @retval TRUE EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+ VOID
+ );
+
+/**
+ Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+
+ @retval TRUE ACPI OS is present
+ @retval FALSE ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+ VOID
+ );
+
+/**
+ Read a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+
+ @retval TRUE The bit is enabled
+ @retval FALSE The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc
+ );
+
+/**
+ Write a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+ @param[in] ValueToWrite The value to be wrote
+ @param[in] WriteClear If the rest bits of the register is write clear
+
+**/
+VOID
+WriteBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc,
+ CONST BOOLEAN ValueToWrite,
+ CONST BOOLEAN WriteClear
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
new file mode 100644
index 0000000000..2871b6c7c4
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
@@ -0,0 +1,61 @@
+## @file
+# Component description file for SmmControl module
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = SmmControl
+FILE_GUID = A0BAD9F7-AB78-491b-B583-C52B7F84B9E0
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_RUNTIME_DRIVER
+ENTRY_POINT = SmmControlDriverEntryInit
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+
+
+[LibraryClasses]
+IoLib
+UefiDriverEntryPoint
+DebugLib
+UefiBootServicesTableLib
+UefiRuntimeServicesTableLib
+PchCycleDecodingLib
+GpioLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SmmControlDriver.h
+SmmControlDriver.c
+
+
+[Protocols]
+gEfiSmmControl2ProtocolGuid ## PRODUCES
+
+
+[Guids]
+gEfiEventVirtualAddressChangeGuid
+
+
+[Depex]
+TRUE
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
new file mode 100644
index 0000000000..96727dde8f
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
@@ -0,0 +1,400 @@
+/** @file
+ This is the driver that publishes the SMM Control Protocol.
+
+Copyright (c) 2017, 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 that 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 "SmmControlDriver.h"
+
+STATIC SMM_CONTROL_PRIVATE_DATA mSmmControl;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mABase;
+
+VOID
+EFIAPI
+DisablePendingSmis (
+ VOID
+ );
+
+/**
+ Fixup internal data pointers so that the services can be called in virtual mode.
+
+ @param[in] Event The event registered.
+ @param[in] Context Event context.
+
+**/
+VOID
+EFIAPI
+SmmControlVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl.SmmControl.Trigger));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl.SmmControl.Clear));
+}
+
+/**
+ <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The SmmControl module is a DXE RUNTIME driver that provides a standard way
+ for other drivers to trigger software SMIs.
+
+ - @pre
+ - PCH Power Management I/O space base address has already been programmed.
+ If SmmControl Runtime DXE driver is run before Status Code Runtime Protocol
+ is installed and there is the need to use Status code in the driver, it will
+ be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in the System Management Mode Core Interface Specification.
+
+ - @result
+ The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL documented in
+ System Management Mode Core Interface Specification.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_STATUS Results of the installation of the SMM Control Protocol
+**/
+EFI_STATUS
+EFIAPI
+SmmControlDriverEntryInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() Start\n"));
+
+ ///
+ /// Get the Power Management I/O space base address. We assume that
+ /// this base address has already been programmed if this driver is
+ /// being run.
+ ///
+ PchAcpiBaseGet (&mABase);
+
+ Status = EFI_SUCCESS;
+ if (mABase != 0) {
+ ///
+ /// Install the instance of the protocol
+ ///
+ mSmmControl.Signature = SMM_CONTROL_PRIVATE_DATA_SIGNATURE;
+ mSmmControl.Handle = ImageHandle;
+
+ mSmmControl.SmmControl.Trigger = Activate;
+ mSmmControl.SmmControl.Clear = Deactivate;
+ mSmmControl.SmmControl.MinimumTriggerPeriod = 0;
+
+ ///
+ /// Install our protocol interfaces on the device's handle
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mSmmControl.Handle,
+ &gEfiSmmControl2ProtocolGuid,
+ &mSmmControl.SmmControl,
+ NULL
+ );
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ return Status;
+ }
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ SmmControlVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &Event
+ );
+ ///
+ /// Disable any PCH SMIs that, for whatever reason, are asserted after the boot.
+ ///
+ DisablePendingSmis ();
+
+ DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() End\n"));
+
+ return Status;
+}
+
+/**
+ Trigger the software SMI
+
+ @param[in] Data The value to be set on the software SMI data port
+
+ @retval EFI_SUCCESS Function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+ IN UINT8 Data
+ )
+{
+ UINT32 OutputData;
+ UINT32 OutputPort;
+
+ ///
+ /// Enable the APMC SMI
+ ///
+ OutputPort = mABase + R_PCH_SMI_EN;
+ OutputData = IoRead32 ((UINTN) OutputPort);
+ OutputData |= (B_PCH_SMI_EN_APMC | B_PCH_SMI_EN_GBL_SMI);
+ DEBUG (
+ (DEBUG_EVENT,
+ "The SMI Control Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite32 (
+ (UINTN) OutputPort,
+ (UINT32) (OutputData)
+ );
+
+ OutputPort = R_PCH_APM_CNT;
+ OutputData = Data;
+
+ ///
+ /// Generate the APMC SMI
+ ///
+ IoWrite8 (
+ (UINTN) OutputPort,
+ (UINT8) (OutputData)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clear the SMI status
+
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_DEVICE_ERROR Something error occurred
+**/
+EFI_STATUS
+EFIAPI
+SmmClear (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 OutputData;
+ UINT32 OutputPort;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Clear the Power Button Override Status Bit, it gates EOS from being set.
+ ///
+ OutputPort = mABase + R_PCH_ACPI_PM1_STS;
+ OutputData = B_PCH_ACPI_PM1_STS_PRBTNOR;
+ DEBUG (
+ (DEBUG_EVENT,
+ "The PM1 Status Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite16 (
+ (UINTN) OutputPort,
+ (UINT16) (OutputData)
+ );
+
+ ///
+ /// Clear the APM SMI Status Bit
+ ///
+ OutputPort = mABase + R_PCH_SMI_STS;
+ OutputData = B_PCH_SMI_STS_APM;
+ DEBUG (
+ (DEBUG_EVENT,
+ "The SMI Status Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite32 (
+ (UINTN) OutputPort,
+ (UINT32) (OutputData)
+ );
+
+ ///
+ /// Set the EOS Bit
+ ///
+ OutputPort = mABase + R_PCH_SMI_EN;
+ OutputData = IoRead32 ((UINTN) OutputPort);
+ OutputData |= B_PCH_SMI_EN_EOS;
+ DEBUG (
+ (DEBUG_EVENT,
+ "The SMI Control Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite32 (
+ (UINTN) OutputPort,
+ (UINT32) (OutputData)
+ );
+
+ ///
+ /// There is no need to read EOS back and check if it is set.
+ /// This can lead to a reading of zero if an SMI occurs right after the SMI_EN port read
+ /// but before the data is returned to the CPU.
+ /// SMM Dispatcher should make sure that EOS is set after all SMI sources are processed.
+ ///
+ return Status;
+}
+
+/**
+ This routine generates an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in, out] CommandPort The buffer contains data to the command port
+ @param[in, out] DataPort The buffer contains data to the data port
+ @param[in] Periodic Periodic or not
+ @param[in] ActivationInterval Interval of periodic SMI
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL * This,
+ IN OUT UINT8 *CommandPort OPTIONAL,
+ IN OUT UINT8 *DataPort OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN UINTN ActivationInterval OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data;
+
+ if (Periodic) {
+ DEBUG ((DEBUG_WARN, "Invalid parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (CommandPort == NULL) {
+ Data = 0xFF;
+ } else {
+ Data = *CommandPort;
+ }
+ ///
+ /// Clear any pending the APM SMI
+ ///
+ Status = SmmClear ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return SmmTrigger (Data);
+}
+
+/**
+ This routine clears an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in] Periodic Periodic or not
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN BOOLEAN Periodic OPTIONAL
+ )
+{
+ if (Periodic) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return SmmClear ();
+}
+/**
+ Disable all pending SMIs
+
+
+**/
+VOID
+EFIAPI
+DisablePendingSmis (
+ VOID
+ )
+{
+ UINT32 Data;
+ UINT32 Port;
+ BOOLEAN SciEn;
+
+ ///
+ /// Determine whether an ACPI OS is present (via the SCI_EN bit)
+ ///
+ Port = mABase + R_PCH_ACPI_PM1_CNT;
+ Data = IoRead16 ((UINTN) Port);
+ SciEn = (BOOLEAN) ((Data & B_PCH_ACPI_PM1_CNT_SCI_EN) == B_PCH_ACPI_PM1_CNT_SCI_EN);
+
+ if (!SciEn) {
+ ///
+ /// Clear any SMIs that double as SCIs (when SCI_EN==0)
+ ///
+ Port = mABase + R_PCH_ACPI_PM1_STS;
+ Data = 0xFFFF;
+ IoWrite16 ((UINTN) Port, (UINT16) (Data));
+
+ Port = mABase + R_PCH_ACPI_PM1_EN;
+ Data = 0x0000;
+ IoWrite16 ((UINTN) Port, (UINT16) (Data));
+
+ Port = mABase + R_PCH_ACPI_PM1_CNT;
+ Data = 0x0000;
+ IoWrite16 ((UINTN) Port, (UINT16) (Data));
+ Port = mABase + R_PCH_ACPI_GPE0_STS_127_96;
+ Data = (UINT32) ~B_PCH_ACPI_GPE0_STS_127_96_WADT;
+ IoWrite32 ((UINTN) Port, (UINT32) (Data));
+
+ Port = mABase + R_PCH_ACPI_GPE0_EN_127_96;
+ Data = B_PCH_ACPI_GPE0_EN_127_96_WADT;
+ IoWrite32 ((UINTN) Port, (UINT32) (Data));
+ }
+ ///
+ /// Clear and disable all SMIs that are unaffected by SCI_EN
+ ///
+ GpioDisableAllGpiSmi ();
+
+ GpioClearAllGpiSmiSts ();
+
+ Port = mABase + R_PCH_DEVACT_STS;
+ Data = 0xFFFF;
+ IoWrite32 ((UINTN) Port, (UINT32) (Data));
+
+ Port = mABase + R_PCH_SMI_STS;
+ Data = 0xFFFFFFFF;
+ IoWrite32 ((UINTN) Port, (UINT32) (Data));
+
+ ///
+ /// (Make sure to write this register last -- EOS re-enables SMIs for the PCH)
+ ///
+ Port = mABase + R_PCH_SMI_EN;
+ Data = IoRead32 ((UINTN) Port);
+ ///
+ /// clear all bits except those tied to SCI_EN
+ ///
+ Data &= B_PCH_SMI_EN_BIOS_RLS;
+ ///
+ /// enable SMIs and specifically enable writes to APM_CNT.
+ ///
+ Data |= B_PCH_SMI_EN_GBL_SMI | B_PCH_SMI_EN_APMC;
+ ///
+ /// NOTE: Default value of EOS is set in PCH, it will be automatically cleared Once the PCH asserts SMI# low,
+ /// we don't need to do anything to clear it
+ ///
+ IoWrite32 ((UINTN) Port, (UINT32) (Data));
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
new file mode 100644
index 0000000000..110b93a3ca
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
@@ -0,0 +1,148 @@
+/** @file
+ Header file for SMM Control Driver.
+
+Copyright (c) 2017, 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 that 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 _SMM_CONTROL_DRIVER_H_
+#define _SMM_CONTROL_DRIVER_H_
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Guid/EventGroup.h>
+#include <Protocol/SmmControl2.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioLib.h>
+#define EFI_INTERNAL_POINTER 0x00000004
+
+#define SMM_CONTROL_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('i', '4', 's', 'c')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SMM_CONTROL2_PROTOCOL SmmControl;
+} SMM_CONTROL_PRIVATE_DATA;
+
+#define SMM_CONTROL_PRIVATE_DATA_FROM_THIS(a) CR (a, SMM_CONTROL_PRIVATE_DATA, SmmControl, SMM_CONTROL_DEV_SIGNATURE)
+
+//
+// Prototypes
+//
+
+/**
+ <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The SmmControl module is a DXE RUNTIME driver that provides a standard way
+ for other drivers to trigger software SMIs.
+
+ - @pre
+ - PCH Power Management I/O space base address has already been programmed.
+ If SmmControl Runtime DXE driver is run before Status Code Runtime Protocol
+ is installed and there is the need to use Status code in the driver, it will
+ be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in the System Management Mode Core Interface Specification.
+
+ - @result
+ The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL documented in
+ System Management Mode Core Interface Specification.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_STATUS Results of the installation of the SMM Control Protocol
+**/
+EFI_STATUS
+EFIAPI
+SmmControlDriverEntryInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Trigger the software SMI
+
+ @param[in] Data The value to be set on the software SMI data port
+
+ @retval EFI_SUCCESS Function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+ UINT8 Data
+ );
+
+/**
+ Clear the SMI status
+
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_DEVICE_ERROR Something error occurred
+**/
+EFI_STATUS
+EFIAPI
+SmmClear (
+ VOID
+ );
+
+/**
+ This routine generates an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in, out] ArgumentBuffer The buffer of argument
+ @param[in, out] ArgumentBufferSize The size of the argument buffer
+ @param[in] Periodic Periodic or not
+ @param[in] ActivationInterval Interval of periodic SMI
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN OUT UINT8 *ArgumentBuffer OPTIONAL,
+ IN OUT UINT8 *ArgumentBufferSize OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN UINTN ActivationInterval OPTIONAL
+ );
+
+/**
+ This routine clears an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in] Periodic Periodic or not
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN BOOLEAN Periodic OPTIONAL
+ );
+/**
+ Disable all pending SMIs
+
+**/
+VOID
+EFIAPI
+DisablePendingSmis (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.c
new file mode 100644
index 0000000000..5cc808aa9d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.c
@@ -0,0 +1,254 @@
+/** @file
+ PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (c) 2017, 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 that 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 "PchSpi.h"
+
+//
+// Global variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE *mSpiInstance;
+//
+// mPchSpiResvMmioAddr keeps the reserved MMIO range assiged to SPI.
+// In SMM it always set back the reserved MMIO address to SPI BAR0 to ensure the MMIO range
+// won't overlap with SMRAM range, and trusted.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiResvMmioAddr;
+
+/**
+ <b>SPI Runtime SMM Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The SPI SMM module provide a standard way for other modules to use the PCH SPI Interface in SMM.
+
+ - @pre
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in System Management Mode Core Interface Specification .
+
+ - @result
+ The SPI SMM driver produces @link _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL @endlink with GUID
+ gPchSmmSpiProtocolGuid which is different from SPI RUNTIME driver.
+
+ - <b>Integration Check List</b>\n
+ - This driver supports Descriptor Mode only.
+ - This driver supports Hardware Sequence only.
+ - When using SMM SPI Protocol to perform flash access in an SMI handler,
+ and the SMI occurrence is asynchronous to normal mode code execution,
+ proper synchronization mechanism must be applied, e.g. disable SMI before
+ the normal mode SendSpiCmd() starts and re-enable SMI after
+ the normal mode SendSpiCmd() completes.
+ @note The implementation of SendSpiCmd() uses GBL_SMI_EN in
+ SMI_EN register (ABase + 30h) to disable and enable SMIs. But this may
+ not be effective as platform may well set the SMI_LOCK bit (i.e., PMC PCI Offset A0h [4]).
+ So the synchronization at caller level is likely needed.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+ @exception EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Init PCH spi reserved MMIO address.
+ //
+ mSpiResvMmioAddr = PCH_SPI_BASE_ADDRESS;
+
+ ///
+ /// Allocate pool for SPI protocol instance
+ ///
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData, /// MemoryType don't care
+ sizeof (SPI_INSTANCE),
+ (VOID **) &mSpiInstance
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (mSpiInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));
+ ///
+ /// Initialize the SPI protocol instance
+ ///
+ Status = SpiProtocolConstructor (mSpiInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Install the SMM PCH_SPI_PROTOCOL interface
+ ///
+ Status = gSmst->SmmInstallProtocolInterface (
+ &(mSpiInstance->Handle),
+ &gPchSmmSpiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(mSpiInstance->SpiProtocol)
+ );
+ if (EFI_ERROR (Status)) {
+ gSmst->SmmFreePool (mSpiInstance);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Acquire PCH spi mmio address.
+ It is not expected for this BAR0 to change because the SPI device is hidden
+ from the OS for SKL PCH LP/H B stepping and above (refer to section 3.5.1),
+ but if it is ever different from the preallocated address, reassign it back.
+ In SMM, it always override the BAR0 and returns the reserved MMIO range for SPI.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval PchSpiBar0 return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ UINT32 SpiBar0;
+ //
+ // Save original SPI physical MMIO address
+ //
+ SpiBar0 = MmioRead32 (SpiInstance->PchSpiBase + R_PCH_SPI_BAR0) & ~(B_PCH_SPI_BAR0_MASK);
+
+ if (SpiBar0 != mSpiResvMmioAddr) {
+ //
+ // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+ //
+ MmioAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ MmioWrite32 (SpiInstance->PchSpiBase + R_PCH_SPI_BAR0, mSpiResvMmioAddr);
+ MmioOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+ //
+ // SPIBAR0 will be different before and after PCI enum so need to get it from SPI BAR0 reg.
+ //
+ return mSpiResvMmioAddr;
+}
+
+/**
+ Release pch spi mmio address. Do nothing.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+}
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ )
+{
+ UINTN SpiBaseAddress;
+
+ SpiBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ // Write clear BC_SYNC_SS prior to change WPD from 0 to 1.
+ //
+ MmioOr8 (
+ SpiBaseAddress + R_PCH_SPI_BC + 1,
+ (B_PCH_SPI_BC_SYNC_SS >> 8)
+ );
+ ///
+ /// Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
+ /// Enable the access to the BIOS space for both read and write cycles
+ ///
+ MmioOr8 (
+ SpiBaseAddress + R_PCH_SPI_BC,
+ B_PCH_SPI_BC_WPD
+ );
+
+ ///
+ /// PCH BIOS Spec Section 3.7 BIOS Region SMM Protection Enabling
+ /// If the following steps are implemented:
+ /// - Set the EISS bit (SPI PCI Offset DCh [5]) = 1b
+ /// - Follow the 1st recommendation in section 3.6
+ /// the BIOS Region can only be updated by following the steps bellow:
+ /// - Once all threads enter SMM
+ /// - Read memory location FED30880h OR with 00000001h, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ /// - Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
+ /// - Modify BIOS Region
+ /// - Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
+ ///
+ if ((MmioRead8 (SpiBaseAddress + R_PCH_SPI_BC) & B_PCH_SPI_BC_EISS) != 0) {
+ CpuSmmDisableBiosWriteProtect ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ )
+{
+ UINTN SpiBaseAddress;
+
+ SpiBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ ///
+ /// Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
+ /// Disable the access to the BIOS space for write cycles
+ ///
+ MmioAnd8 (
+ SpiBaseAddress + R_PCH_SPI_BC,
+ (UINT8) (~B_PCH_SPI_BC_WPD)
+ );
+
+ ///
+ /// Check if EISS bit is set
+ ///
+ if (((MmioRead8 (SpiBaseAddress + R_PCH_SPI_BC)) & B_PCH_SPI_BC_EISS) == B_PCH_SPI_BC_EISS) {
+ CpuSmmEnableBiosWriteProtect ();
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.h
new file mode 100644
index 0000000000..e3b6d7fd90
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpi.h
@@ -0,0 +1,30 @@
+/** @file
+ Header file for the PCH SPI SMM Driver.
+
+Copyright (c) 2017, 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 that 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 _PCH_SPI_H_
+#define _PCH_SPI_H_
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Protocol/Spi.h>
+#include <Library/PchSpiCommonLib.h>
+#include <Library/CpuCommonLib.h>
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf
new file mode 100644
index 0000000000..52f83a9953
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf
@@ -0,0 +1,54 @@
+## @file
+# Component description file for the SPI SMM driver.
+#
+# Copyright (c) 2017, 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 = 0x00010017
+BASE_NAME = PchSpiSmm
+FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = InstallPchSpi
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+UefiDriverEntryPoint
+UefiBootServicesTableLib
+BaseLib
+SmmServicesTableLib
+PchSpiCommonLib
+CpuCommonLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+PchSpi.h
+PchSpi.c
+
+
+[Protocols]
+gPchSmmSpiProtocolGuid ## PRODUCES
+
+
+[Depex]
+gEfiSmmBase2ProtocolGuid AND # This is for SmmServicesTableLib
+gEfiSmmCpuProtocolGuid # This is for CpuSmmDisableBiosWriteProtect()