summaryrefslogtreecommitdiff
path: root/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt
diff options
context:
space:
mode:
authorJiewen Yao <jiewen.yao@intel.com>2018-03-26 20:50:41 +0800
committerJiewen Yao <jiewen.yao@intel.com>2018-03-26 20:52:27 +0800
commit62f1e1e58965702030f722dcdf6de58998cf08a1 (patch)
treec9381f7c793a1cb61912e89e0ddfd561d883bf41 /Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt
parent062cc36cc27bb55c35e0bdd196e9806bc9d79a3e (diff)
downloadedk2-platforms-62f1e1e58965702030f722dcdf6de58998cf08a1.tar.xz
KabylakeOpenBoardPkg: Add TBT support.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Vishal P Adodariya <vishal.p.adodariya@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Diffstat (limited to 'Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt')
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/AcpiTables/Rtd3SptPcieTbt.asl410
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/AcpiTables/Tbt.asl1909
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Acpi/TbtNvs.asl66
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Acpi/TbtNvsAreaDef.h70
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/DxeTbtPolicyLib.h53
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/PeiTbtPolicyLib.h47
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/TbtCommonLib.h247
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Ppi/PeiTbtPolicy.h36
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Private/Library/PeiDTbtInitLib.h114
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Private/Library/PeiTbtCommonInitLib.h47
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Protocol/DxeTbtPolicy.h117
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Protocol/TbtNvsArea.h48
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/TbtBoardInfo.h28
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/TbtPolicyCommonDefinition.h84
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.c167
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.inf73
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLibrary.h28
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.c321
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.inf69
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.c210
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.inf62
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLibrary.h23
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/Private/PeiDTbtInitLib/PeiDTbtInitLib.c572
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/Private/PeiDTbtInitLib/PeiDTbtInitLib.inf48
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Dxe/TbtDxe.c233
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Dxe/TbtDxe.inf54
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Pei/PeiTbtInit.c216
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Pei/PeiTbtInit.inf50
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmiHandler.c1615
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmiHandler.h185
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmm.c1771
-rw-r--r--Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmm.inf83
32 files changed, 9056 insertions, 0 deletions
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/AcpiTables/Rtd3SptPcieTbt.asl b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/AcpiTables/Rtd3SptPcieTbt.asl
new file mode 100644
index 0000000000..b54b5a41c3
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/AcpiTables/Rtd3SptPcieTbt.asl
@@ -0,0 +1,410 @@
+/** @file
+ ACPI RTD3 SSDT table for SPT PCIe
+
+Copyright (c) 2018, Intel Corporation. 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 PID_ICC 0xDC
+#define R_PCH_PCR_ICC_MSKCKRQ 0x100C ///< Mask Control CLKREQ
+
+External(PCRA,MethodObj)
+External(PCRO,MethodObj)
+External(\MMRP, MethodObj)
+External(\MMTB, MethodObj)
+External(\TRDO, IntObj)
+External(\TRD3, IntObj)
+External(\TBPE, IntObj)
+External(\TOFF, IntObj)
+External(\TBSE, IntObj)
+External(\TBOD, IntObj)
+External(\TBRP, IntObj)
+External(\TBHR, IntObj)
+External(\RTBC, IntObj)
+External(\TBCD, IntObj)
+
+Name(G2SD, 0) // Go2Sx done, set by GO2S, cleaned by _ON
+
+Name(WKEN, 0)
+
+ Method(_S0W, 0)
+ {
+ /// This method returns the lowest D-state supported by PCIe root port during S0 state
+
+ ///- PMEs can be generated from D3hot for ULT
+ Return(4)
+
+ /** @defgroup pcie_s0W PCIE _S0W **/
+ } // End _S0W
+
+ Method (_DSD, 0) {
+ Return (
+ Package () {
+ ToUUID("6211E2C0-58A3-4AF3-90E1-927A4E0C55A4"),
+ Package () {
+ Package (2) {"HotPlugSupportInD3", 1},
+ }
+ }
+ ) // End of Return ()
+ }
+
+ Method(_DSW, 3)
+ {
+ /// This method is used to enable/disable wake from PCIe (WKEN)
+ If (LGreaterEqual(Arg1, 1)) { /// If entering Sx, need to disable WAKE# from generating runtime PME
+ /// Also set 2 to TOFF.
+ Store(0, WKEN)
+ Store (2, TOFF)
+ } Else { /// If Staying in S0
+ If(LAnd(Arg0, Arg2)) ///- Check if Exiting D0 and arming for wake
+ { ///- Set PME
+ Store(1, WKEN)
+ Store (1, TOFF)
+ } Else { ///- Disable runtime PME, either because staying in D0 or disabling wake
+ Store(0, WKEN)
+ Store(0, TOFF)
+ }
+ }
+
+ /** @defgroup pcie_dsw PCIE _DSW **/
+ } // End _DSW
+
+
+ PowerResource(PXP, 0, 0)
+ {
+ /// Define the PowerResource for PCIe slot
+ /// Method: _STA(), _ON(), _OFF()
+ /** @defgroup pcie_pxp PCIE Power Resource **/
+
+ Method(_STA, 0)
+ {
+ Return(PSTA())
+ } /** @defgroup pcie_sta PCIE _STA method **/
+
+ Method(_ON) /// Turn on core power to PCIe Slot
+ {
+ Store(1, TRDO)
+ PON()
+ Store(0, TRDO)
+ } /** @defgroup pcie_on PCIE _ON method **/
+
+ Method(_OFF) /// Turn off core power to PCIe Slot
+ {
+ Store(1, TRD3)
+ POFF()
+ Store(0, TRD3)
+ } // End of Method_OFF
+ } // End PXP
+
+ Method(PSTA, 0)
+ {
+ /// Returns the status of PCIe slot core power
+ // detect power pin status
+ if(LNotEqual(DeRefOf(Index(PWRG, 0)),0)) {
+ if(LEqual(DeRefOf(Index(PWRG, 0)),1)) { // GPIO mode
+ if(LEqual(\_SB.GGOV(DeRefOf(Index(PWRG, 2))),DeRefOf(Index(PWRG, 3)))){
+ Return (1)
+ } Else {
+ Return (0)
+ }
+ } // GPIO mode
+ if(LEqual(DeRefOf(Index(PWRG, 0)),2)) { // IOEX mode
+ if(LEqual(\_SB.PCI0.GEXP.GEPS(DeRefOf(Index(PWRG, 1)),DeRefOf(Index(PWRG, 2))),DeRefOf(Index(PWRG, 3)))){
+ Return (1)
+ } Else {
+ Return (0)
+ }
+ } // IOEX mode
+ }
+ // detect reset pin status
+ if(LNotEqual(DeRefOf(Index(RSTG, 0)),0)) {
+ if(LEqual(DeRefOf(Index(RSTG, 0)),1)) { // GPIO mode
+ if(LEqual(\_SB.GGOV(DeRefOf(Index(RSTG, 2))),DeRefOf(Index(RSTG, 3)))){
+ Return (1)
+ } Else {
+ Return (0)
+ }
+ } // GPIO mode
+ if(LEqual(DeRefOf(Index(RSTG, 0)),2)) { // IOEX mode
+ if(LEqual(\_SB.PCI0.GEXP.GEPS(DeRefOf(Index(RSTG, 1)),DeRefOf(Index(RSTG, 2))),DeRefOf(Index(RSTG, 3)))){
+ Return (1)
+ } Else {
+ Return (0)
+ }
+ } // IOEX mode
+ }
+ Return (0)
+ } /** @defgroup pcie_sta PCIE _STA method **/
+
+ Method (SXEX, 0, Serialized) {
+
+ Store(\MMTB(TBSE), Local7)
+ OperationRegion(TBDI, SystemMemory, Local7, 0x550)// TBT HR PCICFG MMIO
+ Field(TBDI,DWordAcc, NoLock, Preserve) {
+ DIVI, 32,
+ CMDR, 32,
+ Offset(0x548),
+ TB2P, 32,
+ P2TB, 32
+ }
+
+ Store(100, Local1)
+ Store(0x09, P2TB) // Write SX_EXIT_TBT_CONNECTED to PCIe2TBT
+ While (LGreater(Local1, 0)) {
+
+ Store(Subtract(Local1, 1), Local1)
+ Store(TB2P, Local2)
+ If (LEqual(Local2, 0xFFFFFFFF)) { // Device gone
+ Return()
+ }
+ If (And(Local2, 1)) { // Done
+ break
+ }
+ Sleep(5)
+ }
+ Store(0x0, P2TB) // Write 0 to PCIe2TBT
+
+ // Fast Link bring-up flow
+ Store(500, Local1)
+ While (LGreater(Local1, 0)) {
+ Store(Subtract(Local1, 1), Local1)
+ Store(TB2P, Local2)
+ If (LEqual(Local2, 0xFFFFFFFF)) {// Device gone
+ Return()
+ }
+ If (LNotEqual(DIVI, 0xFFFFFFFF)) {
+ break
+ }
+ Sleep(10)
+ }
+ } // End of Method(SXEX, 0, Serialized)
+
+ Method(PON) /// Turn on core power to PCIe Slot
+ {
+
+ Store(\MMRP(\TBSE), Local7)
+ OperationRegion(L23P,SystemMemory,Local7,0xE4)
+ Field(L23P,WordAcc, NoLock, Preserve)
+ {
+ Offset(0xA4),// PMCSR
+ PSD0, 2, // PowerState
+ Offset(0xE2),// 0xE2, RPPGEN - Root Port Power Gating Enable
+ , 2,
+ L2TE, 1, // 2, L23_Rdy Entry Request (L23ER)
+ L2TR, 1, // 3, L23_Rdy to Detect Transition (L23R2DT)
+ }
+
+ Store(\MMTB(\TBSE), Local6)
+ OperationRegion(TBDI, SystemMemory, Local6, 0x550)// TBT HR PCICFG MMIO
+ Field(TBDI,DWordAcc, NoLock, Preserve) {
+ DIVI, 32,
+ CMDR, 32,
+ Offset(0xA4),
+ TBPS, 2, // PowerState of TBT
+ Offset(0x548),
+ TB2P, 32,
+ P2TB, 32
+ }
+
+ Store(0, TOFF)
+ // Check RTD3 power enable, if already ON, no need to execute sx_exit
+ If (TBPE) {
+ Return()
+ }
+
+ Store(0,G2SD)
+ If (\RTBC) {
+ /// de-assert CLK_REQ MSK
+ if(LNotEqual(DeRefOf(Index(SCLK, 0)),0)) { // if power gating enabled
+ PCRA(PID_ICC,R_PCH_PCR_ICC_MSKCKRQ,Not(DeRefOf(Index(SCLK, 1)))) // And ~SCLK to clear bit
+ }
+ Sleep(\TBCD)
+ }
+
+ /// Turn ON Power for PCIe Slot
+ if(LNotEqual(DeRefOf(Index(PWRG, 0)),0)) { // if power gating enabled
+ if(LEqual(DeRefOf(Index(PWRG, 0)),1)) { // GPIO mode
+ \_SB.SGOV(DeRefOf(Index(PWRG, 2)),DeRefOf(Index(PWRG, 3)))
+ Store(1, TBPE)
+ Sleep(PEP0) /// Sleep for programmable delay
+ }
+ if(LEqual(DeRefOf(Index(PWRG, 0)),2)) { // IOEX mode
+ \_SB.PCI0.GEXP.SGEP(DeRefOf(Index(PWRG, 1)),DeRefOf(Index(PWRG, 2)),DeRefOf(Index(PWRG, 3)))
+ Store(1, TBPE)
+ Sleep(PEP0) /// Sleep for programmable delay
+ }
+ }
+
+ /// De-Assert Reset Pin
+ if(LNotEqual(DeRefOf(Index(RSTG, 0)),0)) { // if reset pin enabled
+ if(LEqual(DeRefOf(Index(RSTG, 0)),1)) { // GPIO mode
+ \_SB.SGOV(DeRefOf(Index(RSTG, 2)),DeRefOf(Index(RSTG, 3)))
+ }
+ if(LEqual(DeRefOf(Index(RSTG, 0)),2)) { // IOEX mode
+ \_SB.PCI0.GEXP.SGEP(DeRefOf(Index(RSTG, 1)),DeRefOf(Index(RSTG, 2)),DeRefOf(Index(RSTG, 3)))
+ }
+ }
+
+ /// Clear DLSULPPGE, then set L23_Rdy to Detect Transition (L23R2DT)
+ Store(0, DPGE)
+ Store(1, L2TR)
+ Sleep(16)
+ Store(0, Local0)
+ /// Wait up to 12 ms for transition to Detect
+ While(L2TR) {
+ If(Lgreater(Local0, 4)) // Debug - Wait for 5 ms
+ {
+ Break
+ }
+ Sleep(16)
+ Increment(Local0)
+ }
+ /// Once in Detect, wait up to 124 ms for Link Active (typically happens in under 70ms)
+ /// Worst case per PCIe spec from Detect to Link Active is:
+ /// 24ms in Detect (12+12), 72ms in Polling (24+48), 28ms in Config (24+2+2+2+2)
+ Store(1, DPGE)
+ Store(0, Local0)
+ While(LEqual(LASX,0)) {
+ If(Lgreater(Local0, 8))
+ {
+ Break
+ }
+ Sleep(16)
+ Increment(Local0)
+ }
+ Store(0, LEDM) /// Set PCIEDBG.DMIL1EDM (324[3]) = 0
+
+ // TBT special sleep.
+ Store(PSD0, Local1)
+ Store(0, PSD0)// D0
+ Store(20, Local2) // Poll for TBT, up to 200 ms
+
+ While (LGreater(Local2, 0)) {
+ Store(Subtract(Local2, 1), Local2)
+ Store(TB2P, Local3)
+ If (LNotEqual(Local3, 0xFFFFFFFF)) { // Done
+ break
+ }
+ Sleep(10)
+ }
+
+ If (LLessEqual(Local2, 0)) {
+ }
+ SXEX()
+ Store(Local1, PSD0) // Back to Local1
+ } /** @defgroup pcie_on PCIE _ON method **/
+
+ Method(POFF) { /// Turn off core power to PCIe Slot
+ If (LEqual(TOFF, 0)) {
+ Return()
+ }
+ Store(\MMRP(\TBSE), Local7)
+ OperationRegion(L23P, SystemMemory, Local7, 0xE4)
+ Field(L23P,WordAcc, NoLock, Preserve)
+ {
+ Offset(0xA4),// PMCSR
+ PSD0, 2, // PowerState
+ Offset(0xE2),// 0xE2, RPPGEN - Root Port Power Gating Enable
+ , 2,
+ L2TE, 1, // 2, L23_Rdy Entry Request (L23ER)
+ L2TR, 1, // 3, L23_Rdy to Detect Transition (L23R2DT)
+ }
+
+ Store(\MMTB(TBSE), Local6)
+ OperationRegion(TBDI, SystemMemory, Local6, 0x550)// TBT HR PCICFG MMIO
+ Field(TBDI,DWordAcc, NoLock, Preserve) {
+ DIVI, 32,
+ CMDR, 32,
+ Offset(0xA4),
+ TBPS, 2, // PowerState of TBT
+ Offset(0x548),
+ TB2P, 32,
+ P2TB, 32
+ }
+
+ Store(PSD0, Local1)
+ Store(0, PSD0)// D0
+
+ Store(P2TB, Local3)
+
+ If (Lgreater(TOFF, 1)) {
+ Sleep(10)
+ Store(Local1, PSD0) // Back to Local1
+ Return()
+ }
+ Store(0, TOFF)
+
+ Store(Local1, PSD0) // Back to Local1
+
+ /// Set L23_Rdy Entry Request (L23ER)
+ Store(1, L2TE)
+ Sleep(16)
+ Store(0, Local0)
+ While(L2TE) {
+ If(Lgreater(Local0, 4)) /// Debug - Wait for 5 ms
+ {
+ Break
+ }
+ Sleep(16)
+ Increment(Local0)
+ }
+ Store(1, LEDM) /// PCIEDBG.DMIL1EDM (324[3]) = 1
+
+ /// Assert Reset Pin
+ if(LNotEqual(DeRefOf(Index(RSTG, 0)),0)) { // if reset pin enabled
+ if(LEqual(DeRefOf(Index(RSTG, 0)),1)) { // GPIO mode
+ \_SB.SGOV(DeRefOf(Index(RSTG, 2)),Xor(DeRefOf(Index(RSTG, 3)),1))
+ }
+ if(LEqual(DeRefOf(Index(RSTG, 0)),2)) { // IOEX mode
+ \_SB.PCI0.GEXP.SGEP(DeRefOf(Index(RSTG, 1)),DeRefOf(Index(RSTG, 2)),Xor(DeRefOf(Index(RSTG, 3)),1))
+ }
+ }
+ If (\RTBC) {
+ /// assert CLK_REQ MSK
+ if(LNotEqual(DeRefOf(Index(SCLK, 0)),0)) { // if power gating enabled
+ PCRO(PID_ICC,R_PCH_PCR_ICC_MSKCKRQ,DeRefOf(Index(SCLK, 1))) // Or SCLK to set bit
+ Sleep(16)
+ }
+ }
+
+ /// Power OFF for TBT
+ if(LNotEqual(DeRefOf(Index(PWRG, 0)),0)) { // if power gating enabled
+ if(LEqual(DeRefOf(Index(PWRG, 0)),1)) { // GPIO mode
+ \_SB.SGOV(DeRefOf(Index(PWRG, 2)),Xor(DeRefOf(Index(PWRG, 3)),1))
+ }
+ if(LEqual(DeRefOf(Index(PWRG, 0)),2)) { // IOEX mode
+ \_SB.PCI0.GEXP.SGEP(DeRefOf(Index(PWRG, 1)),DeRefOf(Index(PWRG, 2)),Xor(DeRefOf(Index(PWRG, 3)),1))
+ }
+ }
+
+ Store(0, TBPE)
+
+ Store(1, LDIS) /// Set Link Disable
+ Store(0, LDIS) /// Toggle link disable
+
+ /// enable WAKE
+ If (WKEN) {
+ If (LNotEqual(DeRefOf(Index(WAKG, 0)),0)) { // if power gating enabled
+ If (LEqual(DeRefOf(Index(WAKG, 0)),1)) { // GPIO mode
+ \_SB.SGOV(DeRefOf(Index(WAKG, 2)),DeRefOf(Index(WAKG, 3)))
+ \_SB.SHPO(DeRefOf(Index(WAKG, 2)), 0) // set gpio ownership to ACPI(0=ACPI mode, 1=GPIO mode)
+ }
+ If (LEqual(DeRefOf(Index(WAKG, 0)),2)) { // IOEX mode
+ \_SB.PCI0.GEXP.SGEP(DeRefOf(Index(WAKG, 1)),DeRefOf(Index(WAKG, 2)),DeRefOf(Index(WAKG, 3)))
+ }
+ }
+ }
+ Sleep(\TBOD)
+ /** @defgroup pcie_off PCIE _OFF method **/
+ } // End of Method_OFF
+
+ Name(_PR0, Package(){PXP})
+ Name(_PR3, Package(){PXP})
+
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/AcpiTables/Tbt.asl b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/AcpiTables/Tbt.asl
new file mode 100644
index 0000000000..56c27f3a63
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/AcpiTables/Tbt.asl
@@ -0,0 +1,1909 @@
+/** @file
+ Thunderbolt ACPI methods
+
+Copyright (c) 2018, Intel Corporation. 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 DTBT_CONTROLLER 0x00
+#define DTBT_TYPE_PCH 0x01
+#define DTBT_TYPE_PEG 0x02
+#define DTBT_SMI_HANDLER_NUMBER 0xF7
+#define TBT_SMI_ENUMERATION_FUNCTION 21
+#define TBT_SMI_RESET_SWITCH_FUNCTION 22
+#define TBT_SMI_DISABLE_MSI_FUNCTION 23
+#ifndef BIT29
+#define BIT29 0x20000000
+#endif
+
+Name(LDLY, 300) //300 ms
+Name (TNVB, 0xFFFF0000) // TBT NVS Base address
+Name (TNVL, 0xAA55) // TBT NVS Length
+Include ("Acpi/TbtNvs.asl")
+
+External(\_SB.PCI0.RP02.L23D, MethodObj)
+External(\_SB.PCI0.RP03.L23D, MethodObj)
+External(\_SB.PCI0.RP04.L23D, MethodObj)
+External(\_SB.PCI0.RP05.L23D, MethodObj)
+External(\_SB.PCI0.RP06.L23D, MethodObj)
+External(\_SB.PCI0.RP07.L23D, MethodObj)
+External(\_SB.PCI0.RP08.L23D, MethodObj)
+External(\_SB.PCI0.RP09.L23D, MethodObj)
+External(\_SB.PCI0.RP10.L23D, MethodObj)
+External(\_SB.PCI0.RP11.L23D, MethodObj)
+External(\_SB.PCI0.RP12.L23D, MethodObj)
+External(\_SB.PCI0.RP13.L23D, MethodObj)
+External(\_SB.PCI0.RP14.L23D, MethodObj)
+External(\_SB.PCI0.RP15.L23D, MethodObj)
+External(\_SB.PCI0.RP16.L23D, MethodObj)
+External(\_SB.PCI0.RP17.L23D, MethodObj)
+External(\_SB.PCI0.RP18.L23D, MethodObj)
+External(\_SB.PCI0.RP19.L23D, MethodObj)
+External(\_SB.PCI0.RP20.L23D, MethodObj)
+External(\_SB.PCI0.RP21.L23D, MethodObj)
+External(\_SB.PCI0.RP22.L23D, MethodObj)
+External(\_SB.PCI0.RP23.L23D, MethodObj)
+External(\_SB.PCI0.RP24.L23D, MethodObj)
+
+External(\_SB.PCI0.RP01.DL23, MethodObj)
+External(\_SB.PCI0.RP02.DL23, MethodObj)
+External(\_SB.PCI0.RP03.DL23, MethodObj)
+External(\_SB.PCI0.RP04.DL23, MethodObj)
+External(\_SB.PCI0.RP05.DL23, MethodObj)
+External(\_SB.PCI0.RP06.DL23, MethodObj)
+External(\_SB.PCI0.RP07.DL23, MethodObj)
+External(\_SB.PCI0.RP08.DL23, MethodObj)
+External(\_SB.PCI0.RP09.DL23, MethodObj)
+External(\_SB.PCI0.RP10.DL23, MethodObj)
+External(\_SB.PCI0.RP11.DL23, MethodObj)
+External(\_SB.PCI0.RP12.DL23, MethodObj)
+External(\_SB.PCI0.RP13.DL23, MethodObj)
+External(\_SB.PCI0.RP14.DL23, MethodObj)
+External(\_SB.PCI0.RP15.DL23, MethodObj)
+External(\_SB.PCI0.RP16.DL23, MethodObj)
+External(\_SB.PCI0.RP17.DL23, MethodObj)
+External(\_SB.PCI0.RP18.DL23, MethodObj)
+External(\_SB.PCI0.RP19.DL23, MethodObj)
+External(\_SB.PCI0.RP20.DL23, MethodObj)
+External(\_SB.PCI0.RP21.DL23, MethodObj)
+External(\_SB.PCI0.RP22.DL23, MethodObj)
+External(\_SB.PCI0.RP23.DL23, MethodObj)
+External(\_SB.PCI0.RP24.DL23, MethodObj)
+
+External(\_SB.PCI0.RTEN, MethodObj)
+External(\_SB.PCI0.RTDS, MethodObj)
+External(\_SB.PCI0.RP01.PON, MethodObj)
+External(\_SB.PCI0.RP02.PON, MethodObj)
+External(\_SB.PCI0.RP03.PON, MethodObj)
+External(\_SB.PCI0.RP04.PON, MethodObj)
+External(\_SB.PCI0.RP05.PON, MethodObj)
+External(\_SB.PCI0.RP06.PON, MethodObj)
+External(\_SB.PCI0.RP07.PON, MethodObj)
+External(\_SB.PCI0.RP08.PON, MethodObj)
+External(\_SB.PCI0.RP09.PON, MethodObj)
+External(\_SB.PCI0.RP10.PON, MethodObj)
+External(\_SB.PCI0.RP11.PON, MethodObj)
+External(\_SB.PCI0.RP12.PON, MethodObj)
+External(\_SB.PCI0.RP13.PON, MethodObj)
+External(\_SB.PCI0.RP14.PON, MethodObj)
+External(\_SB.PCI0.RP15.PON, MethodObj)
+External(\_SB.PCI0.RP16.PON, MethodObj)
+External(\_SB.PCI0.RP17.PON, MethodObj)
+External(\_SB.PCI0.RP18.PON, MethodObj)
+External(\_SB.PCI0.RP19.PON, MethodObj)
+External(\_SB.PCI0.RP20.PON, MethodObj)
+External(\_SB.PCI0.RP21.PON, MethodObj)
+External(\_SB.PCI0.RP22.PON, MethodObj)
+External(\_SB.PCI0.RP23.PON, MethodObj)
+External(\_SB.PCI0.RP24.PON, MethodObj)
+External(\_SB.PCI0.PEG0.PG00._ON, MethodObj)
+External(\_SB.PCI0.PEG1.PG01._ON, MethodObj)
+External(\_SB.PCI0.PEG2.PG02._ON, MethodObj)
+//
+// SA:RestrictedBegin
+//
+External(\_SB.PCI0.LKEN, MethodObj)
+External(\_SB.PCI0.LKDS, MethodObj)
+//
+// SA:RestrictedEnd
+//
+
+Name(TRDO, 0) // 1 during TBT RTD3 _ON
+Name(TRD3, 0) // 1 during TBT RTD3 _OFF
+Name(TBPE, 0) // Reflects RTD3_PWR_EN value
+Name(TOFF, 0) // param to TBT _OFF method
+
+ Method (TBON, 0, Serialized) {
+ // TBT On process before entering Sx state.
+ Store(1, TRDO)
+ Switch (ToInteger(\RPS0)) { // TBT Root port Selector
+ Case (1) {
+ If (CondRefOf(\_SB.PCI0.RP01.PON)) {
+ \_SB.PCI0.RP01.PON()
+ }
+ }
+ Case (2) {
+ If (CondRefOf(\_SB.PCI0.RP02.PON)) {
+ \_SB.PCI0.RP02.PON()
+ }
+ }
+ Case (3) {
+ If (CondRefOf(\_SB.PCI0.RP03.PON)) {
+ \_SB.PCI0.RP03.PON()
+ }
+ }
+ Case (4) {
+ If (CondRefOf(\_SB.PCI0.RP04.PON)) {
+ \_SB.PCI0.RP04.PON()
+ }
+ }
+ Case (5) {
+ If (CondRefOf(\_SB.PCI0.RP05.PON)) {
+ \_SB.PCI0.RP05.PON()
+ }
+ }
+ Case (6) {
+ If (CondRefOf(\_SB.PCI0.RP06.PON)) {
+ \_SB.PCI0.RP06.PON()
+ }
+ }
+ Case (7) {
+ If (CondRefOf(\_SB.PCI0.RP07.PON)) {
+ \_SB.PCI0.RP07.PON()
+ }
+ }
+ Case (8) {
+ If (CondRefOf(\_SB.PCI0.RP08.PON)) {
+ \_SB.PCI0.RP08.PON()
+ }
+ }
+ Case (9) {
+ If (CondRefOf(\_SB.PCI0.RP09.PON)) {
+ \_SB.PCI0.RP09.PON()
+ }
+ }
+ Case (10) {
+ If (CondRefOf(\_SB.PCI0.RP10.PON)) {
+ \_SB.PCI0.RP10.PON()
+ }
+ }
+ Case (11) {
+ If (CondRefOf(\_SB.PCI0.RP11.PON)) {
+ \_SB.PCI0.RP11.PON()
+ }
+ }
+ Case (12) {
+ If (CondRefOf(\_SB.PCI0.RP12.PON)) {
+ \_SB.PCI0.RP12.PON()
+ }
+ }
+ Case (13) {
+ If (CondRefOf(\_SB.PCI0.RP13.PON)) {
+ \_SB.PCI0.RP13.PON()
+ }
+ }
+ Case (14) {
+ If (CondRefOf(\_SB.PCI0.RP14.PON)) {
+ \_SB.PCI0.RP14.PON()
+ }
+ }
+ Case (15) {
+ If (CondRefOf(\_SB.PCI0.RP15.PON)) {
+ \_SB.PCI0.RP15.PON()
+ }
+ }
+ Case (16) {
+ If (CondRefOf(\_SB.PCI0.RP16.PON)) {
+ \_SB.PCI0.RP16.PON()
+ }
+ }
+ Case (17) {
+ If (CondRefOf(\_SB.PCI0.RP17.PON)) {
+ \_SB.PCI0.RP17.PON()
+ }
+ }
+ Case (18) {
+ If (CondRefOf(\_SB.PCI0.RP18.PON)) {
+ \_SB.PCI0.RP18.PON()
+ }
+ }
+ Case (19) {
+ If (CondRefOf(\_SB.PCI0.RP19.PON)) {
+ \_SB.PCI0.RP19.PON()
+ }
+ }
+ Case (20) {
+ If (CondRefOf(\_SB.PCI0.RP20.PON)) {
+ \_SB.PCI0.RP20.PON()
+ }
+ }
+ Case (21) {
+ If (CondRefOf(\_SB.PCI0.RP21.PON)) {
+ \_SB.PCI0.RP21.PON()
+ }
+ }
+ Case (22) {
+ If (CondRefOf(\_SB.PCI0.RP22.PON)) {
+ \_SB.PCI0.RP22.PON()
+ }
+ }
+ Case (23) {
+ If (CondRefOf(\_SB.PCI0.RP23.PON)) {
+ \_SB.PCI0.RP23.PON()
+ }
+ }
+ Case (24) {
+ If (CondRefOf(\_SB.PCI0.RP24.PON)) {
+ \_SB.PCI0.RP24.PON()
+ }
+ }
+ }//Switch(ToInteger(RPS0)) // TBT Selector
+ Store(0, TRDO)
+ } // End of TBON
+ //
+ // Name: TBTD
+ // Description: Function to return the TBT RP# device no
+ // Input: Arg0 -> Tbt Root Port value from Tbt NVS
+ // Input: Arg1 -> Tbt port type value from Tbt NVS
+ // Return: TBT RP# device no
+ //
+ Method(TBTD,2)
+ {
+ ADBG("TBTD")
+ If (LEqual(Arg1, DTBT_TYPE_PCH)) {
+ Switch(ToInteger(Arg0))
+ {
+ Case (Package () {1, 2, 3, 4, 5, 6, 7, 8})
+ {
+ Store(0x1C, Local0) //Device28-Function0...Function7 = 11100.000...111
+ }
+ Case (Package () {9, 10, 11, 12, 13, 14, 15, 16})
+ {
+ Store(0x1D, Local0) //Device29-Function0...Function7 = 11101.000...111
+ }
+ Case (Package () {17, 18, 19, 20, 21, 22, 23, 24})
+ {
+ Store(0x1B, Local0) //Device27-Function0...Function3 = 11011.000...011
+ }
+ }
+ } ElseIf (LEqual(Arg1, DTBT_TYPE_PEG)) {
+ Switch(ToInteger(Arg0))
+ {
+ Case (Package () {1, 2, 3})
+ {
+ Store(0x1, Local0) //Device1-Function0...Function2 = 00001.000...010
+ }
+#ifndef CPU_CFL
+ Case (Package () {4})
+ {
+ Store(0x6, Local0) //Device6-Function0 = 00110.000
+ }
+#endif
+ }
+ } Else {
+ Store(0xFF, Local0)
+ }
+
+ ADBG("Device no")
+ ADBG(Local0)
+
+ Return(Local0)
+ } // End of Method(TBTD,1)
+
+ //
+ // Name: TBTF
+ // Description: Function to return the TBT RP# function no
+ // Input: Arg0 -> Tbt Root Port value from Tbt NVS
+ // Input: Arg1 -> Tbt port type value from Tbt NVS
+ // Return: TBT RP# function no
+ //
+ Method(TBTF,2)
+ {
+ ADBG("TBTF")
+ If (LEqual(Arg1, DTBT_TYPE_PCH)) {
+ Switch(ToInteger(Arg0))
+ {
+ Case (1)
+ {
+ Store(And(\RPA1,0xF), Local0) //Device28-Function0 = 11100.000
+ }
+ Case (2)
+ {
+ Store(And(\RPA2,0xF), Local0) //Device28-Function1 = 11100.001
+ }
+ Case (3)
+ {
+ Store(And(\RPA3,0xF), Local0) //Device28-Function2 = 11100.010
+ }
+ Case (4)
+ {
+ Store(And(\RPA4,0xF), Local0) //Device28-Function3 = 11100.011
+ }
+ Case (5)
+ {
+ Store(And(\RPA5,0xF), Local0) //Device28-Function4 = 11100.100
+ }
+ Case (6)
+ {
+ Store(And(\RPA6,0xF), Local0) //Device28-Function5 = 11100.101
+ }
+ Case (7)
+ {
+ Store(And(\RPA7,0xF), Local0) //Device28-Function6 = 11100.110
+ }
+ Case (8)
+ {
+ Store(And(\RPA8,0xF), Local0) //Device28-Function7 = 11100.111
+ }
+ Case (9)
+ {
+ Store(And(\RPA9,0xF), Local0) //Device29-Function0 = 11101.000
+ }
+ Case (10)
+ {
+ Store(And(\RPAA,0xF), Local0) //Device29-Function1 = 11101.001
+ }
+ Case (11)
+ {
+ Store(And(\RPAB,0xF), Local0) //Device29-Function2 = 11101.010
+ }
+ Case (12)
+ {
+ Store(And(\RPAC,0xF), Local0) //Device29-Function3 = 11101.011
+ }
+ Case (13)
+ {
+ Store(And(\RPAD,0xF), Local0) //Device29-Function4 = 11101.100
+ }
+ Case (14)
+ {
+ Store(And(\RPAE,0xF), Local0) //Device29-Function5 = 11101.101
+ }
+ Case (15)
+ {
+ Store(And(\RPAF,0xF), Local0) //Device29-Function6 = 11101.110
+ }
+ Case (16)
+ {
+ Store(And(\RPAG,0xF), Local0) //Device29-Function7 = 11101.111
+ }
+ Case (17)
+ {
+ Store(And(\RPAH,0xF), Local0) //Device27-Function0 = 11011.000
+ }
+ Case (18)
+ {
+ Store(And(\RPAI,0xF), Local0) //Device27-Function1 = 11011.001
+ }
+ Case (19)
+ {
+ Store(And(\RPAJ,0xF), Local0) //Device27-Function2 = 11011.010
+ }
+ Case (20)
+ {
+ Store(And(\RPAK,0xF), Local0) //Device27-Function3 = 11011.011
+ }
+ Case (21)
+ {
+ Store(And(\RPAL,0xF), Local0) //Device27-Function4 = 11011.100
+ }
+ Case (22)
+ {
+ Store(And(\RPAM,0xF), Local0) //Device27-Function5 = 11011.101
+ }
+ Case (23)
+ {
+ Store(And(\RPAN,0xF), Local0) //Device27-Function6 = 11011.110
+ }
+ Case (24)
+ {
+ Store(And(\RPAO,0xF), Local0) //Device27-Function7 = 11011.111
+ }
+ }
+ } ElseIf (LEqual(Arg1, DTBT_TYPE_PEG)) {
+ Switch(ToInteger(Arg0))
+ {
+ Case (1)
+ {
+ Store(0x0, Local0) //Device1-Function0 = 00001.000
+ }
+ Case (2)
+ {
+ Store(0x1, Local0) //Device1-Function1 = 00001.001
+ }
+ Case (3)
+ {
+ Store(0x2, Local0) //Device1-Function2 = 00001.010
+ }
+#ifndef CPU_CFL
+ Case (4)
+ {
+ Store(0x0, Local0) //Device6-Function0 = 00110.000
+ }
+#endif
+ }
+ } Else {
+ Store(0xFF, Local0)
+ }
+
+ ADBG("Function no")
+ ADBG(Local0)
+
+ Return(Local0)
+ } // End of Method(TBTF,1)
+
+ //
+ // Name: MMRP
+ // Description: Function to return the Pci base address of TBT rootport
+ // Input: Arg0 -> Tbt Root Port value from Tbt NVS
+ // Input: Arg1 -> Tbt port type value from Tbt NVS
+ //
+
+ Method(MMRP, 2, Serialized)
+ {
+ Store(\_SB.PCI0.GPCB(), Local0) // MMIO Base address
+ Add(Local0, ShiftLeft(TBTD(Arg0, Arg1), 15), Local0) // Device no
+ Add(Local0, ShiftLeft(TBTF(Arg0, Arg1), 12), Local0) // Function no
+
+ Return(Local0)
+ } // End of Method(MMRP)
+
+ //
+ // Name: MMRP
+ // Description: Function to return the Pci base address of TBT Up stream port
+ // Input: Arg0 -> Tbt Root Port value from Tbt NVS
+ // Input: Arg1 -> Tbt port type value from Tbt NVS
+ //
+ Method(MMTB, 2, Serialized)
+ {
+ ADBG("MMTB")
+
+ Store(\_SB.PCI0.GPCB(), Local0) // MMIO Base address
+
+ Add(Local0, ShiftLeft(TBTD(Arg0, Arg1), 15), Local0) // Device no
+ Add(Local0, ShiftLeft(TBTF(Arg0, Arg1), 12), Local0) // Function no
+
+ OperationRegion (MMMM, SystemMemory, Local0, 0x1A)
+ Field (MMMM, AnyAcc, NoLock, Preserve)
+ {
+ Offset(0x19),
+ SBUS, 8
+ }
+ Store(SBUS, Local2)
+ Store(\_SB.PCI0.GPCB(), Local0)
+ Multiply(Local2, 0x100000, Local2)
+ Add(Local2, Local0, Local0) // TBT HR US port
+
+ ADBG("TBT-US-ADR")
+ ADBG(Local0)
+
+ Return(Local0)
+ } // End of Method(MMTB, 1, Serialized)
+ //
+ // Name: FFTB
+ // Description: Function to Check for FFFF in TBT PCIe
+ // Input: Arg0 -> Tbt Root Port value from Tbt NVS
+ // Input: Arg1 -> Tbt port type value from Tbt NVS
+ // Return: 1 if TBT PCIe space has value FFFF, 0 if not
+ //
+ Method(FFTB, 2, Serialized)
+ {
+ ADBG("FFTB")
+
+ Add(MMTB(Arg0, Arg1), 0x548, Local0)
+ OperationRegion(PXVD,SystemMemory,Local0,0x08)
+ Field(PXVD,DWordAcc, NoLock, Preserve)
+ {
+ TB2P, 32,
+ P2TB, 32
+ }
+
+ Store(TB2P, Local1)
+
+ If(LEqual(Local1, 0xFFFFFFFF))
+ {
+ ADBG("FFTb 1")
+ Return (1)
+ }
+ Else
+ {
+ ADBG("FFTb 0")
+ Return (0)
+ }
+ } // End of Method(FFTB)
+
+Name(TDMA, 0x80000000) // Address of Thunderbolt(TM) debug memory buffer, fixed up during POST
+
+Scope(\_GPE)
+{
+ //
+ //
+ //OS up Mail Box command execution to host router upstream port each time
+ //exiting from Sx State .Avoids intermediate
+ //PCIe Scan by OS during resorce allocation
+ // Arg0 : PCIe Base address
+ // Arg1 : Controller Type 0x00 : DTBT
+ //Developer notes: Called twice
+ // 1. During OS INIT (booting to OS from S3-S5/Reboot)
+ // 2. Up on Hot plug
+ //
+ Method(OSUP, 2, Serialized)
+ {
+ ADBG("OSUP")
+
+ Add(Arg0, 0x540, Local0)
+ OperationRegion(PXVD,SystemMemory,Local0,0x10)
+ Field(PXVD,DWordAcc, NoLock, Preserve)
+ {
+ IT2P, 32,
+ IP2T, 32,
+ DT2P, 32,
+ DP2T, 32
+ }
+
+ Store(100, Local1)
+ Store(0x0D, DP2T) // Write OS_Up to PCIe2TBT
+
+ While(LGreater(Local1, 0))
+ {
+ Store(Subtract(Local1, 1), Local1)
+ Store(DT2P, Local2)
+
+ If(LAnd(LEqual(Local2, 0xFFFFFFFF),LEqual(Arg1, DTBT_CONTROLLER)))// Device gone
+ {
+ ADBG("Dev gone")
+ Return(2)
+ }
+ If(And(Local2, 1)) // Done
+ {
+ ADBG("Cmd acknowledged")
+ break
+ }
+ Sleep(50)
+ }
+ If(LEqual(TRWA,1))
+ {
+ Store(0xC, DP2T) // Write OSUP to PCIe2TBT
+ }
+ Else
+ {
+ Store(0x0, DP2T) // Write 0 to PCIe2TBT
+ }
+
+ //Store(0x00, P2TB) // Write 0 to PCIe2TBT
+
+ ADBG("End-of-OSUP")
+
+ Return(1)
+ } // End of Method(OSUP, 1, Serialized)
+
+ //
+ // Check for FFFF in TBT
+ // Input: Arg0 -> Tbt Root Port value from Tbt NVS
+ // Input: Arg1 -> Tbt port type value from Tbt NVS
+ //
+
+ Method(TBFF, 2, Serialized)
+ {
+ ADBG("TBFF")
+
+ Store(MMTB(Arg0, Arg1), Local0)
+ OperationRegion (PXVD, SystemMemory, Local0, 0x8)
+ Field (PXVD, DWordAcc, NoLock, Preserve) {
+ VEDI, 32, // Vendor/Device ID
+ CMDR, 32 // CMD register
+ }
+
+ Store(VEDI, Local1)
+
+ If (LEqual(Local1, 0xFFFFFFFF)) {
+ If (LNotEqual(\TWIN, 0)) { // TBT Enumeration is Native mode?
+ If (LEqual(CMDR, 0xFFFFFFFF)) { // Device Gone
+ Return (2)// Notify only
+ }
+ Return (1)// Exit w/o notify
+ } Else {
+ Return (OSUP(Local0, DTBT_CONTROLLER))
+ }
+ } Else
+ {
+ ADBG("Dev Present")
+ Return (0)
+ }
+ } // End of Method(TBFF, 1, Serialized)
+
+ //
+ // Secondary bus of TBT RP
+ // Input: Arg0 -> Tbt Root Port value from Tbt NVS
+ // Input: Arg1 -> Tbt port type value from Tbt NVS
+ //
+
+ Method(TSUB, 2, Serialized)
+ {
+ ADBG("TSUB")
+
+ Store(\_SB.PCI0.GPCB(), Local0) // MMIO Base address
+
+ Add(Local0, ShiftLeft(TBTD(Arg0, Arg1), 15), Local0) // Device no
+ Add(Local0, ShiftLeft(TBTF(Arg0, Arg1), 12), Local0) // Function no
+
+ ADBG("ADR")
+ ADBG(Local0)
+
+ OperationRegion (MMMM, SystemMemory, Local0, 0x1A)
+ Field (MMMM, AnyAcc, NoLock, Preserve)
+ {
+ Offset(0x19),
+ SBUS, 8
+ }
+
+ ADBG("Sec Bus")
+ ADBG(SBUS)
+
+ Return(SBUS)
+ } // End of Method(TSUB, 0, Serialized)
+
+ //
+ // Pmem of TBT RP
+ // Input: Arg0 -> Tbt Root Port value from Tbt NVS
+ // Input: Arg1 -> Tbt port type value from Tbt NVS
+ //
+
+ Method(TSUP, 2, Serialized)
+ {
+ ADBG("TSUB")
+
+ Store(\_SB.PCI0.GPCB(), Local0) // MMIO Base address
+
+ Add(Local0, ShiftLeft(TBTD(Arg0, Arg1), 15), Local0) // Device no
+ Add(Local0, ShiftLeft(TBTF(Arg0, Arg1), 12), Local0) // Function no
+
+ ADBG("ADR:")
+ ADBG(Local0)
+
+ OperationRegion (MMMM, SystemMemory, Local0, 0x30)
+ Field (MMMM, AnyAcc, NoLock, Preserve)
+ {
+ CMDS, 32,
+ Offset(0x19),
+ SBUS, 8,
+ SBU5, 8,
+ Offset(0x1C),
+ SEIO, 32,
+ MMBL, 32,
+ PMBL, 32,
+
+ }
+
+ ADBG("Pmem of TBT RP:")
+ ADBG(PMBL)
+
+ Return(PMBL)
+ } // End of Method(TSUP, 0, Serialized)
+
+ //
+ // Wait for secondary bus in TBT RP
+ // Input: Arg0 -> Tbt Root Port value from Tbt NVS
+ // Input: Arg1 -> Tbt port type value from Tbt NVS
+ //
+
+ Method(WSUB, 2, Serialized)
+ {
+ ADBG(Concatenate("WSUB=", ToHexString(Arg0)))
+ ADBG(ToHexString(Timer))
+
+ Store(0, Local0)
+ Store(0, Local1)
+ While(1)
+ {
+ Store(TSUP(Arg0, Arg1), Local1)
+ If(LGreater(Local1, 0x1FFF1))
+ {
+ ADBG("WSUB-Finished")
+ Break
+ }
+ Else
+ {
+ Add(Local0, 1, Local0)
+ If(LGreater(Local0, 1000))
+ {
+ Sleep(1000)
+ ADBG("WSUB-Deadlock")
+ }
+ Else
+ {
+ Sleep(16)
+ }
+ }
+ }
+ ADBG(Concatenate("WSUb=", ToHexString(Local1)))
+ } // End of Method(WSUB)
+
+ // Wait for _WAK finished
+ Method(WWAK)
+ {
+ ADBG("WWAK")
+
+ Wait(WFEV, 0xFFFF)
+ Signal(WFEV) // Set it, to enter on next HP
+ } // End of Method(WWAK)
+
+ Method(NTFY, 2, Serialized)
+ {
+ ADBG("NTFY")
+
+ If(LEqual(NOHP,1))
+ {
+ If (LEqual(Arg1, DTBT_TYPE_PCH)) {
+ Switch(ToInteger(Arg0)) // TBT Selector
+ {
+ Case (1)
+ {
+ ADBG("Notify RP01")
+ Notify(\_SB.PCI0.RP01,0)
+ }
+ Case (2)
+ {
+ ADBG("Notify RP02")
+ Notify(\_SB.PCI0.RP02,0)
+ }
+ Case (3)
+ {
+ ADBG("Notify RP03")
+ Notify(\_SB.PCI0.RP03,0)
+ }
+ Case (4)
+ {
+ ADBG("Notify RP04")
+ Notify(\_SB.PCI0.RP04,0)
+ }
+ Case (5)
+ {
+ ADBG("Notify RP05")
+ Notify(\_SB.PCI0.RP05,0)
+ }
+ Case (6)
+ {
+ ADBG("Notify RP06")
+ Notify(\_SB.PCI0.RP06,0)
+ }
+ Case (7)
+ {
+ ADBG("Notify RP07")
+ Notify(\_SB.PCI0.RP07,0)
+ }
+ Case (8)
+ {
+ ADBG("Notify RP08")
+ Notify(\_SB.PCI0.RP08,0)
+ }
+ Case (9)
+ {
+ ADBG("Notify RP09")
+ Notify(\_SB.PCI0.RP09,0)
+ }
+ Case (10)
+ {
+ ADBG("Notify RP10")
+ Notify(\_SB.PCI0.RP10,0)
+ }
+ Case (11)
+ {
+ ADBG("Notify RP11")
+ Notify(\_SB.PCI0.RP11,0)
+ }
+ Case (12)
+ {
+ ADBG("Notify RP12")
+ Notify(\_SB.PCI0.RP12,0)
+ }
+ Case (13)
+ {
+ ADBG("Notify RP13")
+ Notify(\_SB.PCI0.RP13,0)
+ }
+ Case (14)
+ {
+ ADBG("Notify RP14")
+ Notify(\_SB.PCI0.RP14,0)
+ }
+ Case (15)
+ {
+ ADBG("Notify RP15")
+ Notify(\_SB.PCI0.RP15,0)
+ }
+ Case (16)
+ {
+ ADBG("Notify RP16")
+ Notify(\_SB.PCI0.RP16,0)
+ }
+ Case (17)
+ {
+ ADBG("Notify RP17")
+ Notify(\_SB.PCI0.RP17,0)
+ }
+ Case (18)
+ {
+ ADBG("Notify RP18")
+ Notify(\_SB.PCI0.RP18,0)
+ }
+ Case (19)
+ {
+ ADBG("Notify RP19")
+ Notify(\_SB.PCI0.RP19,0)
+ }
+ Case (20)
+ {
+ ADBG("Notify RP20")
+ Notify(\_SB.PCI0.RP20,0)
+ }
+ Case (21)
+ {
+ ADBG("Notify RP21")
+ Notify(\_SB.PCI0.RP21,0)
+ }
+ Case (22)
+ {
+ ADBG("Notify RP22")
+ Notify(\_SB.PCI0.RP22,0)
+ }
+ Case (23)
+ {
+ ADBG("Notify RP23")
+ Notify(\_SB.PCI0.RP23,0)
+ }
+ Case (24)
+ {
+ ADBG("Notify RP24")
+ Notify(\_SB.PCI0.RP24,0)
+ }
+ }//Switch(ToInteger(TBSS)) // TBT Selector
+ } ElseIf (LEqual(Arg1, DTBT_TYPE_PEG)) {
+ Switch(ToInteger(Arg0))
+ {
+ Case (1)
+ {
+ ADBG("Notify PEG0")
+ Notify(\_SB.PCI0.PEG0,0)
+ }
+ Case (2)
+ {
+ ADBG("Notify PEG1")
+ Notify(\_SB.PCI0.PEG1,0)
+ }
+ Case (3)
+ {
+ ADBG("Notify PEG2")
+ Notify(\_SB.PCI0.PEG2,0)
+ }
+#ifndef CPU_CFL
+ Case (4)
+ {
+ ADBG("Notify PEG3")
+ Notify(\_SB.PCI0.PEG3,0)
+ }
+#endif
+ }
+ }//Switch(ToInteger(TBSS)) // TBT Selector
+ }//If(NOHP())
+ P8XH(0,0xC2)
+ P8XH(1,0xC2)
+ }// End of Method(NTFY)
+
+//
+// TBT BIOS, GPIO 5 filtering,
+// Hot plug of 12V USB devices, into TBT host router, cause electrical noise on PCH GPIOs,
+// This noise cause false hot-plug events, and negatively influence BIOS assisted hot-plug.
+// SKL-PCH GPIO does not implement Glitch Filter logic (refer to GPIO HAS) on any GPIO pad. Native functions have to implement their own digital glitch-filter logic
+// if needed. As HW filter was not implemented on SKL PCH, because of that SW workaround should be implemented in BIOS.
+// Register 0x544(Bios mailbox) bit 0 definition:
+// if BIOS reads bit as 1, BIOS will clear the bit and continue normal flow, if bit is 0 BIOS will exit from method
+//
+
+ Method(GNIS,2, Serialized)
+ {
+
+ ADBG("GNIS")
+ If(LEqual(GP5F, 0))
+ {
+ ADBG("GNIS_Dis=0")
+ Return(0)
+ }
+ //
+ // BIOS mailbox command for GPIO filter
+ //
+ Add(MMTB(Arg0, Arg1), 0x544, Local0)
+ OperationRegion(PXVD,SystemMemory,Local0,0x08)
+
+ Field(PXVD,DWordAcc, NoLock, Preserve)
+ {
+ HPFI, 1,
+ Offset(0x4),
+ TB2P, 32
+ }
+ Store(TB2P, Local1)
+ ADBG(Concatenate("TB2P=", ToHexString(Local1)))
+ If(LEqual(Local1, 0xFFFFFFFF)) // Disconnect?
+ {
+ ADBG("GNIS=0")
+ Return(0)
+ }
+ Store(HPFI, Local2)
+ ADBG(Concatenate("HPFI=", ToHexString(Local2)))
+ If(LEqual(Local2, 0x01))
+ {
+ Store(0x00, HPFI)
+ ADBG("GNIS=0")
+ Return(0)
+ }
+ // Any other values treated as a GPIO noise
+ ADBG("GNIS=1")
+ Return(1)
+ }
+
+ Method(CHKP,2, Serialized)
+ {
+ Add(MMTB(Arg0, Arg1), 0x544, Local0)
+ OperationRegion(PXVE,SystemMemory,Local0,0x08)
+
+ Field(PXVE,DWordAcc, NoLock, Preserve)
+ {
+ HPFI, 1,
+ Offset(0x4),
+ TB2P, 32
+ }
+ Store(TB2P, Local1)
+ And(Local1,BIT29,Local1)
+ ADBG(Concatenate("Local1=", ToHexString(Local1)))
+ //ADBG(Concatenate("BIT29=", ToHexString(LAnd(Local1,BIT29))))
+ If(LEqual(Local1, BIT29))
+ {
+ Return(1)
+ }
+ Else
+ {
+ Return(0)
+ }
+ }
+
+ //
+ // Method to Handle enumerate PCIe structure through
+ // SMI for Thunderbolt(TM) devices
+ //
+ Method(XTBT,2, Serialized)
+ {
+ ADBG("XTBT")
+ ADBG("RP :")
+ ADBG(Arg0)
+ Store(Arg0, DTCP) // Root port to enumerate
+ Store(Arg1, DTPT) // Root port Type
+ If(LEqual(Arg0, RPS0)) {
+ Store (1, Local0)
+ } ElseIf (LEqual(Arg0, RPS1)) {
+ Store (2, Local0)
+ } Else {
+ Store (0, Local0)
+ Return ()
+ }
+
+ If (TRDO) {
+ ADBG("Durng TBT_ON")
+ Return ()
+ }
+
+ If (TRD3) {
+ ADBG("During TBT_OFF")
+ Return ()
+ }
+ WWAK()
+ WSUB(Arg0, Arg1)
+ If(GNIS(Arg0, Arg1))
+ {
+ Return()
+ }
+
+ OperationRegion(SPRT,SystemIO, 0xB2,2)
+ Field (SPRT, ByteAcc, Lock, Preserve)
+ {
+ SSMP, 8
+ }
+
+ ADBG("TBT-HP-Handler")
+
+ Acquire(OSUM, 0xFFFF)
+ Store(TBFF(Arg0, Arg1), Local1)
+ If(LEqual(Local1, 1))// Only HR
+ {
+ Sleep(16)
+ Release(OSUM)
+ ADBG("OS_Up_Received")
+ Return ()
+ }
+ If(LEqual(Local1, 2)) // Disconnect
+ {
+ NTFY(Arg0, Arg1)
+ Sleep(16)
+ Release(OSUM)
+ ADBG("Disconnect")
+ Return ()
+ }
+
+ // HR and EP
+ If(LEqual(SOHP, 1))
+ {
+ // Trigger SMI to enumerate PCIe Structure
+ ADBG("TBT SW SMI")
+ Store(21, TBSF)
+ Store(0xF7, SSMP)
+ }
+ NTFY(Arg0, Arg1)
+ Sleep(16)
+ Release(OSUM)
+
+ ADBG("End-of-XTBT")
+ } // End of Method(XTBT)
+
+ //
+ // Calling Method to Handle enumerate PCIe structure through
+ // SMI for Thunderbolt(TM) devices for Tier 1 GPIOs
+ // Used in Two ways ,
+ // If CIO GPIO(1 Tier) is Different for the Controllers, this will be used as 1 Tier GPIO Handler for 1st controller
+ // If CIO GPIO(1 Tier) is Same for all the controllers, this will be used as 1 Tier GPIO Handler for All the controllers
+ //
+ Method(ATBT)
+ {
+ ADBG("ATBT")
+ //
+ // Calling Method to Handle enumerate PCIe structure through
+ //
+ If(LEqual(CGST,0)) { // If GPIO is Different for each controller
+ If(LEqual(RPN0,1))
+ {
+ XTBT(RPS0, RPT0)
+ }
+ } Else {
+ If(LEqual(RPN0,1))
+ {
+ XTBT(RPS0, RPT0)
+ }
+ ElseIf(LEqual(RPN1,1))
+ {
+ XTBT(RPS1, RPT1)
+ }
+ }
+ ADBG("End-of-ATBT")
+ } // End of Method(ATBT)
+
+ Method(BTBT)
+ {
+ ADBG("BTBT")
+ //
+ // Calling Method to Handle enumerate PCIe structure through
+ //
+ If(LEqual(CGST,0)) { // If GPIO is Different for each controller
+ If(LEqual(RPN1,1))
+ {
+ XTBT(RPS1, RPT1)
+ }
+ }
+ ADBG("End-of-BTBT")
+ } // End of Method(BTBT)
+ //
+ // Method to call OSPU Mail box command
+ // Arg0 : Controller type 0x00 : Discrete 0x80 : Integrated TBT
+ // Arg1 : TBT RP Selector / DMA
+ // Arg2 : TBT Type (PCH or PEG)
+ //
+ Method(TINI, 3, Serialized)
+ {
+ ADBG("TINI")
+ If(Lequal (Arg0, DTBT_CONTROLLER))
+ {
+ //ADBG("DTBT")
+ Store(MMRP(Arg1, Arg2), Local0)
+ OperationRegion(RP_X,SystemMemory,Local0,0x20)
+ Field(RP_X,DWordAcc, NoLock, Preserve)
+ {
+ REG0, 32,
+ REG1, 32,
+ REG2, 32,
+ REG3, 32,
+ REG4, 32,
+ REG5, 32,
+ REG6, 32,
+ REG7, 32
+ }
+ Store(REG6, Local1)
+ Store(0x00F0F000, REG6)
+ Store(MMTB(Arg1, Arg2), Local2)
+ OSUP(Local2, DTBT_CONTROLLER)
+ Store(Local1, REG6)
+ }
+ ADBG("End-of-TINI")
+ }
+
+} // End of Scope (\_GPE)
+
+Scope (\_SB)
+{
+ //
+ // The code needs to be executed for TBT Hotplug Handler event (2-tier GPI GPE event architecture) is presented here
+ //
+ Method(THDR, 3, Serialized)
+ {
+ ADBG("THDR")
+ \_SB.CAGS(Arg0)
+ \_GPE.XTBT(Arg1, Arg2)
+ } // End of Method(THDR, 3, Serialized)
+} // End of Scope(\_SB)
+
+Scope (\_SB)
+{
+ //
+ // Name: CGWR [Combined GPIO Write]
+ // Description: Function to write into GPIO
+ // Input: Arg0 -> GpioPad / Expander pin
+ // Arg1 -> Value
+ // Return: Nothing
+ //
+ Method(CGWR, 2, Serialized)
+ {
+ // PCH
+ If (CondRefOf(\_SB.SGOV))
+ {
+ \_SB.SGOV(Arg0, Arg1)
+ }
+ } // End of Method(CGWR, 4, Serialized)
+
+ //
+ // Name: CGRD [Combined GPIO Read]
+ // Description: Function to read from GPIO
+ // Input: Arg0 -> GpioPad / Expander pin
+ // Arg1 -> 0: GPO [GPIO TX State]
+ // 1: GPI [GPIO RX State]
+ // Return: Value
+ //
+ Method(CGRD, 2, Serialized)
+ {
+ Store(1, Local0)
+ // PCH
+ If (LEqual(Arg1, 0))
+ {
+ // GPIO TX State
+ If (CondRefOf(\_SB.GGOV))
+ {
+ Store(\_SB.GGOV(Arg0), Local0)
+ }
+ }
+ ElseIf (LEqual(Arg1, 1))
+ {
+ // GPIO RX State
+ If (CondRefOf(\_SB.GGIV))
+ {
+ Store(\_SB.GGIV(Arg0), Local0)
+ }
+ }
+ Return(Local0)
+ } // End of Method(CGRD, 4, Serialized)
+ //
+ // Name: WRGP [GPIO Write]
+ // Description: Function to write into GPIO
+ // Input: Arg0 -> COMMON_GPIO_CONFIG GpioInfo
+ // Arg1 -> Value
+ // Return: Nothing
+ //
+ Method(WRGP, 2, Serialized)
+ {
+ Store(Arg0, Local0)
+ Store(Arg0, Local1)
+ And(Local0, 0xFFFFFFFF, Local0) // Low 32 bits (31:00)
+ ShiftRight(Local1, 32, Local1) // High 32 bits (63:32)
+ If (LEqual(And(Local0, 0xFF), 1))
+ {
+ // PCH
+ \_SB.CGWR(Local1, Arg1)
+ }
+ } // End of Method(WRGP, 2, Serialized)
+
+ //
+ // Name: RDGP [GPIO Read]
+ // Description: Function to write into GPIO
+ // Input: Arg0 -> COMMON_GPIO_CONFIG GpioInfo
+ // Arg1 -> In case of PCH Gpio Read {GPIO TX(0)/RX(1) State indicator}
+ // Return: Value
+ //
+ Method(RDGP, 2, Serialized)
+ {
+ Store(1, Local7)
+ Store(Arg0, Local0)
+ Store(Arg0, Local1)
+ And(Local0, 0xFFFFFFFF, Local0) // Low 32 bits (31:00)
+ ShiftRight(Local1, 32, Local1) // High 32 bits (63:32)
+ If (LEqual(And(Local0, 0xFF), 1))
+ {
+ // PCH
+ Store(\_SB.CGRD(Local1, Arg1), Local7)
+ }
+ Return(Local7)
+ } // End of Method(RDGP, 2, Serialized)
+
+} // End of Scope(\_SB)
+
+Scope(\_SB)
+{
+ // Asserts/De-asserts TBT force power
+ Method(TBFP, 2)
+ {
+ If(Arg0)
+ {
+ // Implementation dependent way to assert TBT force power
+ If(LEqual(Arg1, 1)) {
+ CGWR(FPG0, FP0L)
+ }
+ Else {
+ CGWR(FPG1, FP1L)
+ }
+ }
+ Else
+ {
+ // Implementation dependent way to de-assert TBT force power
+ If(LEqual(Arg1, 1)) {
+ CGWR(FPG0, LNot(FP0L))
+ }
+ Else {
+ CGWR(FPG1, LNot(FP1L))
+ }
+ }
+ }
+
+ // WMI ACPI device to control TBT force power
+ Device(WMTF)
+ {
+ // pnp0c14 is pnp id assigned to WMI mapper
+ Name(_HID, "PNP0C14")
+ Name(_UID, "TBFP")
+
+ Name(_WDG, Buffer() {
+ // {86CCFD48-205E-4A77-9C48-2021CBEDE341}
+ 0x48, 0xFD, 0xCC, 0x86,
+ 0x5E, 0x20,
+ 0x77, 0x4A,
+ 0x9C, 0x48,
+ 0x20, 0x21, 0xCB, 0xED, 0xE3, 0x41,
+ 84, 70, // Object Id (TF)
+ 1, // Instance Count
+ 0x02 // Flags (WMIACPI_REGFLAG_METHOD)
+ })
+
+ // Set TBT force power
+ // Arg2 is force power value
+ Method(WMTF, 3)
+ {
+ CreateByteField(Arg2,0,FP)
+
+ If(FP)
+ {
+ TBFP(1, 1)
+ }
+ Else
+ {
+ TBFP(0, 1)
+ }
+ }
+ }
+} // End of Scope(\_SB)
+
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 1),LEqual(RPS1, 1))))
+{
+ Scope(\_SB.PCI0.RP01)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP01)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 2),LEqual(RPS1, 2))))
+{
+ Scope(\_SB.PCI0.RP02)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP02)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 3),LEqual(RPS1, 3))))
+{
+ Scope(\_SB.PCI0.RP03)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP03)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 4),LEqual(RPS1, 4))))
+{
+ Scope(\_SB.PCI0.RP04)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP04)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 5),LEqual(RPS1, 5))))
+{
+ Scope(\_SB.PCI0.RP05)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP05)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 6),LEqual(RPS1, 6))))
+{
+ Scope(\_SB.PCI0.RP06)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP06)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 7),LEqual(RPS1, 7))))
+{
+ Scope(\_SB.PCI0.RP07)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP07)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 8),LEqual(RPS1, 8))))
+{
+ Scope(\_SB.PCI0.RP08)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP08)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 9),LEqual(RPS1, 9))))
+{
+ Scope(\_SB.PCI0.RP09)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP09)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 10),LEqual(RPS1, 10))))
+{
+ Scope(\_SB.PCI0.RP10)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP10)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 11),LEqual(RPS1, 11))))
+{
+ Scope(\_SB.PCI0.RP11)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP11)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 12),LEqual(RPS1, 12))))
+{
+ Scope(\_SB.PCI0.RP12)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP12)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 13),LEqual(RPS1, 13))))
+{
+ Scope(\_SB.PCI0.RP13)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP13)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 14),LEqual(RPS1, 14))))
+{
+ Scope(\_SB.PCI0.RP14)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP14)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 15),LEqual(RPS1, 15))))
+{
+ Scope(\_SB.PCI0.RP15)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP15)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 16),LEqual(RPS1, 16))))
+{
+ Scope(\_SB.PCI0.RP16)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP16)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 17),LEqual(RPS1, 17))))
+{
+ Scope(\_SB.PCI0.RP17)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP17)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 18),LEqual(RPS1, 18))))
+{
+ Scope(\_SB.PCI0.RP18)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP18)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 19),LEqual(RPS1, 19))))
+{
+ Scope(\_SB.PCI0.RP19)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP19)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 20),LEqual(RPS1, 20))))
+{
+ Scope(\_SB.PCI0.RP20)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.RP20)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 21),LEqual(RPS1, 21))))
+{
+ Scope(\_SB.PCI0.PEG0)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.PEG0)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 22),LEqual(RPS1, 22))))
+{
+ Scope(\_SB.PCI0.PEG1)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.PEG1)
+}
+
+If(LAnd(LEqual(TBTS, 1),LOr(LEqual(RPS0, 23),LEqual(RPS1, 23))))
+{
+ Scope(\_SB.PCI0.PEG2)
+ {
+ Device(HRUS)// Host router Upstream port
+ {
+ Name(_ADR, 0x00000000)
+
+ Method(_RMV)
+ {
+ Return(TARS)
+ } // end _RMV
+ }
+ }//End of Scope(\_SB.PCI0.PEG2)
+}
+
+Scope(\_SB)
+{
+ //
+ // Name: PERB
+ // Description: Function to read a Byte from PCIE-MMIO
+ // Input: Arg0 -> PCIE base address
+ // Arg1 -> Bus
+ // Arg2 -> Device
+ // Arg3 -> Function
+ // Arg4 -> Register offset
+ // Return: Byte data read from PCIE-MMIO
+ //
+ Method(PERB,5,Serialized)
+ {
+ ADBG("PERB")
+
+ Store(Arg0, Local7)
+ Or(Local7, ShiftLeft(Arg1, 20), Local7)
+ Or(Local7, ShiftLeft(Arg2, 15), Local7)
+ Or(Local7, ShiftLeft(Arg3, 12), Local7)
+ Or(Local7, Arg4, Local7)
+
+ OperationRegion(PCI0, SystemMemory, Local7, 1)
+ Field(PCI0, ByteAcc,NoLock,Preserve)
+ {
+ TEMP, 8
+ }
+
+ Return(TEMP)
+ } // End of Method(PERB,5,Serialized)
+
+ //
+ // Name: PEWB
+ // Description: Function to write a Byte into PCIE-MMIO
+ // Input: Arg0 -> PCIE base address
+ // Arg1 -> Bus
+ // Arg2 -> Device
+ // Arg3 -> Function
+ // Arg4 -> Register offset
+ // Arg5 -> Data
+ // Return: Nothing
+ //
+ Method(PEWB,6,Serialized)
+ {
+ ADBG("PEWB")
+
+ Store(Arg0, Local7)
+ Or(Local7, ShiftLeft(Arg1, 20), Local7)
+ Or(Local7, ShiftLeft(Arg2, 15), Local7)
+ Or(Local7, ShiftLeft(Arg3, 12), Local7)
+ Or(Local7, Arg4, Local7)
+
+ OperationRegion(PCI0, SystemMemory, Local7, 1)
+ Field(PCI0, ByteAcc,NoLock,Preserve)
+ {
+ TEMP, 8
+ }
+
+ Store(Arg5,TEMP)
+ } // End of Method(PEWB,6,Serialized)
+
+ //
+ // Name: PERW
+ // Description: Function to read a Word from PCIE-MMIO
+ // Input: Arg0 -> PCIE base address
+ // Arg1 -> Bus
+ // Arg2 -> Device
+ // Arg3 -> Function
+ // Arg4 -> Register offset
+ // Return: Word data read from PCIE-MMIO
+ //
+ Method(PERW,5,Serialized)
+ {
+ ADBG("PERW")
+
+ Store(Arg0, Local7)
+ Or(Local7, ShiftLeft(Arg1, 20), Local7)
+ Or(Local7, ShiftLeft(Arg2, 15), Local7)
+ Or(Local7, ShiftLeft(Arg3, 12), Local7)
+ Or(Local7, Arg4, Local7)
+
+ OperationRegion(PCI0, SystemMemory, Local7, 2)
+ Field(PCI0, ByteAcc,NoLock,Preserve)
+ {
+ TEMP, 16
+ }
+
+ Return(TEMP)
+ } // End of Method(PERW,5,Serialized)
+
+ //
+ // Name: PEWW
+ // Description: Function to write a Word into PCIE-MMIO
+ // Input: Arg0 -> PCIE base address
+ // Arg1 -> Bus
+ // Arg2 -> Device
+ // Arg3 -> Function
+ // Arg4 -> Register offset
+ // Arg5 -> Data
+ // Return: Nothing
+ //
+ Method(PEWW,6,Serialized)
+ {
+ ADBG("PEWW")
+
+ Store(Arg0, Local7)
+ Or(Local7, ShiftLeft(Arg1, 20), Local7)
+ Or(Local7, ShiftLeft(Arg2, 15), Local7)
+ Or(Local7, ShiftLeft(Arg3, 12), Local7)
+ Or(Local7, Arg4, Local7)
+
+ OperationRegion(PCI0, SystemMemory, Local7, 2)
+ Field(PCI0, ByteAcc,NoLock,Preserve)
+ {
+ TEMP, 16
+ }
+
+ Store(Arg5,TEMP)
+ } // End of Method(PEWW,6,Serialized)
+
+ //
+ // Name: PERD
+ // Description: Function to read a Dword from PCIE-MMIO
+ // Input: Arg0 -> PCIE base address
+ // Arg1 -> Bus
+ // Arg2 -> Device
+ // Arg3 -> Function
+ // Arg4 -> Register offset
+ // Return: Dword data read from PCIE-MMIO
+ //
+ Method(PERD,5,Serialized)
+ {
+ ADBG("PERD")
+
+ Store(Arg0, Local7)
+ Or(Local7, ShiftLeft(Arg1, 20), Local7)
+ Or(Local7, ShiftLeft(Arg2, 15), Local7)
+ Or(Local7, ShiftLeft(Arg3, 12), Local7)
+ Or(Local7, Arg4, Local7)
+
+ OperationRegion(PCI0, SystemMemory, Local7, 4)
+ Field(PCI0, ByteAcc,NoLock,Preserve)
+ {
+ TEMP, 32
+ }
+
+ Return(TEMP)
+ } // End of Method(PERD,5,Serialized)
+
+ //
+ // Name: PEWD
+ // Description: Function to write a Dword into PCIE-MMIO
+ // Input: Arg0 -> PCIE base address
+ // Arg1 -> Bus
+ // Arg2 -> Device
+ // Arg3 -> Function
+ // Arg4 -> Register offset
+ // Arg5 -> Data
+ // Return: Nothing
+ //
+ Method(PEWD,6,Serialized)
+ {
+ ADBG("PEWD")
+
+ Store(Arg0, Local7)
+ Or(Local7, ShiftLeft(Arg1, 20), Local7)
+ Or(Local7, ShiftLeft(Arg2, 15), Local7)
+ Or(Local7, ShiftLeft(Arg3, 12), Local7)
+ Or(Local7, Arg4, Local7)
+
+ OperationRegion(PCI0, SystemMemory, Local7, 4)
+ Field(PCI0, ByteAcc,NoLock,Preserve)
+ {
+ TEMP, 32
+ }
+
+ Store(Arg5,TEMP)
+ } // End of Method(PEWD,6,Serialized)
+
+ //
+ // Name: STDC
+ // Description: Function to get Standard Capability Register Offset
+ // Input: Arg0 -> PCIE base address
+ // Arg1 -> Bus
+ // Arg2 -> Device
+ // Arg3 -> Function
+ // Arg4 -> Capability ID
+ // Return: Capability Register Offset data
+ //
+ Method(STDC,5,Serialized)
+ {
+ ADBG("STDC")
+
+ //Check for Referenced device is present or not
+ Store(PERW(Arg0, Arg1, Arg2, Arg3, 0x00), Local7) //Vendor ID register
+ If(LEqual(Local7, 0xFFFF))
+ {
+ ADBG("Referenced device is not present")
+ Return(0)
+ }
+
+ Store(PERW(Arg0, Arg1, Arg2, Arg3, 0x06), Local0) //Device Status register
+ If (LEqual(And(Local0, 16), 0)) //Bit4 - Capabilities List
+ {
+ //No Capabilities linked list is available
+ ADBG("No Capabilities linked list is available")
+ Return(0)
+ }
+
+ //Local1 is for storing CapabilityID
+ //Local2 is for storing CapabilityPtr
+ Store(PERB(Arg0, Arg1, Arg2, Arg3, 0x34), Local2) //CapabilityPtr
+
+ While(1)
+ {
+ And(Local2, 0xFC, Local2) //Each capability must be DWORD aligned
+
+ If(LEqual(Local2, 0)) //A pointer value of 00h is used to indicate the last capability in the list
+ {
+ ADBG("Capability ID is not found")
+ Return(0)
+ }
+
+ Store(PERB(Arg0, Arg1, Arg2, Arg3, Local2), Local1) //CapabilityID
+
+ If(LEqual(Arg4, Local1)) //CapabilityID match
+ {
+ ADBG("Capability ID is found")
+ ADBG("Capability Offset : ")
+ ADBG(Local2)
+ Return(Local2)
+ }
+ Store(PERB(Arg0, Arg1, Arg2, Arg3, Add(Local2, 1)), Local2) //CapabilityPtr
+ Return(0)
+ }
+ } // End of Method(STDC,5,Serialized)
+
+} // End Scope(\_SB)
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Acpi/TbtNvs.asl b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Acpi/TbtNvs.asl
new file mode 100644
index 0000000000..65961e0940
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Acpi/TbtNvs.asl
@@ -0,0 +1,66 @@
+/**@file
+
+Copyright (c) 2018, Intel Corporation. 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 TBT NVS Area operation region.
+ //
+
+
+
+ OperationRegion(BNVS,SystemMemory,TNVB,TNVL)
+ Field(BNVS,AnyAcc,Lock,Preserve)
+ { Offset(0), TBSF, 8, // Offset(0), Thunderbolt(TM) SMI Function Number
+ Offset(1), SOHP, 8, // Offset(1), SMI on Hot Plug for TBT devices
+ Offset(2), TWIN, 8, // Offset(2), TbtWin10Support
+ Offset(3), GP5F, 8, // Offset(3), Gpio filter to detect USB Hotplug event
+ Offset(4), NOHP, 8, // Offset(4), Notify on Hot Plug for TBT devices
+ Offset(5), TBSE, 8, // Offset(5), Thunderbolt(TM) Root port selector
+ Offset(6), WKFN, 8, // Offset(6), WAK Finished
+ Offset(7), TBTS, 8, // Offset(7), Thunderbolt(TM) support
+ Offset(8), TARS, 8, // Offset(8), TbtAcpiRemovalSupport
+ Offset(9), FPEN, 32, // Offset(9), TbtFrcPwrEn
+ Offset(13), FPG0, 32, // Offset(13), TbtFrcPwrGpioNo
+ Offset(17), FP0L, 8, // Offset(17), TbtFrcPwrGpioLevel
+ Offset(18), CPG0, 32, // Offset(18), TbtCioPlugEventGpioNo
+ Offset(22), RSG0, 32, // Offset(22), TbtPcieRstGpioNo
+ Offset(26), RS0L, 8, // Offset(26), TbtPcieRstGpioLevel
+ Offset(27), DTCP, 8, // Offset(27), Current Port that has plug event
+ Offset(28), RPS0, 8, // Offset(28), Root port Selected by the User
+ Offset(29), RPT0, 8, // Offset(29), Root port Type
+ Offset(30), RPS1, 8, // Offset(30), Root port Selected by the User
+ Offset(31), RPT1, 8, // Offset(31), Root port Type
+ Offset(32), RPN0, 8, // Offset(32), Root port Enabled by the User
+ Offset(33), RPN1, 8, // Offset(33), Root port Enabled by the User
+ Offset(34), FPG1, 32, // Offset(34), TbtFrcPwrGpioNo
+ Offset(38), FP1L, 8, // Offset(38), TbtFrcPwrGpioLevel
+ Offset(39), CPG1, 32, // Offset(39), TbtCioPlugEventGpioNo
+ Offset(43), RSG1, 32, // Offset(43), TbtPcieRstGpioNo
+ Offset(47), RS1L, 8, // Offset(47), TbtPcieRstGpioLevel
+ Offset(48), CGST, 8, // Offset(48), Set if Single GPIO is used for Multi/Different Controller Hot plug support
+ Offset(49), DTPT, 8, // Offset(49), Root Port type for which SCI Triggered
+ Offset(50), TRWA, 8, // Offset(50), Titan Ridge Osup command
+ Offset(51), ACDC, 8, // Offset(51), TBT Dynamic AcDc L1
+ Offset(52), DT0E, 8, // Offset(52), DTbtController0 is enabled or not.
+ Offset(53), DT1E, 8, // Offset(53), DTbtController1 is enabled or not.
+ Offset(54), TASP, 8, // Offset(54), ASPM setting for all the PCIe device in TBT daisy chain.
+ Offset(55), TL1S, 8, // Offset(55), L1 SubState for for all the PCIe device in TBT daisy chain.
+ Offset(56), TCLK, 8, // Offset(56), CLK REQ for all the PCIe device in TBT daisy chain.
+ Offset(57), TLTR, 8, // Offset(57), LTR for for all the PCIe device in TBT daisy chain.
+ Offset(58), TPTM, 8, // Offset(58), PTM for for all the PCIe device in TBT daisy chain.
+ Offset(59), TWAK, 8, // Offset(59), Send Go2SxNoWake or GoSxWake according to TbtWakeupSupport
+ Offset(60), TBOD, 16, // Offset(60), Rtd3TbtOffDelay TBT RTD3 Off Delay
+ Offset(62), TSXW, 8, // Offset(62), TbtSxWakeSwitchLogicEnable Set True if TBT_WAKE_N will be routed to PCH WakeB at Sx entry point. HW logic is required.
+ Offset(63), RTBT, 8, // Offset(63), Enable Rtd3 support for TBT. Corresponding to Rtd3Tbt in Setup.
+ Offset(64), RTBC, 8, // Offset(64), Enable TBT RTD3 CLKREQ mask.
+ Offset(65), TBCD, 16, // Offset(65), TBT RTD3 CLKREQ mask delay.
+ } \ No newline at end of file
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Acpi/TbtNvsAreaDef.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Acpi/TbtNvsAreaDef.h
new file mode 100644
index 0000000000..583fda5914
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Acpi/TbtNvsAreaDef.h
@@ -0,0 +1,70 @@
+/**@file
+
+Copyright (c) 2018, Intel Corporation. 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 TBT NVS Area operation region.
+ //
+
+#ifndef _TBT_NVS_AREA_DEF_H_
+#define _TBT_NVS_AREA_DEF_H_
+
+#pragma pack (push,1)
+typedef struct {
+ UINT8 ThunderboltSmiFunction; ///< Offset 0 Thunderbolt(TM) SMI Function Number
+ UINT8 ThunderboltHotSmi; ///< Offset 1 SMI on Hot Plug for TBT devices
+ UINT8 TbtWin10Support; ///< Offset 2 TbtWin10Support
+ UINT8 TbtGpioFilter; ///< Offset 3 Gpio filter to detect USB Hotplug event
+ UINT8 ThunderboltHotNotify; ///< Offset 4 Notify on Hot Plug for TBT devices
+ UINT8 TbtSelector; ///< Offset 5 Thunderbolt(TM) Root port selector
+ UINT8 WAKFinished; ///< Offset 6 WAK Finished
+ UINT8 DiscreteTbtSupport; ///< Offset 7 Thunderbolt(TM) support
+ UINT8 TbtAcpiRemovalSupport; ///< Offset 8 TbtAcpiRemovalSupport
+ UINT32 TbtFrcPwrEn; ///< Offset 9 TbtFrcPwrEn
+ UINT32 TbtFrcPwrGpioNo0; ///< Offset 13 TbtFrcPwrGpioNo
+ UINT8 TbtFrcPwrGpioLevel0; ///< Offset 17 TbtFrcPwrGpioLevel
+ UINT32 TbtCioPlugEventGpioNo0; ///< Offset 18 TbtCioPlugEventGpioNo
+ UINT32 TbtPcieRstGpioNo0; ///< Offset 22 TbtPcieRstGpioNo
+ UINT8 TbtPcieRstGpioLevel0; ///< Offset 26 TbtPcieRstGpioLevel
+ UINT8 CurrentDiscreteTbtRootPort; ///< Offset 27 Current Port that has plug event
+ UINT8 RootportSelected0; ///< Offset 28 Root port Selected by the User
+ UINT8 RootportSelected0Type; ///< Offset 29 Root port Type
+ UINT8 RootportSelected1; ///< Offset 30 Root port Selected by the User
+ UINT8 RootportSelected1Type; ///< Offset 31 Root port Type
+ UINT8 RootportEnabled0; ///< Offset 32 Root port Enabled by the User
+ UINT8 RootportEnabled1; ///< Offset 33 Root port Enabled by the User
+ UINT32 TbtFrcPwrGpioNo1; ///< Offset 34 TbtFrcPwrGpioNo
+ UINT8 TbtFrcPwrGpioLevel1; ///< Offset 38 TbtFrcPwrGpioLevel
+ UINT32 TbtCioPlugEventGpioNo1; ///< Offset 39 TbtCioPlugEventGpioNo
+ UINT32 TbtPcieRstGpioNo1; ///< Offset 43 TbtPcieRstGpioNo
+ UINT8 TbtPcieRstGpioLevel1; ///< Offset 47 TbtPcieRstGpioLevel
+ UINT8 TBtCommonGpioSupport; ///< Offset 48 Set if Single GPIO is used for Multi/Different Controller Hot plug support
+ UINT8 CurrentDiscreteTbtRootPortType; ///< Offset 49 Root Port type for which SCI Triggered
+ UINT8 TrOsup; ///< Offset 50 Titan Ridge Osup command
+ UINT8 TbtAcDcSwitch; ///< Offset 51 TBT Dynamic AcDc L1
+ UINT8 DTbtControllerEn0; ///< Offset 52 DTbtController0 is enabled or not.
+ UINT8 DTbtControllerEn1; ///< Offset 53 DTbtController1 is enabled or not.
+ UINT8 TbtAspm; ///< Offset 54 ASPM setting for all the PCIe device in TBT daisy chain.
+ UINT8 TbtL1SubStates; ///< Offset 55 L1 SubState for for all the PCIe device in TBT daisy chain.
+ UINT8 TbtSetClkReq; ///< Offset 56 CLK REQ for all the PCIe device in TBT daisy chain.
+ UINT8 TbtLtr; ///< Offset 57 LTR for for all the PCIe device in TBT daisy chain.
+ UINT8 TbtPtm; ///< Offset 58 PTM for for all the PCIe device in TBT daisy chain.
+ UINT8 TbtWakeupSupport; ///< Offset 59 Send Go2SxNoWake or GoSxWake according to TbtWakeupSupport
+ UINT16 Rtd3TbtOffDelay; ///< Offset 60 Rtd3TbtOffDelay TBT RTD3 Off Delay
+ UINT8 TbtSxWakeSwitchLogicEnable; ///< Offset 62 TbtSxWakeSwitchLogicEnable Set True if TBT_WAKE_N will be routed to PCH WakeB at Sx entry point. HW logic is required.
+ UINT8 Rtd3TbtSupport; ///< Offset 63 Enable Rtd3 support for TBT. Corresponding to Rtd3Tbt in Setup.
+ UINT8 Rtd3TbtClkReq; ///< Offset 64 Enable TBT RTD3 CLKREQ mask.
+ UINT16 Rtd3TbtClkReqDelay; ///< Offset 65 TBT RTD3 CLKREQ mask delay.
+} TBT_NVS_AREA;
+
+#pragma pack(pop)
+#endif
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/DxeTbtPolicyLib.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/DxeTbtPolicyLib.h
new file mode 100644
index 0000000000..9fe16b8a68
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/DxeTbtPolicyLib.h
@@ -0,0 +1,53 @@
+/** @file
+ Prototype of the DxeTbtPolicyLib library.
+
+Copyright (c) 2018, Intel Corporation. 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_TBT_POLICY_LIB_H_
+#define _DXE_TBT_POLICY_LIB_H_
+
+
+/**
+ Install TBT Policy.
+
+ @param[in] ImageHandle Image handle of this driver.
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+InstallTbtPolicy (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ Update Tbt Policy Callback.
+
+ @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
+UpdateTbtPolicyCallback (
+ VOID
+ );
+
+/**
+ Print DXE TBT Policy
+**/
+VOID
+TbtPrintDxePolicyConfig (
+ VOID
+ );
+#endif // _DXE_TBT_POLICY_LIB_H_
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/PeiTbtPolicyLib.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/PeiTbtPolicyLib.h
new file mode 100644
index 0000000000..f1ca61ca4e
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/PeiTbtPolicyLib.h
@@ -0,0 +1,47 @@
+/** @file
+ Prototype of the PeiTbtPolicyLib library.
+
+Copyright (c) 2018, Intel Corporation. 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_TBT_POLICY_LIB_H_
+#define _PEI_TBT_POLICY_LIB_H_
+
+/**
+ Install Tbt Policy
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+InstallPeiTbtPolicy (
+ VOID
+ );
+
+/**
+ Update PEI TBT Policy
+**/
+VOID
+EFIAPI
+UpdatePeiTbtPolicy (
+ VOID
+ );
+
+/**
+ Print PEI TBT Policy
+**/
+VOID
+EFIAPI
+TbtPrintPeiPolicyConfig (
+ VOID
+ );
+#endif // _DXE_TBT_POLICY_LIB_H_
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/TbtCommonLib.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/TbtCommonLib.h
new file mode 100644
index 0000000000..f9338d3bd5
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/TbtCommonLib.h
@@ -0,0 +1,247 @@
+/**@file
+
+Copyright (c) 2018, Intel Corporation. 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 _TBT_COMMON_LIB_H_
+#define _TBT_COMMON_LIB_H_
+
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/GpioExpanderLib.h>
+
+#define DTBT_CONTROLLER 0x00
+#define DTBT_TYPE_PCH 0x01
+#define DTBT_TYPE_PEG 0x02
+#define TBT2PCIE_DTBT_R 0x548
+#define PCIE2TBT_DTBT_R 0x54C
+
+//
+// Thunderbolt FW OS capability
+//
+#define NO_OS_NATIVE_SUPPORT 0
+#define OS_NATIVE_SUPPORT_ONLY 1
+#define OS_NATIVE_SUPPORT_RTD3 2
+
+#define DTBT_SAVE_STATE_OFFSET BIT0 // Bits 0-3 is for DTBT (only bit 0 is in use)
+/**
+Get Tbt2Pcie Register Offset
+
+@retval Register Register Variable
+**/
+
+#define GET_TBT2PCIE_REGISTER_ADDRESS(Segment, Bus, Device, Function, RegisterAddress) \
+RegisterAddress = PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, TBT2PCIE_DTBT_R); \
+
+/**
+Get Pcie2Tbt Register Offset
+
+@retval Register Register Variable
+**/
+
+#define GET_PCIE2TBT_REGISTER_ADDRESS(Segment, Bus, Device, Function, RegisterAddress) \
+RegisterAddress = PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, PCIE2TBT_DTBT_R); \
+
+#define PCIE2TBT_VLD_B BIT0
+#define TBT2PCIE_DON_R BIT0
+#define TBT_MAIL_BOX_DELAY (100*1000)
+#define TBT_5S_TIMEOUT 50
+#define TBT_1S_TIMEOUT 10
+#define TBT_3S_TIMEOUT 30
+
+#define PCIE2TBT_GO2SX (0x02 << 1)
+#define PCIE2TBT_GO2SX_NO_WAKE (0x03 << 1)
+#define PCIE2TBT_SX_EXIT_TBT_CONNECTED (0x04 << 1)
+#define PCIE2TBT_SX_EXIT_NO_TBT_CONNECTED (0x05 << 1)
+#define PCIE2TBT_OS_UP (0x06 << 1)
+#define PCIE2TBT_SET_SECURITY_LEVEL (0x08 << 1)
+#define PCIE2TBT_GET_SECURITY_LEVEL (0x09 << 1)
+#define PCIE2TBT_CM_AUTH_MODE_ENTER (0x10 << 1)
+#define PCIE2TBT_CM_AUTH_MODE_EXIT (0x11 << 1)
+#define PCIE2TBT_BOOT_ON (0x18 << 1)
+#define PCIE2TBT_BOOT_OFF (0x19 << 1)
+#define PCIE2TBT_USB_ON (0x19 << 1)
+#define PCIE2TBT_GET_ENUMERATION_METHOD (0x1A << 1)
+#define PCIE2TBT_SET_ENUMERATION_METHOD (0x1B << 1)
+#define PCIE2TBT_POWER_CYCLE (0x1C << 1)
+#define PCIE2TBT_PREBOOTACL (0x1E << 1)
+#define CONNECT_TOPOLOGY_COMMAND (0x1F << 1)
+
+#define RESET_HR_BIT BIT0
+#define ENUMERATE_HR_BIT BIT1
+#define AUTO 0x0
+
+//
+//Thunder Bolt Device IDs
+//
+
+//
+// Alpine Ridge HR device IDs
+//
+#define AR_HR_2C 0x1576
+#define AR_HR_4C 0x1578
+#define AR_XHC 0x15B5
+#define AR_XHC_4C 0x15B6
+#define AR_HR_LP 0x15C0
+//
+// Alpine Ridge C0 HR device IDs
+//
+#define AR_HR_C0_2C 0x15DA
+#define AR_HR_C0_4C 0x15D3
+//
+// Titan Ridge HR device IDs
+//
+#define TR_HR_2C 0x15E7
+#define TR_HR_4C 0x15EA
+//
+//End of Thunderbolt(TM) Device IDs
+//
+
+typedef struct _DEV_ID {
+ UINT8 Segment;
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Fun;
+} DEV_ID;
+
+//@todo Seems to only be used by Platform/TBT/Smm/TbtSmm.inf
+//@todo should refactor this to only be present in that driver
+//@todo also definitions like this should never be in a .h file anyway
+//@todo this is a quick hack to get things compiling for now
+#ifdef __GNUC__
+#pragma GCC diagnostic warning "-Wunused-variable"
+#endif
+
+/**
+Based on the Security Mode Selection, BIOS drives FORCE_PWR.
+
+@param[in] GpioNumber
+@param[in] Value
+**/
+VOID
+ForceDtbtPower(
+ IN UINT8 GpioAccessType,
+ IN UINT8 Expander,
+ IN UINT32 GpioNumber,
+ IN BOOLEAN Value
+);
+
+/**
+ Get Security Level.
+ @param[in] Bus Bus number for Host Router (DTBT)
+ @param[in] Device Device number for Host Router (DTBT)
+ @param[in] Function Function number for Host Router (DTBT)
+ @param[in] Timeout Time out with 100 ms garnularity
+**/
+UINT8
+GetSecLevel (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 Command,
+ IN UINT32 Timeout
+ );
+
+/**
+ Set Security Level.
+ @param[in] Data Security State
+ @param[in] Bus Bus number for Host Router (DTBT)
+ @param[in] Device Device number for Host Router (DTBT)
+ @param[in] Function Function number for Host Router (DTBT)
+ @param[in] Timeout Time out with 100 ms garnularity
+**/
+BOOLEAN
+SetSecLevel (
+ IN UINT8 Data,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 Command,
+ IN UINT32 Timeout
+ );
+
+/**
+Execute TBT Mail Box Command
+
+@param[in] Command TBT Command
+@param[in] Bus Bus number for Host Router (DTBT)
+@param[in] Device Device number for Host Router (DTBT)
+@param[in] Function Function number for Host Router (DTBT)
+@param[in] Timeout Time out with 100 ms garnularity
+@Retval true if command executes succesfully
+**/
+BOOLEAN
+TbtSetPcie2TbtCommand(
+ IN UINT8 Command,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT32 Timeout
+);
+/**
+ Check connected TBT controller is supported or not by DeviceID
+
+ @param[in] DeviceID DeviceID of of TBT controller
+
+
+ @retval TRUE Valid DeviceID
+ @retval FALSE Invalid DeviceID
+**/
+
+BOOLEAN
+IsTbtHostRouter (
+ IN UINT16 DeviceID
+ );
+
+/**
+ Get Pch/Peg Pcie Root Port Device and Function Number for TBT 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
+**/
+EFI_STATUS
+EFIAPI
+GetDTbtRpDevFun(
+ IN BOOLEAN Type,
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFunc
+ );
+
+/**
+ Internal function to Wait for Tbt2PcieDone Bit.to Set or clear
+ @param[in] CommandOffsetAddress Tbt2Pcie Register Address
+ @param[in] TimeOut Time out with 100 ms garnularity
+ @param[in] Tbt2PcieDone Wait condition (wait for Bit to Clear/Set)
+ @param[out] *Tbt2PcieValue Function Register value
+**/
+BOOLEAN
+InternalWaitforCommandCompletion (
+ IN UINT64 CommandOffsetAddress,
+ IN UINT32 TimeOut,
+ IN BOOLEAN Tbt2PcieDone,
+ OUT UINT32 *Tbt2PcieValue
+ );
+
+VOID
+GetRootporttoSetResourcesforTbt (
+ IN UINTN RpIndex,
+ OUT UINT8 *RsvdExtraBusNum,
+ OUT UINT16 *RsvdPcieMegaMem,
+ OUT UINT8 *PcieMemAddrRngMax,
+ OUT UINT16 *RsvdPciePMegaMem,
+ OUT UINT8 *PciePMemAddrRngMax,
+ OUT BOOLEAN *SetResourceforTbt
+ );
+
+#endif \ No newline at end of file
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Ppi/PeiTbtPolicy.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Ppi/PeiTbtPolicy.h
new file mode 100644
index 0000000000..9b7ff25c55
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Ppi/PeiTbtPolicy.h
@@ -0,0 +1,36 @@
+/** @file
+TBT PEI Policy
+
+Copyright (c) 2018, Intel Corporation. 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_TBT_POLICY_H_
+#define _PEI_TBT_POLICY_H_
+
+#include <TbtPolicyCommonDefinition.h>
+
+#pragma pack(push, 1)
+
+#define PEI_TBT_POLICY_REVISION 1
+
+/**
+ TBT PEI configuration\n
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct _PEI_TBT_POLICY {
+ DTBT_COMMON_CONFIG DTbtCommonConfig; ///< dTbt Common Configuration
+ DTBT_CONTROLLER_CONFIG DTbtControllerConfig; ///< dTbt Controller Configuration
+} PEI_TBT_POLICY;
+
+#pragma pack(pop)
+
+#endif
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Private/Library/PeiDTbtInitLib.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Private/Library/PeiDTbtInitLib.h
new file mode 100644
index 0000000000..963a678845
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Private/Library/PeiDTbtInitLib.h
@@ -0,0 +1,114 @@
+/**@file
+ PEI DTBT Init Dispatch library Header file
+
+Copyright (c) 2018, Intel Corporation. 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_DTBT_INIT_LIB_H__
+#define __PEI_DTBT_INIT_LIB_H__
+
+#include <Ppi/PeiTbtPolicy.h>
+
+/**
+ set tPCH25 Timing to 10 ms for DTBT.
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtSetTPch25Timing (
+ IN PEI_TBT_POLICY *PeiTbtConfig
+);
+
+/**
+ Do ForcePower for DTBT Controller
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtForcePower (
+ IN PEI_TBT_POLICY *PeiTbtConfig
+);
+
+/**
+ Clear VGA Registers for DTBT.
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtClearVgaRegisters (
+ IN PEI_TBT_POLICY *PeiTbtConfig
+);
+
+/**
+ Exectue Mail box command "Boot On".
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtBootOn (
+ IN PEI_TBT_POLICY *PeiTbtConfig
+);
+
+/**
+ Exectue Mail box command "USB On".
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtUsbOn (
+ IN PEI_TBT_POLICY *PeiTbtConfig
+);
+
+/**
+ Exectue Mail box command "Sx Exit".
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtSxExitFlow (
+ IN PEI_TBT_POLICY *PeiTbtConfig
+);
+/**
+ Initialize Thunderbolt(TM)
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval others
+**/
+EFI_STATUS
+EFIAPI
+TbtInit (
+ VOID
+);
+
+#endif \ No newline at end of file
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Private/Library/PeiTbtCommonInitLib.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Private/Library/PeiTbtCommonInitLib.h
new file mode 100644
index 0000000000..3af3f64377
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Private/Library/PeiTbtCommonInitLib.h
@@ -0,0 +1,47 @@
+/**@file
+ PEI TBT Common Init Dispatch library Header file
+
+Copyright (c) 2018, Intel Corporation. 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_TBT_COMMON_INIT_LIB_H__
+#define __PEI_TBT_COMMON_INIT_LIB_H__
+
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/GpioLib.h>
+#include <Library/TimerLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TbtCommonLib.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/PchPmcLib.h>
+
+VOID
+TbtSetSxMode(
+IN BOOLEAN Type,
+IN UINT8 Bus,
+IN UINT8 Device,
+IN UINT8 Function,
+IN UINT8 TbtBootOn
+);
+
+VOID
+TbtClearVgaRegisters(
+IN UINTN Segment,
+IN UINTN Bus,
+IN UINTN Device,
+IN UINTN Function
+);
+
+#endif \ No newline at end of file
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Protocol/DxeTbtPolicy.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Protocol/DxeTbtPolicy.h
new file mode 100644
index 0000000000..76f5071d9a
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Protocol/DxeTbtPolicy.h
@@ -0,0 +1,117 @@
+/** @file
+TBT DXE Policy
+
+Copyright (c) 2018, Intel Corporation. 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_TBT_POLICY_H_
+#define _DXE_TBT_POLICY_H_
+
+#include <TbtPolicyCommonDefinition.h>
+
+#pragma pack(push, 1)
+
+#define DXE_TBT_POLICY_REVISION 1
+
+//
+// TBT Common Data Structure
+//
+typedef struct _TBT_COMMON_CONFIG{
+ /**
+ TBT Security Level
+ <b>0: SL0 No Security</b>, 1: SL1 User Authorization, 2: SL2 Secure Connect, 3: SL3 Display Port and USB
+ **/
+ UINT32 SecurityMode : 3;
+ /**
+ BIOS W/A for Hot plug of 12V USB devices cause electrical noise on PCH GPIOs
+ <b>0: Disabled</b>, 1: Enabled
+ **/
+ UINT32 Gpio5Filter : 1;
+ /**
+ Send Go2SxNoWake or GoSxWake according to TbtWakeupSupport
+ <b>0: Disabled</b>, 1: Enabled
+ **/
+ UINT32 TbtWakeupSupport : 1;
+ /**
+ SMI TBT enumeration
+ <b>0: Disabled</b>, 1: Enabled
+ **/
+ UINT32 TbtHotSMI : 1;
+ /**
+ Notify PCIe RP after Hot-Plug/Hot-Unplug occurred.
+ <b>0: Disabled</b>, 1: Enabled
+ **/
+ UINT32 TbtHotNotify : 1;
+ /**
+ CLK REQ for all the PCIe device in TBT daisy chain.
+ <b>0: Disabled</b>, 1: Enabled
+ **/
+ UINT32 TbtSetClkReq : 1;
+ /**
+ ASPM setting for all the PCIe device in TBT daisy chain.
+ <b>0: Disabled</b>, 1: L0s, 2: L1, 3: L0sL1
+ **/
+ UINT32 TbtAspm : 2;
+ /**
+ LTR for for all the PCIe device in TBT daisy chain.
+ <b>0: Disabled</b>, 1: Enabled
+ **/
+ UINT32 TbtLtr : 1;
+ /**
+ TBT Dynamic AC/DC L1.
+ <b>0: Disabled</b>, 1: Enabled
+ **/
+ UINT32 TbtAcDcSwitch : 1;
+ /**
+ TBT RTD3 Support.
+ <b>0: Disabled</b>, 1: Enabled
+ **/
+ UINT32 Rtd3Tbt : 1;
+ /**
+ TBT ClkReq for RTD3 Flow.
+ <b>0: Disabled</b>, 1: Enabled
+ **/
+ UINT32 Rtd3TbtClkReq : 1;
+ /**
+ TBT Win10support for Tbt FW execution mode.
+ <b>0: Disabled</b>, 1: Native, 2: Native + RTD3
+ **/
+ UINT32 Win10Support : 2;
+ UINT32 Rsvd0 : 17; ///< Reserved bits
+ UINT16 Rtd3TbtClkReqDelay;
+ UINT16 Rtd3TbtOffDelay;
+} TBT_COMMON_CONFIG;
+
+//
+// dTBT Resource Data Structure
+//
+typedef struct _DTBT_RESOURCE_CONFIG{
+ UINT8 DTbtPcieExtraBusRsvd; ///< Preserve Bus resource for PCIe RP that connect to dTBT Host Router
+ UINT16 DTbtPcieMemRsvd; ///< Preserve MEM resource for PCIe RP that connect to dTBT Host Router
+ UINT8 DTbtPcieMemAddrRngMax; ///< Alignment of Preserve MEM resource for PCIe RP that connect to dTBT Host Router
+ UINT16 DTbtPciePMemRsvd; ///< Preserve PMEM resource for PCIe RP that connect to dTBT Host Router
+ UINT8 DTbtPciePMemAddrRngMax; ///< Alignment of Preserve PMEM resource for PCIe RP that connect to dTBT Host Router
+ UINT8 Reserved[1]; ///< Reserved for DWORD alignment
+} DTBT_RESOURCE_CONFIG;
+
+/**
+ TBT DXE configuration\n
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct _DXE_TBT_POLICY_PROTOCOL {
+ TBT_COMMON_CONFIG TbtCommonConfig; ///< Tbt Common Information
+ DTBT_RESOURCE_CONFIG DTbtResourceConfig; ///< dTbt Resource Configuration
+} DXE_TBT_POLICY_PROTOCOL;
+
+#pragma pack(pop)
+
+#endif
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Protocol/TbtNvsArea.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Protocol/TbtNvsArea.h
new file mode 100644
index 0000000000..c662f162ec
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Protocol/TbtNvsArea.h
@@ -0,0 +1,48 @@
+/** @file
+ This file defines the TBT NVS Area Protocol.
+
+Copyright (c) 2018, Intel Corporation. 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 _TBT_NVS_AREA_H_
+#define _TBT_NVS_AREA_H_
+
+//
+// Platform NVS Area definition
+//
+#include <Acpi\TbtNvsAreaDef.h>
+
+//
+// Includes
+//
+#define TBT_NVS_DEVICE_ENABLE 1
+#define TBT_NVS_DEVICE_DISABLE 0
+
+//
+// Forward reference for pure ANSI compatibility
+//
+typedef struct _TBT_NVS_AREA_PROTOCOL TBT_NVS_AREA_PROTOCOL;
+
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gTbtNvsAreaProtocolGuid;
+
+#define TBT_NVS_AREA_REVISION_1 1
+
+//
+// Platform NVS Area Protocol
+//
+typedef struct _TBT_NVS_AREA_PROTOCOL {
+ TBT_NVS_AREA *Area;
+} TBT_NVS_AREA_PROTOCOL;
+
+#endif // _TBT_NVS_AREA_H_
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/TbtBoardInfo.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/TbtBoardInfo.h
new file mode 100644
index 0000000000..9844935212
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/TbtBoardInfo.h
@@ -0,0 +1,28 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. 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 _TBT_INFO_GUID_H_
+#define _TBT_INFO_GUID_H_
+#include <TbtPolicyCommonDefinition.h>
+
+#pragma pack(1)
+//
+// TBT Info HOB
+//
+typedef struct _TBT_INFO_HOB {
+ EFI_HOB_GUID_TYPE EfiHobGuidType;
+ DTBT_COMMON_CONFIG DTbtCommonConfig; ///< dTbt Common Configuration
+ DTBT_CONTROLLER_CONFIG DTbtControllerConfig; ///< dTbt Controller Configuration
+} TBT_INFO_HOB;
+#pragma pack()
+
+#endif
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/TbtPolicyCommonDefinition.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/TbtPolicyCommonDefinition.h
new file mode 100644
index 0000000000..2033126a25
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/TbtPolicyCommonDefinition.h
@@ -0,0 +1,84 @@
+/** @file
+TBT Policy Common definition.
+
+Copyright (c) 2018, Intel Corporation. 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 _TBT_POLICY_COMMON_H_
+#define _TBT_POLICY_COMMON_H_
+
+#include <Library/GpioLib.h>
+#include <IndustryStandard/Pci22.h>
+
+#define TYPE_PCIE 0x01
+#define TYPE_PEG 0x02
+
+#pragma pack(push, 1)
+
+//
+// dTBT Force Power GPIO Data Structure
+//
+typedef struct _DTBT_FORCE_POWER_GPIO_CONFIG {
+ UINT8 GpioAccessType; ///< Where the GPIO comes from [a.k.a how to access the GPIO],Where the GPIO comes from. 0: Disabled; 1: PCH, 2: I/O Expander
+ UINT8 Expander; ///< Applicable to GpioAccessType = IoExpander {TCA6424A} type
+ GPIO_PAD GpioPad; ///< GPIO Pad Number
+ BOOLEAN GpioLevel; ///< 0 = Active Low; 1 = Active High
+ UINT8 Reserved[1]; ///< Reserved for DWORD alignment
+} DTBT_FORCE_POWER_GPIO_CONFIG;
+
+//
+// dTBT CIO Plug Event GPIO Data Structure
+//
+typedef struct _DTBT_CIO_PLUG_EVENT_GPIO_CONFIG {
+ GPIO_PAD GpioPad; ///< GPIO Pad Number
+ UINT32 AcpiGpeSignature; ///< AcpiPlatform driver will change the XTBT method to the _Lxx or _Exx that we assign in this item.
+ BOOLEAN AcpiGpeSignaturePorting; ///< 0 = No porting required(for 2-tier GPI GPE event architecture), 1 = Porting required(for 1-tier GPI GPE event architecture)
+ UINT8 Reserved[3]; ///< Reserved for DWORD alignment
+} DTBT_CIO_PLUG_EVENT_GPIO_CONFIG;
+
+//
+// dTBT PCIE Reset GPIO Data Structure
+//
+typedef struct _DTBT_PCIE_RESET_GPIO_CONFIG {
+ GPIO_PAD GpioPad; ///< GPIO Pad Number
+ BOOLEAN GpioLevel; ///< 0 = Active Low; 1 = Active High
+ UINT8 Reserved[3]; ///< Reserved for DWORD alignment
+} DTBT_PCIE_RESET_GPIO_CONFIG;
+
+//
+// dTBT Controller Data Structure
+//
+typedef struct _DTBT_CONTROLLER_CONFIG{
+ UINT8 DTbtControllerEn; ///< Enable/Disable DTbtController.
+ UINT8 Type; ///< 01-Pcie RP, 02- PEG,Reserved. <Specific according to Board Design>
+ UINT8 PcieRpNumber; ///< RP Number/ PEG Port (0,1,2) that connecet to dTBT controller. <Specific according to Board Design>
+ DTBT_FORCE_POWER_GPIO_CONFIG ForcePwrGpio; ///< The GPIO pin that can force dTBT Power On. <Specific according to Board Design>
+ DTBT_CIO_PLUG_EVENT_GPIO_CONFIG CioPlugEventGpio; ///< The GPIO pin that can generate Hot-Plug event. <Specific according to Board Design>
+ DTBT_PCIE_RESET_GPIO_CONFIG PcieRstGpio; ///< The GPIO pin that is use to perform Reset when platform enters to Sx, it is required for platforms where PCI_RST pin connected to Tbt is controlled with GPIO <Specific according to Board Design>
+ UINT8 Reserved[1]; ///< Reserved for DWORD alignment
+} DTBT_CONTROLLER_CONFIG;
+
+//
+// dTBT Controller Data Structure
+//
+typedef struct _DTBT_COMMON_CONFIG{
+ UINT8 TbtBootOn; ///< Send BootOn Mailbox command when TbtBootOn is enabled.
+ UINT8 TbtUsbOn; ///< Send UsbOn Mailbox command when TbtBootOn is enabled.
+ UINT8 Gpio3ForcePwr; ///< Force GPIO to power on or not
+ UINT16 Gpio3ForcePwrDly; ///< The delay time after do ForcePwr
+ BOOLEAN DTbtSharedGpioConfiguration; ///< Multiple DTBT controllers share the same GPIO pin <Specific according to Board Design>
+ BOOLEAN PcieRstSupport; ///< 0 = Not Support, 1 = Supported. it is required for platforms where PCI_RST pin connected to Tbt is controlled with GPIO
+ UINT8 Reserved[1]; ///< Reserved for DWORD alignment
+} DTBT_COMMON_CONFIG;
+
+#pragma pack(pop)
+
+#endif
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.c b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.c
new file mode 100644
index 0000000000..0e58bc8294
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.c
@@ -0,0 +1,167 @@
+/** @file
+ This file is DxeTbtPolicyLib library.
+
+Copyright (c) 2018, Intel Corporation. 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 <DxeTbtPolicyLibrary.h>
+#include <TbtBoardInfo.h>
+#include <Protocol/DxeTbtPolicy.h>
+#include <Guid/HobList.h>
+#include <Library/HobLib.h>
+
+
+/**
+Update Tbt Policy Callback
+Need to add PCDs for setup options
+**/
+
+VOID
+EFIAPI
+UpdateTbtPolicyCallback (
+ VOID
+ )
+{
+
+ EFI_STATUS Status;
+ DXE_TBT_POLICY_PROTOCOL *DxeTbtConfig;
+
+ DxeTbtConfig = NULL;
+ Status = EFI_NOT_FOUND;
+ DEBUG ((DEBUG_INFO, "UpdateTbtPolicyCallback\n"));
+
+ Status = gBS->LocateProtocol (
+ &gDxeTbtPolicyProtocolGuid,
+ NULL,
+ (VOID **) &DxeTbtConfig
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, " gDxeTbtPolicyProtocolGuid Not installed!!!\n"));
+ } else {
+ DxeTbtConfig->DTbtResourceConfig.DTbtPcieExtraBusRsvd = PcdGet8 (PcdDTbtPcieExtraBusRsvd);
+ DxeTbtConfig->DTbtResourceConfig.DTbtPcieMemRsvd = PcdGet16 (PcdDTbtPcieMemRsvd);
+ DxeTbtConfig->DTbtResourceConfig.DTbtPcieMemAddrRngMax = PcdGet8 (PcdDTbtPcieMemAddrRngMax);
+ DxeTbtConfig->DTbtResourceConfig.DTbtPciePMemRsvd = PcdGet16 (PcdDTbtPciePMemRsvd);
+ DxeTbtConfig->DTbtResourceConfig.DTbtPciePMemAddrRngMax = PcdGet8 (PcdDTbtPciePMemAddrRngMax);
+
+ DxeTbtConfig->TbtCommonConfig.TbtAspm = PcdGet8 (PcdDTbtAspm);
+ DxeTbtConfig->TbtCommonConfig.TbtHotNotify = PcdGet8 (PcdDTbtHotNotify);
+ DxeTbtConfig->TbtCommonConfig.TbtHotSMI = PcdGet8 (PcdDTbtHotSMI);
+ DxeTbtConfig->TbtCommonConfig.TbtSetClkReq = PcdGet8 (PcdDTbtSetClkReq);
+ DxeTbtConfig->TbtCommonConfig.TbtWakeupSupport = PcdGet8 (PcdDTbtWakeupSupport);
+ DxeTbtConfig->TbtCommonConfig.SecurityMode = PcdGet8 (PcdDTbtSecurityMode);
+
+ DxeTbtConfig->TbtCommonConfig.Gpio5Filter = PcdGet8 (PcdDTbtGpio5Filter);
+ DxeTbtConfig->TbtCommonConfig.TbtAcDcSwitch = PcdGet8 (PcdDTbtAcDcSwitch);
+
+ DxeTbtConfig->TbtCommonConfig.Rtd3Tbt = PcdGet8 (PcdRtd3Tbt);
+ DxeTbtConfig->TbtCommonConfig.Rtd3TbtOffDelay = PcdGet16 (PcdRtd3TbtOffDelay);
+ DxeTbtConfig->TbtCommonConfig.Rtd3TbtClkReq = PcdGet8 (PcdRtd3TbtClkReq);
+ DxeTbtConfig->TbtCommonConfig.Win10Support = PcdGet8 (PcdDTbtWin10Support);
+ }
+
+ return;
+}
+
+/**
+ Print DXE TBT Policy
+**/
+VOID
+TbtPrintDxePolicyConfig (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ DXE_TBT_POLICY_PROTOCOL *DxeTbtConfig;
+
+ DEBUG ((DEBUG_INFO, "TbtPrintDxePolicyConfig Start\n"));
+
+ DxeTbtConfig = NULL;
+ Status = EFI_NOT_FOUND;
+ Status = gBS->LocateProtocol (
+ &gDxeTbtPolicyProtocolGuid,
+ NULL,
+ (VOID **) &DxeTbtConfig
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, " gDxeTbtPolicyProtocolGuid Not installed!!!\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Print DTBT Policy
+ //
+ DEBUG ((DEBUG_ERROR, " ========================= DXE TBT POLICY ========================= \n"));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->DTbtResourceConfig.DTbtPcieExtraBusRsvd = %x\n", DxeTbtConfig->DTbtResourceConfig.DTbtPcieExtraBusRsvd));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->DTbtResourceConfig.DTbtPcieMemRsvd = %x\n", DxeTbtConfig->DTbtResourceConfig.DTbtPcieMemRsvd));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->DTbtResourceConfig.DTbtPcieMemAddrRngMax = %x\n", DxeTbtConfig->DTbtResourceConfig.DTbtPcieMemAddrRngMax));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->DTbtResourceConfig.DTbtPciePMemRsvd = %x\n", DxeTbtConfig->DTbtResourceConfig.DTbtPciePMemRsvd));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->DTbtResourceConfig.DTbtPciePMemAddrRngMax = %x\n", DxeTbtConfig->DTbtResourceConfig.DTbtPciePMemAddrRngMax));
+
+
+ //
+ // Print TBT Common Policy
+ //
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.TbtAspm = %x\n", DxeTbtConfig->TbtCommonConfig.TbtAspm));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.TbtHotNotify = %x\n", DxeTbtConfig->TbtCommonConfig.TbtHotNotify));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.TbtHotSMI = %x\n", DxeTbtConfig->TbtCommonConfig.TbtHotSMI));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.TbtLtr = %x\n", DxeTbtConfig->TbtCommonConfig.TbtLtr));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.TbtSetClkReq = %x\n", DxeTbtConfig->TbtCommonConfig.TbtSetClkReq));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.TbtWakeupSupport = %x\n", DxeTbtConfig->TbtCommonConfig.TbtWakeupSupport));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.SecurityMode = %x\n", DxeTbtConfig->TbtCommonConfig.SecurityMode));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.Gpio5Filter = %x\n", DxeTbtConfig->TbtCommonConfig.Gpio5Filter));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.TbtAcDcSwitch = %x\n", DxeTbtConfig->TbtCommonConfig.TbtAcDcSwitch));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.Rtd3Tbt = %x\n", DxeTbtConfig->TbtCommonConfig.Rtd3Tbt));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.Rtd3TbtOffDelay = %x\n", DxeTbtConfig->TbtCommonConfig.Rtd3TbtOffDelay));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.Rtd3TbtClkReq = %x\n", DxeTbtConfig->TbtCommonConfig.Rtd3TbtClkReq));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.Rtd3TbtClkReqDelay = %x\n", DxeTbtConfig->TbtCommonConfig.Rtd3TbtClkReqDelay));
+ DEBUG ((DEBUG_INFO, "DxeTbtConfig->TbtCommonConfig.Win10Support = %x\n", DxeTbtConfig->TbtCommonConfig.Win10Support));
+
+ return;
+}
+
+/**
+ Install Tbt Policy
+
+ @param[in] ImageHandle Image handle of this driver.
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+InstallTbtPolicy (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ DXE_TBT_POLICY_PROTOCOL *DxeTbtPolicy;
+
+ DEBUG ((DEBUG_INFO, "Install DXE TBT Policy\n"));
+
+ DxeTbtPolicy = NULL;
+ //Alloc memory for DxeTbtPolicy
+ DxeTbtPolicy = (DXE_TBT_POLICY_PROTOCOL *) AllocateZeroPool (sizeof (DXE_TBT_POLICY_PROTOCOL));
+ if (DxeTbtPolicy == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gDxeTbtPolicyProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ DxeTbtPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Install Tbt Secure Boot List protocol failed\n"));
+ }
+ return Status;
+}
+
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.inf b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.inf
new file mode 100644
index 0000000000..38f30d1f11
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.inf
@@ -0,0 +1,73 @@
+## @file
+# Component description file for Tbt functionality
+#
+# Copyright (c) 2018, Intel Corporation. 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 = DxeTbtPolicyLib
+FILE_GUID = 28ABF346-4E52-4BD3-b1FF-63BA7563C9D4
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxeTbtPolicyLib
+
+
+[LibraryClasses]
+BaseMemoryLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+DebugLib
+PostCodeLib
+HobLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ KabylakeOpenBoardPkg/OpenBoardPkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+gBoardModuleTokenSpaceGuid.PcdDTbtSecurityMode ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtGpio5Filter ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtWakeupSupport ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtHotSMI ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtHotNotify ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtSetClkReq ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtAspm ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtAcDcSwitch ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdRtd3Tbt ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdRtd3TbtClkReq ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtWin10Support ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdRtd3TbtClkReqDelay ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdRtd3TbtOffDelay ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPcieExtraBusRsvd ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPcieMemRsvd ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPcieMemAddrRngMax ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPciePMemRsvd ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPciePMemAddrRngMax ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPcieRpNumber ## CONSUMES
+
+
+[Sources]
+DxeTbtPolicyLib.c
+
+
+[Guids]
+gEfiEndOfDxeEventGroupGuid
+#gSetupVariableGuid
+gTbtInfoHobGuid
+
+[Protocols]
+gDxeTbtPolicyProtocolGuid
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLibrary.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLibrary.h
new file mode 100644
index 0000000000..e0f749ec53
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLibrary.h
@@ -0,0 +1,28 @@
+/** @file
+ Header file for the DxeTBTPolicy library.
+
+Copyright (c) 2018, Intel Corporation. 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_TBT_POLICY_LIBRARY_H_
+#define _DXE_TBT_POLICY_LIBRARY_H_
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <Guid/EventGroup.h>
+
+#endif // _DXE_TBT_POLICY_LIBRARY_H_
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.c b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.c
new file mode 100644
index 0000000000..4f2690ca56
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.c
@@ -0,0 +1,321 @@
+/** @file
+ PeiTbtInit library implementition with empty functions.
+
+Copyright (c) 2018, Intel Corporation. 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 <Uefi/UefiBaseType.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/TbtCommonLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/GpioLib.h>
+
+
+/**
+ Selects the proper TBT Root port to assign resources
+ based on the user input value
+
+ @param[in] SetupData Pointer to Setup data
+
+ @retval TbtSelectorChosen Rootport number.
+**/
+VOID
+GetRootporttoSetResourcesforTbt (
+ IN UINTN RpIndex,
+ OUT UINT8 *RsvdExtraBusNum,
+ OUT UINT16 *RsvdPcieMegaMem,
+ OUT UINT8 *PcieMemAddrRngMax,
+ OUT UINT16 *RsvdPciePMegaMem,
+ OUT UINT8 *PciePMemAddrRngMax,
+ OUT BOOLEAN *SetResourceforTbt
+ )
+{
+ UINTN TbtRpNumber;
+ TbtRpNumber = (UINTN) PcdGet8 (PcdDTbtPcieRpNumber);
+
+ if (RpIndex == (TbtRpNumber - 1)) {
+ *RsvdExtraBusNum = PcdGet8 (PcdDTbtPcieExtraBusRsvd);
+ *RsvdPcieMegaMem = PcdGet16 (PcdDTbtPcieMemRsvd);
+ *PcieMemAddrRngMax = PcdGet8 (PcdDTbtPcieMemAddrRngMax);
+ *RsvdPciePMegaMem = PcdGet16 (PcdDTbtPciePMemRsvd);
+ *PciePMemAddrRngMax = PcdGet8 (PcdDTbtPciePMemAddrRngMax);
+ *SetResourceforTbt = TRUE;
+ }
+ else {
+ *SetResourceforTbt = FALSE;
+ }
+ }
+
+/**
+ Internal function to Wait for Tbt2PcieDone Bit.to Set or clear
+ @param[in] CommandOffsetAddress Tbt2Pcie Register Address
+ @param[in] TimeOut Time out with 100 ms garnularity
+ @param[in] Tbt2PcieDone Wait condition (wait for Bit to Clear/Set)
+ @param[out] *Tbt2PcieValue Function Register value
+**/
+BOOLEAN
+InternalWaitforCommandCompletion(
+ IN UINT64 CommandOffsetAddress,
+ IN UINT32 TimeOut,
+ IN BOOLEAN Tbt2PcieDone,
+ OUT UINT32 *Tbt2PcieValue
+ )
+{
+ BOOLEAN ReturnFlag;
+ UINT32 Tbt2PcieCheck;
+
+ ReturnFlag = FALSE;
+ while (TimeOut-- > 0) {
+ *Tbt2PcieValue = PciSegmentRead32 (CommandOffsetAddress);
+
+ if (0xFFFFFFFF == *Tbt2PcieValue ) {
+ //
+ // Device is not here return now
+ //
+ ReturnFlag = FALSE;
+ break;
+ }
+
+ if(Tbt2PcieDone) {
+ Tbt2PcieCheck = *Tbt2PcieValue & TBT2PCIE_DON_R;
+ } else {
+ Tbt2PcieCheck = !(*Tbt2PcieValue & TBT2PCIE_DON_R);
+ }
+
+ if (Tbt2PcieCheck) {
+ ReturnFlag = TRUE;
+ break;
+ }
+
+ MicroSecondDelay(TBT_MAIL_BOX_DELAY);
+ }
+ return ReturnFlag;
+}
+/**
+ Get Security Level.
+ @param[in] Bus Bus number Host Router (DTBT)
+ @param[in] Device Device number for Host Router (DTBT)
+ @param[in] Function Function number for Host Router (DTBT)
+ @param[in] Command Command for Host Router (DTBT)
+ @param[in] Timeout Time out with 100 ms garnularity
+**/
+UINT8
+GetSecLevel (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 Command,
+ IN UINT32 Timeout
+ )
+{
+ UINT64 Pcie2Tbt;
+ UINT64 Tbt2Pcie;
+ UINT32 RegisterValue;
+ UINT8 ReturnFlag;
+
+ ReturnFlag = 0xFF;
+
+ DEBUG ((DEBUG_INFO, "GetSecLevel() \n"));
+
+ GET_TBT2PCIE_REGISTER_ADDRESS(0, Bus, Device, Function, Tbt2Pcie)
+ GET_PCIE2TBT_REGISTER_ADDRESS(0, Bus, Device, Function, Pcie2Tbt)
+
+ PciSegmentWrite32 (Pcie2Tbt, Command | PCIE2TBT_VLD_B);
+
+ if(InternalWaitforCommandCompletion(Tbt2Pcie, Timeout, TRUE, &RegisterValue)) {
+ ReturnFlag = (UINT8) (0xFF & (RegisterValue >> 8));
+ }
+
+ PciSegmentWrite32 (Pcie2Tbt, 0);
+
+ InternalWaitforCommandCompletion(Tbt2Pcie, Timeout, FALSE, &RegisterValue);
+ DEBUG ((DEBUG_INFO, "Security Level configured to %x \n", ReturnFlag));
+
+ return ReturnFlag;
+}
+
+/**
+ Set Security Level.
+ @param[in] Data Security State
+ @param[in] Bus Bus number for Host Router (DTBT)
+ @param[in] Device Device number for Host Router (DTBT)
+ @param[in] Function Function number for Host Router (DTBT)
+ @param[in] Command Command for Host Router (DTBT)
+ @param[in] Timeout Time out with 100 ms garnularity
+**/
+BOOLEAN
+SetSecLevel (
+ IN UINT8 Data,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 Command,
+ IN UINT32 Timeout
+ )
+{
+ UINT64 Pcie2Tbt;
+ UINT64 Tbt2Pcie;
+ UINT32 RegisterValue;
+ BOOLEAN ReturnFlag;
+
+ ReturnFlag = FALSE;
+
+ DEBUG ((DEBUG_INFO, "SetSecLevel() \n"));
+
+ GET_TBT2PCIE_REGISTER_ADDRESS(0, Bus, Device, Function, Tbt2Pcie)
+ GET_PCIE2TBT_REGISTER_ADDRESS(0, Bus, Device, Function, Pcie2Tbt)
+
+ PciSegmentWrite32 (Pcie2Tbt, (Data << 8) | Command | PCIE2TBT_VLD_B);
+
+ ReturnFlag = InternalWaitforCommandCompletion(Tbt2Pcie, Timeout, TRUE, &RegisterValue);
+ DEBUG ((DEBUG_INFO, "RegisterValue %x \n", RegisterValue));
+ PciSegmentWrite32 (Pcie2Tbt, 0);
+
+ InternalWaitforCommandCompletion(Tbt2Pcie, Timeout, FALSE, &RegisterValue);
+ DEBUG ((DEBUG_INFO, "Return value %x \n", ReturnFlag));
+ return ReturnFlag;
+}
+
+/**
+Based on the Security Mode Selection, BIOS drives FORCE_PWR.
+
+@param[in] GpioNumber
+@param[in] Value
+**/
+VOID
+ForceDtbtPower(
+ IN UINT8 GpioAccessType,
+ IN UINT8 Expander,
+ IN UINT32 GpioNumber,
+ IN BOOLEAN Value
+)
+{
+ if (GpioAccessType == 0x01) {
+ // PCH
+ GpioSetOutputValue (GpioNumber, (UINT32)Value);
+ } else if (GpioAccessType == 0x02) {
+ // IoExpander {TCA6424A}
+ GpioExpSetOutput (Expander, (UINT8)GpioNumber, (UINT8)Value);
+ }
+}
+
+/**
+Execute TBT Mail Box Command
+
+@param[in] Command TBT Command
+@param[in] Bus Bus number for Host Router (DTBT)
+@param[in] Device Device number for Host Router (DTBT)
+@param[in] Function Function number for Host Router (DTBT)
+@param[in] Timeout Time out with 100 ms garnularity
+@Retval true if command executes succesfully
+**/
+BOOLEAN
+TbtSetPcie2TbtCommand(
+ IN UINT8 Command,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT32 Timeout
+)
+{
+ UINT64 Pcie2Tbt;
+ UINT64 Tbt2Pcie;
+ UINT32 RegisterValue;
+ BOOLEAN ReturnFlag;
+
+ GET_TBT2PCIE_REGISTER_ADDRESS(0, Bus, Device, Function, Tbt2Pcie)
+ GET_PCIE2TBT_REGISTER_ADDRESS(0, Bus, Device, Function, Pcie2Tbt)
+
+ PciSegmentWrite32 (Pcie2Tbt, Command | PCIE2TBT_VLD_B);
+
+ ReturnFlag = InternalWaitforCommandCompletion(Tbt2Pcie, Timeout, TRUE, &RegisterValue);
+
+ PciSegmentWrite32(Pcie2Tbt, 0);
+
+ return ReturnFlag;
+}
+/**
+ Get Pch/Peg Pcie Root Port Device and Function Number for TBT 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 If Invalid Root Port Number or TYPE is Passed
+**/
+EFI_STATUS
+EFIAPI
+GetDTbtRpDevFun (
+ IN BOOLEAN Type,
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFunc
+ )
+{
+ EFI_STATUS Status;
+ UINTN TbtRpDev;
+ UINTN TbtRpFunc;
+
+ Status = EFI_INVALID_PARAMETER; // Update the Status to EFI_SUCCESS if valid input found.
+ //
+ // CNL PCH-H can support up to 24 root ports. PEG0,PEG1 and PEG2 will be
+ // with device number 0x1 and Function number 0,1 and 2 respectively.
+ //
+ if (Type == DTBT_TYPE_PEG)
+ {
+ //
+ // PEG Rootport
+ //
+ if (RpNumber <= 2) {
+ *RpDev = 0x01;
+ *RpFunc = RpNumber;
+ Status = EFI_SUCCESS;
+ }
+ }
+ if (Type == DTBT_TYPE_PCH)
+ {
+ //
+ // PCH Rootport
+ //
+ if (RpNumber <= 23) {
+ Status = GetPchPcieRpDevFun (RpNumber, &TbtRpDev, &TbtRpFunc);
+ *RpDev = TbtRpDev;
+ *RpFunc = TbtRpFunc;
+ }
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+BOOLEAN
+IsTbtHostRouter (
+ IN UINT16 DeviceID
+ )
+{
+ switch (DeviceID) {
+ case AR_HR_2C:
+ case AR_HR_4C:
+ case AR_HR_LP:
+ case AR_HR_C0_2C:
+ case AR_HR_C0_4C:
+ case TR_HR_2C:
+ case TR_HR_4C:
+ return TRUE;
+ }
+
+ return FALSE;
+} // IsTbtHostRouter
+
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.inf b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.inf
new file mode 100644
index 0000000000..ec8a31421e
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.inf
@@ -0,0 +1,69 @@
+### @file
+# Component information file for Tbt common library
+#
+# Copyright (c) 2018, Intel Corporation. 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 = TbtCommonLib
+ FILE_GUID = 5F03614E-CB56-40B1-9989-A09E25BBA294
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = TbtCommonLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[LibraryClasses]
+ DebugLib
+ PchPcieRpLib
+ PciSegmentLib
+ TimerLib
+ BaseLib
+ GpioLib
+ GpioExpanderLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ KabylakeOpenBoardPkg/OpenBoardPkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gBoardModuleTokenSpaceGuid.PcdDTbtSecurityMode ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtGpio5Filter ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtWakeupSupport ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtHotSMI ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtHotNotify ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtSetClkReq ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtAspm ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtAcDcSwitch ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdRtd3Tbt ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdRtd3TbtClkReq ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtWin10Support ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdRtd3TbtClkReqDelay ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdRtd3TbtOffDelay ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPcieExtraBusRsvd ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPcieMemRsvd ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPcieMemAddrRngMax ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPciePMemRsvd ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPciePMemAddrRngMax ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPcieRpNumber
+
+[Sources]
+ TbtCommonLib.c
+
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.c b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.c
new file mode 100644
index 0000000000..d0e3229db5
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.c
@@ -0,0 +1,210 @@
+/** @file
+ This file is PeiTbtPolicyLib library.
+
+Copyright (c) 2018, Intel Corporation. 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/PeiServicesLib.h>
+#include <Library/GpioLib.h>
+#include <PiPei.h>
+#include <PeiTbtPolicyLibrary.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/PeiTbtPolicy.h>
+#include <Base.h>
+#include <GpioConfig.h>
+
+/**
+ Update PEI TBT Policy Callback
+**/
+VOID
+EFIAPI
+UpdatePeiTbtPolicy (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;
+ PEI_TBT_POLICY *PeiTbtConfig;
+
+ PeiTbtConfig = NULL;
+ Status = EFI_NOT_FOUND;
+
+ DEBUG ((DEBUG_INFO, "UpdatePeiTbtPolicy \n"));
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **) &VariableServices
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesLocatePpi (
+ &gPeiTbtPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PeiTbtConfig
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, " gPeiTbtPolicyPpiGuid Not installed!!!\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Update DTBT Policy
+ //
+ PeiTbtConfig-> DTbtControllerConfig.DTbtControllerEn = PcdGet8 (PcdDTbtControllerEn);
+ if (PcdGet8 (PcdDTbtControllerType) == TYPE_PEG)
+ {
+ PeiTbtConfig-> DTbtControllerConfig.Type = (UINT8) TYPE_PEG;
+ PeiTbtConfig-> DTbtControllerConfig.PcieRpNumber = 1; // PEG RP 1 (Function no. 0)
+ }
+ else {
+ PeiTbtConfig-> DTbtControllerConfig.PcieRpNumber = PcdGet8 (PcdDTbtPcieRpNumber);
+ PeiTbtConfig-> DTbtControllerConfig.Type = PcdGet8 (PcdDTbtControllerType);
+ }
+ PeiTbtConfig->DTbtControllerConfig.CioPlugEventGpio.GpioPad = (GPIO_PAD) PcdGet32 (PcdDTbtCioPlugEventGpioPad);
+ if (GpioCheckFor2Tier(PeiTbtConfig->DTbtControllerConfig.CioPlugEventGpio.GpioPad)) {
+ PeiTbtConfig->DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignaturePorting = 0;
+ PeiTbtConfig->DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignature = SIGNATURE_32('X', 'T', 'B', 'T');
+ }
+ else {
+ PeiTbtConfig->DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignaturePorting = 1;
+ //
+ // Update Signature based on platform GPIO.
+ //
+ PeiTbtConfig->DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignature = SIGNATURE_32('X', 'T', 'B', 'T');
+ }
+ PeiTbtConfig->DTbtCommonConfig.TbtBootOn = PcdGet8 (PcdDTbtBootOn);
+ PeiTbtConfig->DTbtCommonConfig.TbtUsbOn = PcdGet8 (PcdDTbtUsbOn);
+ PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwr = PcdGet8 (PcdDTbtGpio3ForcePwr);
+ PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwrDly = PcdGet16 (PcdDTbtGpio3ForcePwrDly);
+
+ return;
+}
+
+/**
+ Print PEI TBT Policy
+**/
+VOID
+EFIAPI
+TbtPrintPeiPolicyConfig (
+ VOID
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ EFI_STATUS Status;
+ PEI_TBT_POLICY *PeiTbtConfig;
+
+ PeiTbtConfig = NULL;
+ Status = EFI_NOT_FOUND;
+ DEBUG ((DEBUG_INFO, "TbtPrintPolicyConfig Start\n"));
+
+ Status = PeiServicesLocatePpi (
+ &gPeiTbtPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PeiTbtConfig
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, " gPeiTbtPolicyPpiGuid Not installed!!!\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Print DTBT Policy
+ //
+ DEBUG ((DEBUG_INFO, "\n------------------------ TBT Policy (PEI) Print BEGIN -----------------\n"));
+ DEBUG ((DEBUG_INFO, "Revision : 0x%x\n", PEI_TBT_POLICY_REVISION));
+ DEBUG ((DEBUG_INFO, "------------------------ PEI_TBT_CONFIG -----------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision : %d\n", PEI_TBT_POLICY_REVISION));
+
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtControllerConfig.DTbtControllerEn = %x\n", PeiTbtConfig-> DTbtControllerConfig.DTbtControllerEn));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtControllerConfig.Type = %x\n", PeiTbtConfig-> DTbtControllerConfig.Type));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtControllerConfig.PcieRpNumber = %x\n", PeiTbtConfig-> DTbtControllerConfig.PcieRpNumber));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtControllerConfig.ForcePwrGpio.GpioPad = %x\n", PeiTbtConfig-> DTbtControllerConfig.ForcePwrGpio.GpioPad));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtControllerConfig.ForcePwrGpio.GpioLevel = %x\n", PeiTbtConfig-> DTbtControllerConfig.ForcePwrGpio.GpioLevel));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtControllerConfig.PcieRstGpio.GpioPad = %x\n", PeiTbtConfig-> DTbtControllerConfig.PcieRstGpio.GpioPad));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtControllerConfig.PcieRstGpio.GpioLevel = %x\n", PeiTbtConfig-> DTbtControllerConfig.PcieRstGpio.GpioLevel));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtControllerConfig.CioPlugEventGpio.GpioPad = %x\n", PeiTbtConfig-> DTbtControllerConfig.CioPlugEventGpio.GpioPad));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignature = %x\n", PeiTbtConfig-> DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignature));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignaturePorting = %x\n", PeiTbtConfig-> DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignaturePorting));
+
+
+ //
+ // Print DTBT Common Policy
+ //
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtCommonConfig.TbtBootOn = %x\n", PeiTbtConfig->DTbtCommonConfig.TbtBootOn));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtCommonConfig.TbtUsbOn = %x\n", PeiTbtConfig->DTbtCommonConfig.TbtUsbOn));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwr = %x\n", PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwr));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwrDly = %x\n", PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwrDly));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtCommonConfig.DTbtSharedGpioConfiguration = %x\n", PeiTbtConfig->DTbtCommonConfig.DTbtSharedGpioConfiguration));
+ DEBUG ((DEBUG_INFO, "PeiTbtConfig->DTbtCommonConfig.PcieRstSupport = %x\n", PeiTbtConfig->DTbtCommonConfig.PcieRstSupport));
+
+ DEBUG ((DEBUG_INFO, "\n------------------------ TBT Policy (PEI) Print END -----------------\n"));
+ DEBUG_CODE_END ();
+
+ return;
+}
+
+/**
+ Install Tbt Policy
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+InstallPeiTbtPolicy (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *PeiTbtPolicyPpiDesc;
+ PEI_TBT_POLICY *PeiTbtConfig;
+
+ DEBUG ((DEBUG_INFO, "Install PEI TBT Policy\n"));
+
+ PeiTbtConfig = NULL;
+
+ //
+ // Allocate memory for PeiTbtPolicyPpiDesc
+ //
+ PeiTbtPolicyPpiDesc = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ ASSERT (PeiTbtPolicyPpiDesc != NULL);
+ if (PeiTbtPolicyPpiDesc == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Allocate memory and initialize all default to zero for PeiTbtPolicy
+ //
+ PeiTbtConfig = (PEI_TBT_POLICY *) AllocateZeroPool (sizeof (PEI_TBT_POLICY));
+ ASSERT (PeiTbtConfig != NULL);
+ if (PeiTbtConfig == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize PPI
+ //
+ PeiTbtPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ PeiTbtPolicyPpiDesc->Guid = &gPeiTbtPolicyPpiGuid;
+ PeiTbtPolicyPpiDesc->Ppi = PeiTbtConfig;
+
+ Status = PeiServicesInstallPpi (PeiTbtPolicyPpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Install PEI TBT Policy failed\n"));
+ }
+ return Status;
+}
+
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.inf b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.inf
new file mode 100644
index 0000000000..fa88e97b8f
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.inf
@@ -0,0 +1,62 @@
+## @file
+# Component description file for Tbt policy
+#
+# Copyright (c) 2018, Intel Corporation. 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 = PeiTbtPolicyLib
+FILE_GUID = 4A95FDBB-2535-49eb-9A79-D56D24257106
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = PeiTbtPolicyLib
+
+
+[LibraryClasses]
+BaseMemoryLib
+PeiServicesLib
+PeiServicesTablePointerLib
+MemoryAllocationLib
+DebugLib
+PostCodeLib
+HobLib
+GpioLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ KabylakeOpenBoardPkg/OpenBoardPkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ IntelSiliconPkg/IntelSiliconPkg.dec
+
+[Pcd]
+gBoardModuleTokenSpaceGuid.PcdDTbtControllerEn ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtControllerType ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtPcieRpNumber ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtBootOn ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtUsbOn ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtGpio3ForcePwr ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtGpio3ForcePwrDly ## CONSUMES
+gBoardModuleTokenSpaceGuid.PcdDTbtCioPlugEventGpioPad ## CONSUMES
+
+[Sources]
+PeiTbtPolicyLib.c
+
+[Guids]
+gTbtInfoHobGuid
+
+[Ppis]
+gEfiPeiReadOnlyVariable2PpiGuid
+gPeiTbtPolicyPpiGuid
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLibrary.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLibrary.h
new file mode 100644
index 0000000000..16ac667b1c
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLibrary.h
@@ -0,0 +1,23 @@
+/** @file
+ Header file for the PeiTBTPolicy library.
+
+Copyright (c) 2018, Intel Corporation. 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_TBT_POLICY_LIBRARY_H_
+#define _PEI_TBT_POLICY_LIBRARY_H_
+
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#endif // _PEI_TBT_POLICY_LIBRARY_H_
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/Private/PeiDTbtInitLib/PeiDTbtInitLib.c b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/Private/PeiDTbtInitLib/PeiDTbtInitLib.c
new file mode 100644
index 0000000000..4521bff957
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/Private/PeiDTbtInitLib/PeiDTbtInitLib.c
@@ -0,0 +1,572 @@
+/**@file
+ Thunderbolt(TM) Pei Library
+
+Copyright (c) 2018, Intel Corporation. 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/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/GpioLib.h>
+#include <GpioPinsSklLp.h>
+#include <GpioPinsSklH.h>
+#include <Library/TimerLib.h>
+#include <Library/IoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/GpioExpanderLib.h>
+#include <Ppi/ReadOnlyVariable2.h>
+
+#include <Base.h>
+#include <Library/TbtCommonLib.h>
+#include <TbtBoardInfo.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Ppi/PeiTbtPolicy.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PeiTbtPolicyLib.h>
+#include <Library/PchPmcLib.h>
+#include <Private/Library/PeiDTbtInitLib.h>
+
+/**
+Is host router (For dTBT) or End Point (For iTBT) present before sleep
+
+@param[in] ControllerType - DTBT_CONTROLLER or ITBT_CONTROLLER
+@param[in] Controller - Controller begin offset of CMOS
+
+@Retval TRUE There is a TBT HostRouter presented before sleep
+@Retval FALSE There is no TBT HostRouter presented before sleep
+
+BOOLEAN
+IsHostRouterPresentBeforeSleep(
+IN UINT8 ControllerType,
+IN UINT8 Controller
+)
+{
+ UINT8 SavedState;
+
+ SavedState = (UINT8)GetTbtHostRouterStatus();
+ if (ControllerType == DTBT_CONTROLLER){
+ return ((SavedState & (DTBT_SAVE_STATE_OFFSET << Controller)) == (DTBT_SAVE_STATE_OFFSET << Controller));
+ } else {
+ if (ControllerType == ITBT_CONTROLLER) {
+ return ((SavedState & (ITBT_SAVE_STATE_OFFSET << Controller)) == (ITBT_SAVE_STATE_OFFSET << Controller));
+ }
+ }
+ return 0;
+}
+**/
+
+/**
+Execute TBT PCIE2TBT_SX_EXIT_TBT_CONNECTED Mail Box Command for S4 mode with PreBootAclEnable
+
+@param[in] Bus Bus number for Host Router (DTBT)
+@param[in] Device Device number for Host Router (DTBT)
+@param[in] Function Function number for Host Router (DTBT)
+@param[in] Timeout Time out with 100 ms garnularity
+@Retval true if command executes succesfully
+**/
+BOOLEAN
+TbtSetPcie2TbtSxExitCommandWithPreBootAclEnable(
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT32 Timeout
+)
+{
+ UINT64 Pcie2Tbt;
+ UINT64 Tbt2Pcie;
+ UINT32 RegisterValue;
+ BOOLEAN ReturnFlag;
+ UINT32 Command;
+
+ GET_TBT2PCIE_REGISTER_ADDRESS(0, Bus, Device, Function, Tbt2Pcie)
+ GET_PCIE2TBT_REGISTER_ADDRESS(0, Bus, Device, Function, Pcie2Tbt)
+
+// If PreBootAcl is Enable, we need to enable DATA bit while sending SX EXIT MAIL BOX Command
+ Command = (1 << 8) | PCIE2TBT_SX_EXIT_TBT_CONNECTED;
+ PciSegmentWrite32 (Pcie2Tbt, Command | PCIE2TBT_VLD_B);
+
+ ReturnFlag = InternalWaitforCommandCompletion(Tbt2Pcie, Timeout, TRUE, &RegisterValue);
+
+ PciSegmentWrite32(Pcie2Tbt, 0);
+
+ return ReturnFlag;
+}
+
+/**
+Set the Sleep Mode if the HR is up.
+@param[in] Bus Bus number for Host Router (DTBT)
+@param[in] Device Device number for Host Router (DTBT)
+@param[in] Function Function number for Host Router (DTBT)
+**/
+VOID
+TbtSetSxMode(
+IN UINT8 Bus,
+IN UINT8 Device,
+IN UINT8 Function,
+IN UINT8 TbtBootOn
+)
+{
+ UINT64 TbtUsDevId;
+ UINT64 Tbt2Pcie;
+ UINT32 RegVal;
+ UINT32 MaxLoopCount;
+ UINTN Delay;
+ UINT8 RetCode;
+ EFI_BOOT_MODE BootMode;
+ EFI_STATUS Status;
+
+ TbtUsDevId = PCI_SEGMENT_LIB_ADDRESS(0, Bus, Device, Function, 0);
+ GET_TBT2PCIE_REGISTER_ADDRESS(0, Bus, Device, Function, Tbt2Pcie)
+
+ MaxLoopCount = TBT_5S_TIMEOUT; // Wait 5 sec
+ Delay = 100 * 1000;
+ RetCode = 0x62;
+
+ Status = PeiServicesGetBootMode(&BootMode);
+ ASSERT_EFI_ERROR(Status);
+
+ if ((BootMode == BOOT_ON_S4_RESUME) && (TbtBootOn == 2)) {
+ MaxLoopCount = TBT_3S_TIMEOUT;
+ if (!TbtSetPcie2TbtSxExitCommandWithPreBootAclEnable(Bus, Device, Function, MaxLoopCount)) {
+ //
+ // Nothing to wait, HR is not responsive
+ //
+ return;
+ }
+ }
+ else {
+ if (!TbtSetPcie2TbtCommand(PCIE2TBT_SX_EXIT_TBT_CONNECTED, Bus, Device, Function, MaxLoopCount)) {
+ //
+ // Nothing to wait, HR is not responsive
+ //
+ return;
+ }
+ }
+
+ DEBUG((DEBUG_INFO, "Wait for Dev ID != 0xFF\n"));
+
+ while (MaxLoopCount-- > 0) {
+ //
+ // Check what HR still here
+ //
+ RegVal = PciSegmentRead32(Tbt2Pcie);
+ if (0xFFFFFFFF == RegVal) {
+ RetCode = 0x6F;
+ break;
+ }
+ //
+ // Check completion of TBT link
+ //
+ RegVal = PciSegmentRead32(TbtUsDevId);
+ if (0xFFFFFFFF != RegVal) {
+ RetCode = 0x61;
+ break;
+ }
+
+ MicroSecondDelay(Delay);
+ }
+
+ DEBUG((DEBUG_INFO, "Return code = 0x%x\n", RetCode));
+}
+/**
+ set tPCH25 Timing to 10 ms for DTBT.
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtSetTPch25Timing (
+ IN PEI_TBT_POLICY *PeiTbtConfig
+)
+{
+ DEBUG ((DEBUG_INFO, "DTbtSetTPch25Timing call Inside\n"));
+ UINT32 PchPwrmBase;
+
+ //
+ //During boot, reboot and wake tPCH25 Timing should be set to 10 ms
+ //
+ PchPwrmBaseGet (&PchPwrmBase);
+ MmioOr32 (
+ (UINTN) (PchPwrmBase + R_PCH_PWRM_CFG),
+ (BIT0 | BIT1)
+ );
+
+ DEBUG((DEBUG_INFO, "DTbtSetTPch25Timing call Return\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ Do ForcePower for DTBT Controller
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtForcePower (
+ IN PEI_TBT_POLICY *PeiTbtConfig
+)
+{
+
+ DEBUG ((DEBUG_INFO, "DTbtForcePower call Inside\n"));
+
+ if (PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwr) {
+ DEBUG((DEBUG_INFO, "ForcePwrGpio.GpioPad = %x \n", PeiTbtConfig-> DTbtControllerConfig.ForcePwrGpio.GpioPad));
+ ForceDtbtPower(PeiTbtConfig-> DTbtControllerConfig.ForcePwrGpio.GpioAccessType,PeiTbtConfig-> DTbtControllerConfig.ForcePwrGpio.Expander, PeiTbtConfig-> DTbtControllerConfig.ForcePwrGpio.GpioPad, PeiTbtConfig-> DTbtControllerConfig.ForcePwrGpio.GpioLevel);
+ DEBUG((DEBUG_INFO, "ForceDtbtPower asserted \n"));
+ MicroSecondDelay(PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwrDly * 1000);
+ DEBUG((DEBUG_INFO, "Delay after ForceDtbtPower = 0x%x ms \n", PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwrDly));
+ }
+
+ DEBUG ((DEBUG_INFO, "DTbtForcePower call Return\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ Clear VGA Registers for DTBT.
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtClearVgaRegisters (
+ IN PEI_TBT_POLICY *PeiTbtConfig
+)
+{
+ UINTN RpDev;
+ UINTN RpFunc;
+ EFI_STATUS Status;
+ UINT64 BridngeBaseAddress;
+ UINT16 Data16;
+
+ DEBUG ((DEBUG_INFO, "DTbtClearVgaRegisters call Inside\n"));
+
+ Status = EFI_SUCCESS;
+
+ Status = GetDTbtRpDevFun(PeiTbtConfig-> DTbtControllerConfig.Type, PeiTbtConfig-> DTbtControllerConfig.PcieRpNumber - 1, &RpDev, &RpFunc);
+ ASSERT_EFI_ERROR(Status);
+ //
+ // VGA Enable and VGA 16-bit decode registers of Bridge control register of Root port where
+ // Host router resides should be cleaned
+ //
+
+ BridngeBaseAddress = PCI_SEGMENT_LIB_ADDRESS(0, 0, (UINT32)RpDev, (UINT32)RpFunc, 0);
+ Data16 = PciSegmentRead16(BridngeBaseAddress + PCI_BRIDGE_CONTROL_REGISTER_OFFSET);
+ Data16 &= (~(EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16));
+ PciSegmentWrite16(BridngeBaseAddress + PCI_BRIDGE_CONTROL_REGISTER_OFFSET, Data16);
+
+ DEBUG ((DEBUG_INFO, "DTbtClearVgaRegisters call Return\n"));
+ return Status;
+}
+
+/**
+ Exectue Mail box command "Boot On".
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtBootOn(
+ IN PEI_TBT_POLICY *PeiTbtConfig
+)
+{
+ EFI_STATUS Status;
+ UINT32 OrgBusNumberConfiguration;
+ UINTN RpDev;
+ UINTN RpFunc;
+
+ DEBUG((DEBUG_INFO, "DTbtBootOn call Inside\n"));
+
+ Status = EFI_SUCCESS;
+
+ Status = GetDTbtRpDevFun(PeiTbtConfig-> DTbtControllerConfig.Type, PeiTbtConfig-> DTbtControllerConfig.PcieRpNumber - 1, &RpDev, &RpFunc);
+ ASSERT_EFI_ERROR(Status);
+ OrgBusNumberConfiguration = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (0, 0, RpDev, RpFunc, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET));
+ //
+ // Set Sec/Sub buses to 0xF0
+ //
+ PciSegmentWrite32(PCI_SEGMENT_LIB_ADDRESS (0, 0, RpDev, RpFunc, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET), 0x00F0F000);
+ //
+ //When Thunderbolt(TM) boot [TbtBootOn] is enabled in bios setup we need to do the below:
+ //Bios should send "Boot On" message through PCIE2TBT register
+ //The Boot On command as described above would include the command and acknowledge from FW (with the default timeout in BIOS),
+ //once the Boot On command is completed it is guaranteed that the AlpineRidge(AR) device is there and the PCI tunneling was done by FW,
+ //next step from BIOS is enumeration using SMI
+ //
+
+ if (PeiTbtConfig->DTbtCommonConfig.TbtBootOn > 0) {
+ //
+ // Exectue Mail box command "Boot On / Pre-Boot ACL"
+ //
+ //Command may be executed only during boot/reboot and not during Sx exit flow
+ if (PeiTbtConfig->DTbtCommonConfig.TbtBootOn == 1) {
+ if (!TbtSetPcie2TbtCommand(PCIE2TBT_BOOT_ON, 0xF0, 0, 0, TBT_5S_TIMEOUT)) {
+ //
+ // Nothing to wait, HR is not responsive
+ //
+ DEBUG((DEBUG_INFO, "<TbtPei> DTbtBootOn - Boot On message sent failed \n"));
+ }
+ }
+ if (PeiTbtConfig->DTbtCommonConfig.TbtBootOn == 2) {
+ if (!TbtSetPcie2TbtCommand(PCIE2TBT_PREBOOTACL, 0xF0, 0, 0, TBT_3S_TIMEOUT)) {
+ //
+ // Nothing to wait, HR is not responsive
+ //
+ DEBUG((DEBUG_INFO, "<TbtPei> DTbtBootOn - Pre-Boot ACL message sent failed \n"));
+ }
+ }
+ }
+ //
+ // Reset Sec/Sub buses to original value
+ //
+ PciSegmentWrite32(PCI_SEGMENT_LIB_ADDRESS (0, 0, RpDev, RpFunc, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET), OrgBusNumberConfiguration);
+
+ DEBUG((DEBUG_INFO, "DTbtBootOn call Return\n"));
+ return Status;
+}
+
+/**
+ Exectue Mail box command "USB On".
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtUsbOn(
+ IN PEI_TBT_POLICY *PeiTbtConfig
+)
+{
+ EFI_STATUS Status;
+ UINTN RpDev;
+ UINTN RpFunc;
+ UINT32 OrgBusNumberConfiguration;
+ UINT64 TbtBaseAddress;
+ UINT32 MaxWaitIter;
+ UINT32 RegVal;
+ EFI_BOOT_MODE BootMode;
+
+ DEBUG((DEBUG_INFO, "DTbtUsbOn call Inside\n"));
+
+ Status = EFI_SUCCESS;
+
+ Status = GetDTbtRpDevFun(PeiTbtConfig-> DTbtControllerConfig.Type, PeiTbtConfig-> DTbtControllerConfig.PcieRpNumber - 1, &RpDev, &RpFunc);
+ ASSERT_EFI_ERROR(Status);
+ OrgBusNumberConfiguration = PciSegmentRead32(PCI_SEGMENT_LIB_ADDRESS (0, 0, RpDev, RpFunc, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET));
+ //
+ // Set Sec/Sub buses to 0xF0
+ //
+ PciSegmentWrite32(PCI_SEGMENT_LIB_ADDRESS (0, 0, RpDev, RpFunc, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET), 0x00F0F000);
+
+ //
+ //When Thunderbolt(TM) Usb boot [TbtUsbOn] is enabled in bios setup we need to do the below:
+ //Bios should send "Usb On" message through PCIE2TBT register
+ //The Usb On command as described above would include the command and acknowledge from FW (with the default timeout in BIOS),
+ //once the Usb On command is completed it is guaranteed that the AlpineRidge(AR) device is there and the PCI tunneling was done by FW,
+ //next step from BIOS is enumeration using SMI
+ //
+ if (PeiTbtConfig->DTbtCommonConfig.TbtUsbOn) {
+ if (PeiTbtConfig->DTbtCommonConfig.TbtBootOn > 0) {
+ MaxWaitIter = 50; // Wait 5 sec
+ TbtBaseAddress = PCI_SEGMENT_LIB_ADDRESS(0, 0xF0, 0, 0, 0);
+ //
+ // Driver clears the PCIe2TBT Valid bit to support two consicutive mailbox commands
+ //
+ PciSegmentWrite32(TbtBaseAddress + PCIE2TBT_DTBT_R, 0);
+ DEBUG((DEBUG_INFO, "TbtBaseAddress + PCIE2TBT_DTBT_R = 0x%lx \n", TbtBaseAddress + PCIE2TBT_DTBT_R));
+ while (MaxWaitIter-- > 0) {
+ RegVal = PciSegmentRead32(TbtBaseAddress + TBT2PCIE_DTBT_R);
+ if (0xFFFFFFFF == RegVal) {
+ //
+ // Device is not here return now
+ //
+ DEBUG((DEBUG_INFO, "TBT device is not present \n"));
+ break;
+ }
+
+ if (!(RegVal & TBT2PCIE_DON_R)) {
+ break;
+ }
+ MicroSecondDelay(100 * 1000);
+ }
+ }
+
+ Status = PeiServicesGetBootMode(&BootMode);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Exectue Mail box command "Usb On"
+ //
+ //Command may be executed only during boot/reboot and not during S3 exit flow
+ //In case of S4 Exit send USB ON cmd only if Host Router was inactive/not present during S4 entry
+ if ((BootMode == BOOT_ON_S4_RESUME) ) {
+ // USB_ON cmd not required
+ } else {
+ if (!TbtSetPcie2TbtCommand(PCIE2TBT_USB_ON, 0xF0, 0, 0, TBT_5S_TIMEOUT)) {
+ //
+ // Nothing to wait, HR is not responsive
+ //
+ DEBUG((DEBUG_INFO, "<TbtPei> TbtBootSupport - Usb On message sent failed \n"));
+ }
+ }
+ }
+ //
+ // Reset Sec/Sub buses to original value
+ //
+ PciSegmentWrite32(PCI_SEGMENT_LIB_ADDRESS (0, 0, RpDev, RpFunc, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET), OrgBusNumberConfiguration);
+
+ DEBUG((DEBUG_INFO, "DTbtUsbOn call return\n"));
+ return Status;
+}
+
+/**
+ Exectue Mail box command "Sx Exit".
+
+ @param[in] PEI_TBT_POLICY PeiTbtConfig
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_UNSUPPORTED dTBT is not supported.
+**/
+EFI_STATUS
+EFIAPI
+DTbtSxExitFlow(
+ IN PEI_TBT_POLICY *PeiTbtConfig
+)
+{
+ EFI_STATUS Status;
+ UINT32 OrgBusNumberConfiguration;
+ UINTN RpDev;
+ UINTN RpFunc;
+ UINT32 Count;
+
+ DEBUG((DEBUG_INFO, "DTbtSxExitFlow call Inside\n"));
+
+ Status = EFI_SUCCESS;
+ Count = 0;
+
+ Status = GetDTbtRpDevFun(PeiTbtConfig-> DTbtControllerConfig.Type, PeiTbtConfig-> DTbtControllerConfig.PcieRpNumber - 1, &RpDev, &RpFunc);
+ ASSERT_EFI_ERROR(Status);
+ OrgBusNumberConfiguration = PciSegmentRead32(PCI_SEGMENT_LIB_ADDRESS (0, 0, RpDev, RpFunc, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET));
+ //
+ // Set Sec/Sub buses to 0xF0
+ //
+ PciSegmentWrite32(PCI_SEGMENT_LIB_ADDRESS (0, 0, RpDev, RpFunc, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET), 0x00F0F000);
+
+ if ( (PeiTbtConfig->DTbtCommonConfig.TbtBootOn == 2)) {
+ //
+ // WA: When system with TBT 3.1 device, resume SX system need to wait device ready. In document that maximum time out should be 500ms.
+ //
+ while (PciSegmentRead32(PCI_SEGMENT_LIB_ADDRESS(0, 0xf0, 0x0, 0x0, 0x08)) == 0xffffffff) { //End Device will be with Device Number 0x0, Function Number 0x0.
+ MicroSecondDelay(STALL_ONE_MICRO_SECOND * 1000); // 1000usec
+ Count++;
+ if (Count > 10000) { //Allowing Max Delay of 10 sec for CFL-S board.
+ break;
+ }
+ }
+
+ //
+ // Upon wake, if BIOS saved pre-Sx Host Router state as active (system went to sleep with
+ // attached devices), BIOS should:
+ // 1. Execute "Sx_Exit_TBT_Connected" mailbox command.
+ // 2. If procedure above returns true, BIOS should perform "wait for fast link bring-up" loop
+ // 3. Continue regular wake flow.
+ //
+ //
+ // Exectue Mail box command and perform "wait for fast link bring-up" loop
+ //
+ TbtSetSxMode(0xF0, 0, 0, PeiTbtConfig->DTbtCommonConfig.TbtBootOn);
+ }
+ //
+ // Reset Sec/Sub buses to original value
+ //
+ PciSegmentWrite32(PCI_SEGMENT_LIB_ADDRESS (0, 0, RpDev, RpFunc, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET), OrgBusNumberConfiguration);
+
+ DEBUG((DEBUG_INFO, "DTbtSxExitFlow call Return\n"));
+ return Status;
+}
+
+
+/**
+ Initialize Thunderbolt(TM)
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval others
+**/
+EFI_STATUS
+EFIAPI
+TbtInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PEI_TBT_POLICY *PeiTbtConfig;
+
+ //
+ // Get the TBT Policy
+ //
+ Status = PeiServicesLocatePpi (
+ &gPeiTbtPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PeiTbtConfig
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, " gPeiTbtPolicyPpiGuid Not installed!!!\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Exectue Mail box command "Boot On"
+ //
+ Status = DTbtBootOn (PeiTbtConfig);
+ //
+ // Exectue Mail box command "Usb On"
+ //
+ Status = DTbtUsbOn (PeiTbtConfig);
+ //
+ //During boot, reboot and wake (bits [1:0]) of PCH PM_CFG register should be
+ //set to 11b - 10 ms (default value is 0b - 10 us)
+ //
+ Status = DTbtSetTPch25Timing (PeiTbtConfig);
+ //
+ // Configure Tbt Force Power
+ //
+ Status = DTbtForcePower (PeiTbtConfig);
+ //
+ // VGA Enable and VGA 16-bit decode registers of Bridge control register of Root port where
+ // Host router resides should be cleaned
+ //
+ Status = DTbtClearVgaRegisters (PeiTbtConfig);
+ //
+ // Upon wake, if BIOS saved pre-Sx Host Router state as active (system went to sleep with
+ // attached devices), BIOS should:
+ // 1. Execute "Sx_Exit_TBT_Connected" mailbox command.
+ // 2. If procedure above returns true, BIOS should perform "wait for fast link bring-up" loop
+ // 3. Continue regular wake flow.
+ //
+ Status = DTbtSxExitFlow (PeiTbtConfig);
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/Private/PeiDTbtInitLib/PeiDTbtInitLib.inf b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/Private/PeiDTbtInitLib/PeiDTbtInitLib.inf
new file mode 100644
index 0000000000..83a0f57535
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/Private/PeiDTbtInitLib/PeiDTbtInitLib.inf
@@ -0,0 +1,48 @@
+### @file
+# Component description file for PEI DTBT Init library.
+#
+# Copyright (c) 2018, Intel Corporation. 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 = PeiDTbtInitLib
+ FILE_GUID = 06768A8D-8152-403f-83C1-59584FD2B438
+ VERSION_STRING = 1.0
+ MODULE_TYPE = PEIM
+ LIBRARY_CLASS = PeiDTbtInitLib
+
+[LibraryClasses]
+ PeiServicesLib
+ DebugLib
+ PcdLib
+ TbtCommonLib
+ PciSegmentLib
+ PeiTbtPolicyLib
+ PchPmcLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ KabylakeOpenBoardPkg/OpenBoardPkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+[Ppis]
+ gPeiTbtPolicyPpiGuid ## CONSUMES
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
+ #gClientCommonModuleTokenSpaceGuid.PcdTbtSupport ## PRODUCES
+
+[Sources]
+ PeiDTbtInitLib.c
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Dxe/TbtDxe.c b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Dxe/TbtDxe.c
new file mode 100644
index 0000000000..cfe38d8018
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Dxe/TbtDxe.c
@@ -0,0 +1,233 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. 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/BaseMemoryLib.h>
+#include <Library/TbtCommonLib.h>
+#include <Library/DxeTbtPolicyLib.h>
+#include <TbtBoardInfo.h>
+#include <Protocol/DxeTbtPolicy.h>
+#include <Protocol/TbtNvsArea.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Uefi/UefiSpec.h>
+#include <Library/PcdLib.h>
+#include <Library/AslUpdateLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED TBT_NVS_AREA_PROTOCOL mTbtNvsAreaProtocol;
+GLOBAL_REMOVE_IF_UNREFERENCED TBT_INFO_HOB *gTbtInfoHob = NULL;
+
+/**
+ TBT NVS Area Initialize
+
+**/
+
+VOID
+TbtNvsAreaInit (
+ IN VOID **mTbtNvsAreaPtr
+ )
+{
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+ TBT_NVS_AREA_PROTOCOL *TbtNvsAreaProtocol;
+ DXE_TBT_POLICY_PROTOCOL *DxeTbtConfig;
+
+ DEBUG ((DEBUG_INFO, "TbtNvsAreaInit Start\n"));
+ Status = gBS->LocateProtocol (
+ &gDxeTbtPolicyProtocolGuid,
+ NULL,
+ (VOID **) &DxeTbtConfig
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Pages = EFI_SIZE_TO_PAGES (sizeof (TBT_NVS_AREA));
+ Address = 0xffffffff; // allocate address below 4G.
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ Pages,
+ &Address
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *mTbtNvsAreaPtr = (VOID *) (UINTN) Address;
+ SetMem (*mTbtNvsAreaPtr, sizeof (TBT_NVS_AREA), 0);
+
+ //
+ // TBTNvsAreaProtocol default value init here
+ //
+ TbtNvsAreaProtocol = (TBT_NVS_AREA_PROTOCOL *) &Address;
+
+ //
+ // Initialize default values
+ //
+ TbtNvsAreaProtocol->Area->WAKFinished = 0;
+ TbtNvsAreaProtocol->Area->DiscreteTbtSupport = ((gTbtInfoHob-> DTbtControllerConfig.DTbtControllerEn == 1 ) ? TRUE : FALSE);
+ TbtNvsAreaProtocol->Area->TbtAcpiRemovalSupport = 0;
+ TbtNvsAreaProtocol->Area->TbtGpioFilter = (UINT8) DxeTbtConfig->TbtCommonConfig.Gpio5Filter;
+// TbtNvsAreaProtocol->Area->TrOsup = (UINT8) DxeTbtConfig->TbtCommonConfig.TrA0OsupWa;
+ TbtNvsAreaProtocol->Area->TbtFrcPwrEn = gTbtInfoHob->DTbtCommonConfig.Gpio3ForcePwr;
+ TbtNvsAreaProtocol->Area->TbtAspm = (UINT8) DxeTbtConfig->TbtCommonConfig.TbtAspm;
+// TbtNvsAreaProtocol->Area->TbtL1SubStates = (UINT8) DxeTbtConfig->TbtCommonConfig.TbtL1SubStates;
+ TbtNvsAreaProtocol->Area->TbtSetClkReq = (UINT8) DxeTbtConfig->TbtCommonConfig.TbtSetClkReq;
+ TbtNvsAreaProtocol->Area->TbtLtr = (UINT8) DxeTbtConfig->TbtCommonConfig.TbtLtr;
+// TbtNvsAreaProtocol->Area->TbtPtm = (UINT8) DxeTbtConfig->TbtCommonConfig.TbtPtm;
+ TbtNvsAreaProtocol->Area->TbtWakeupSupport = (UINT8) DxeTbtConfig->TbtCommonConfig.TbtWakeupSupport;
+ TbtNvsAreaProtocol->Area->TbtAcDcSwitch = (UINT8) DxeTbtConfig->TbtCommonConfig.TbtAcDcSwitch;
+ TbtNvsAreaProtocol->Area->Rtd3TbtSupport = (UINT8) DxeTbtConfig->TbtCommonConfig.Rtd3Tbt; // TBT RTD3 Enable.
+ TbtNvsAreaProtocol->Area->Rtd3TbtOffDelay = (UINT16) DxeTbtConfig->TbtCommonConfig.Rtd3TbtOffDelay; // TBT RTD3 Off delay in ms.
+ TbtNvsAreaProtocol->Area->Rtd3TbtClkReq = (UINT8) DxeTbtConfig->TbtCommonConfig.Rtd3TbtClkReq; // TBT RTD3 ClkReq Mask Enable.
+ TbtNvsAreaProtocol->Area->Rtd3TbtClkReqDelay = (UINT16) DxeTbtConfig->TbtCommonConfig.Rtd3TbtClkReqDelay; // TBT RTD3 ClkReq mask delay in ms.
+ TbtNvsAreaProtocol->Area->TbtWin10Support = (UINT8) DxeTbtConfig->TbtCommonConfig.Win10Support; // TBT FW Execution Mode
+
+ //
+ // DTBT Controller 1
+ //
+ TbtNvsAreaProtocol->Area->DTbtControllerEn0 = gTbtInfoHob-> DTbtControllerConfig.DTbtControllerEn;
+ TbtNvsAreaProtocol->Area->RootportSelected0 = gTbtInfoHob-> DTbtControllerConfig.PcieRpNumber;
+ TbtNvsAreaProtocol->Area->RootportSelected0Type = gTbtInfoHob-> DTbtControllerConfig.Type;
+ TbtNvsAreaProtocol->Area->RootportEnabled0 = gTbtInfoHob-> DTbtControllerConfig.DTbtControllerEn;
+ TbtNvsAreaProtocol->Area->TbtFrcPwrGpioNo0 = gTbtInfoHob-> DTbtControllerConfig.ForcePwrGpio.GpioPad;
+ TbtNvsAreaProtocol->Area->TbtFrcPwrGpioLevel0 = gTbtInfoHob-> DTbtControllerConfig.ForcePwrGpio.GpioLevel;
+ TbtNvsAreaProtocol->Area->TbtCioPlugEventGpioNo0 = gTbtInfoHob-> DTbtControllerConfig.CioPlugEventGpio.GpioPad;
+ TbtNvsAreaProtocol->Area->TbtPcieRstGpioNo0 = gTbtInfoHob-> DTbtControllerConfig.PcieRstGpio.GpioPad;
+ TbtNvsAreaProtocol->Area->TbtPcieRstGpioLevel0 = gTbtInfoHob-> DTbtControllerConfig.PcieRstGpio.GpioLevel;
+
+ TbtNvsAreaProtocol->Area->TBtCommonGpioSupport = gTbtInfoHob->DTbtCommonConfig.DTbtSharedGpioConfiguration;
+
+ DEBUG ((DEBUG_INFO, "TbtNvsAreaInit End\n"));
+}
+
+/**
+ This function gets registered as a callback to patch TBT ASL code
+
+ @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.
+ can we put this also in read me
+**/
+VOID
+EFIAPI
+TbtAcpiEndOfDxeCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Address;
+ UINT16 Length;
+ UINT32 Signature;
+
+ Status = InitializeAslUpdateLib ();
+ ASSERT_EFI_ERROR (Status);
+
+ Address = (UINT32) (UINTN) mTbtNvsAreaProtocol.Area;
+ Length = (UINT16) sizeof (TBT_NVS_AREA);
+ DEBUG ((DEBUG_INFO, "Patch TBT NvsAreaAddress: TBT NVS Address %x Length %x\n", Address, Length));
+ Status = UpdateNameAslCode (SIGNATURE_32 ('T','N','V','B'), &Address, sizeof (Address));
+ ASSERT_EFI_ERROR (Status);
+ Status = UpdateNameAslCode (SIGNATURE_32 ('T','N','V','L'), &Length, sizeof (Length));
+ ASSERT_EFI_ERROR (Status);
+
+ if (gTbtInfoHob != NULL) {
+ if (gTbtInfoHob-> DTbtControllerConfig.DTbtControllerEn == 1) {
+ if (gTbtInfoHob-> DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignaturePorting == TRUE) {
+ DEBUG ((DEBUG_INFO, "Patch ATBT Method Name\n"));
+ Signature = gTbtInfoHob-> DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignature;
+ Status = UpdateNameAslCode (SIGNATURE_32 ('A','T','B','T'), &Signature, sizeof (Signature));
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ }
+
+ return;
+}
+
+/**
+ Initialize Thunderbolt(TM) SSDT ACPI tables
+
+ @retval EFI_SUCCESS ACPI tables are initialized successfully
+ @retval EFI_NOT_FOUND ACPI tables not found
+**/
+
+EFI_STATUS
+EFIAPI
+TbtDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ // EFI_EVENT EndOfDxeEvent;
+
+ DEBUG ((DEBUG_INFO, "TbtDxeEntryPoint \n"));
+
+ //
+ // Get TBT INFO HOB
+ //
+ gTbtInfoHob = (TBT_INFO_HOB *) GetFirstGuidHob (&gTbtInfoHobGuid);
+ if (gTbtInfoHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ InstallTbtPolicy (ImageHandle);
+ //
+ // Update DXE TBT Policy
+ //
+ UpdateTbtPolicyCallback ();
+
+ //
+ // Print DXE TBT Policy
+ //
+ TbtPrintDxePolicyConfig ();
+
+ //
+ // Initialize Tbt Nvs Area
+ //
+ TbtNvsAreaInit ((VOID **) &mTbtNvsAreaProtocol.Area);
+
+
+ //
+ // [ACPI] Thunderbolt ACPI table
+ //
+
+
+ Handle = NULL;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gTbtNvsAreaProtocolGuid,
+ &mTbtNvsAreaProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register an end of DXE event for TBT ACPI to do some patch can be put as description
+ //
+ /**
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ TbtAcpiEndOfDxeCallback,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+**/
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Dxe/TbtDxe.inf b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Dxe/TbtDxe.inf
new file mode 100644
index 0000000000..86f51191d1
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Dxe/TbtDxe.inf
@@ -0,0 +1,54 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. 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 = TbtDxe
+ FILE_GUID = 19C9762C-3A88-41B0-906F-8C4C2895A887
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ ENTRY_POINT = TbtDxeEntryPoint
+
+[LibraryClasses]
+ DebugLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiDriverEntryPoint
+ HobLib
+ UefiLib
+ TbtCommonLib
+ DxeTbtPolicyLib
+ AslUpdateLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ KabylakeOpenBoardPkg/OpenBoardPkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+ TbtDxe.c
+
+[Protocols]
+ gTbtNvsAreaProtocolGuid ## CONSUMES
+ gDxeTbtPolicyProtocolGuid
+
+[Guids]
+ gTbtInfoHobGuid ## CONSUMES
+
+[Depex]
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiVariableArchProtocolGuid \ No newline at end of file
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Pei/PeiTbtInit.c b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Pei/PeiTbtInit.c
new file mode 100644
index 0000000000..a9a022844d
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Pei/PeiTbtInit.c
@@ -0,0 +1,216 @@
+/** @file
+ Source code file for TBT Init PEI module
+
+Copyright (c) 2018, Intel Corporation. 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/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PeiTbtPolicyLib.h>
+#include <Ppi/SiPolicy.h>
+#include <Ppi/PeiTbtPolicy.h>
+#include <Ppi/EndOfPeiPhase.h>
+#include <TbtBoardInfo.h>
+#include <Private/Library/PeiDTbtInitLib.h>
+/*
+/**
+ This function Update and Print PEI TBT Policy after TbtPolicyBoardInitDone
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval others
+**/
+
+
+/**
+ This function pass PEI TBT Policy to Hob at the end of PEI
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval others
+**/
+
+
+EFI_STATUS
+EFIAPI
+PassTbtPolicyToHob (
+VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ TBT_INFO_HOB *TbtInfoHob;
+ PEI_TBT_POLICY *PeiTbtConfig;
+
+ DEBUG ((DEBUG_INFO, "PassTbtPolicyToHob\n"));
+
+ Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR (Status);
+ if (BootMode == BOOT_ON_S3_RESUME ) {
+ return EFI_SUCCESS;
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gPeiTbtPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PeiTbtConfig
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, " gPeiTbtPolicyPpiGuid Not installed!!!\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create HOB for TBT Data
+ //
+ Status = PeiServicesCreateHob (
+ EFI_HOB_TYPE_GUID_EXTENSION,
+ sizeof (TBT_INFO_HOB),
+ (VOID **) &TbtInfoHob
+ );
+ DEBUG ((DEBUG_INFO, "TbtInfoHob Created \n"));
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize the TBT INFO HOB data.
+ //
+ TbtInfoHob->EfiHobGuidType.Name = gTbtInfoHobGuid;
+
+ //
+ // Update DTBT Policy
+ //
+ TbtInfoHob-> DTbtControllerConfig.DTbtControllerEn = PeiTbtConfig-> DTbtControllerConfig.DTbtControllerEn;
+ TbtInfoHob-> DTbtControllerConfig.Type = PeiTbtConfig-> DTbtControllerConfig.Type;
+ TbtInfoHob-> DTbtControllerConfig.PcieRpNumber = PeiTbtConfig-> DTbtControllerConfig.PcieRpNumber;
+ TbtInfoHob-> DTbtControllerConfig.ForcePwrGpio.GpioPad = PeiTbtConfig-> DTbtControllerConfig.ForcePwrGpio.GpioPad;
+ TbtInfoHob-> DTbtControllerConfig.ForcePwrGpio.GpioLevel = PeiTbtConfig-> DTbtControllerConfig.ForcePwrGpio.GpioLevel;
+ TbtInfoHob-> DTbtControllerConfig.CioPlugEventGpio.GpioPad = PeiTbtConfig-> DTbtControllerConfig.CioPlugEventGpio.GpioPad;
+ TbtInfoHob-> DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignature = PeiTbtConfig-> DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignature;
+ TbtInfoHob-> DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignaturePorting = PeiTbtConfig-> DTbtControllerConfig.CioPlugEventGpio.AcpiGpeSignaturePorting;
+ TbtInfoHob-> DTbtControllerConfig.PcieRstGpio.GpioPad = PeiTbtConfig-> DTbtControllerConfig.PcieRstGpio.GpioPad;
+ TbtInfoHob-> DTbtControllerConfig.PcieRstGpio.GpioLevel = PeiTbtConfig-> DTbtControllerConfig.PcieRstGpio.GpioLevel;
+
+ TbtInfoHob->DTbtCommonConfig.TbtBootOn = PeiTbtConfig->DTbtCommonConfig.TbtBootOn;
+ TbtInfoHob->DTbtCommonConfig.TbtUsbOn = PeiTbtConfig->DTbtCommonConfig.TbtUsbOn;
+ TbtInfoHob->DTbtCommonConfig.Gpio3ForcePwr = PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwr;
+ TbtInfoHob->DTbtCommonConfig.Gpio3ForcePwrDly = PeiTbtConfig->DTbtCommonConfig.Gpio3ForcePwrDly;
+ TbtInfoHob->DTbtCommonConfig.DTbtSharedGpioConfiguration = PeiTbtConfig->DTbtCommonConfig.DTbtSharedGpioConfiguration;
+ TbtInfoHob->DTbtCommonConfig.PcieRstSupport = PeiTbtConfig->DTbtCommonConfig.PcieRstSupport;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function handles TbtInit task at the end of PEI
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval others
+**/
+
+EFI_STATUS
+EFIAPI
+TbtInitEndOfPei (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN DTbtExisted;
+ PEI_TBT_POLICY *PeiTbtConfig;
+
+ DEBUG ((DEBUG_INFO, "TbtInitEndOfPei Entry\n"));
+
+ Status = EFI_SUCCESS;
+ PeiTbtConfig = NULL;
+ DTbtExisted = FALSE;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiTbtPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PeiTbtConfig
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, " gPeiTbtPolicyPpiGuid Not installed!!!\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ if (PeiTbtConfig-> DTbtControllerConfig.DTbtControllerEn == 1) {
+ DTbtExisted = TRUE;
+ }
+
+ if (DTbtExisted == TRUE) {
+ //
+ // Call Init function
+ //
+ Status = TbtInit ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ TBT Init PEI module entry point
+
+ @param[in] FileHandle Not used.
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database
+**/
+EFI_STATUS
+EFIAPI
+TbtInitEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "TBT PEI EntryPoint\n"));
+
+ //
+ // Install PEI TBT Policy
+ //
+ Status = InstallPeiTbtPolicy ();
+ ASSERT_EFI_ERROR (Status);
+
+
+ UpdatePeiTbtPolicy ();
+
+ TbtPrintPeiPolicyConfig ();
+ //
+ // Performing PassTbtPolicyToHob and TbtInitEndOfPei
+ //
+ Status = PassTbtPolicyToHob ();
+
+ Status = TbtInitEndOfPei ();
+
+ return Status;
+}
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Pei/PeiTbtInit.inf b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Pei/PeiTbtInit.inf
new file mode 100644
index 0000000000..fdf85cbd67
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Pei/PeiTbtInit.inf
@@ -0,0 +1,50 @@
+### @file
+# Component information file for the TBT Init PEI module.
+#
+# Copyright (c) 2018, Intel Corporation. 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 = PeiTbtInit
+ FILE_GUID = 90BF2BFB-F998-4cbc-AD72-008D4D047A4B
+ VERSION_STRING = 1.0
+ MODULE_TYPE = PEIM
+ ENTRY_POINT = TbtInitEntryPoint
+
+[LibraryClasses]
+ PeimEntryPoint
+ DebugLib
+ HobLib
+ PeiServicesLib
+ PeiTbtPolicyLib
+ PeiDTbtInitLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ KabylakeOpenBoardPkg/OpenBoardPkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+[Sources]
+ PeiTbtInit.c
+
+[Guids]
+ gTbtInfoHobGuid ## CONSUMES
+
+[Ppis]
+ gEfiEndOfPeiSignalPpiGuid ## CONSUMES
+ gPeiTbtPolicyBoardInitDonePpiGuid ## CONSUMES
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid \ No newline at end of file
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmiHandler.c b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmiHandler.c
new file mode 100644
index 0000000000..5280f9e1c8
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmiHandler.c
@@ -0,0 +1,1615 @@
+/**@file
+
+Copyright (c) 2018, Intel Corporation. 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 "TbtSmiHandler.h"
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/SmmVariable.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/PciSegmentLib.h>
+#define MEM_PER_SLOT (DEF_RES_MEM_PER_DEV << 4)
+#define PMEM_PER_SLOT (DEF_RES_PMEM_PER_DEV << 4)
+#define IO_PER_SLOT (DEF_RES_IO_PER_DEV << 2)
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN gDeviceBaseAddress;
+//
+//US(X:0:0), DS(X+1:3:0),DS(X+1:4:0),DS(X+1:5:0),DS(X+1:6:0)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED BRDG_CONFIG HrConfigs[MAX_CFG_PORTS];
+
+extern UINT8 gCurrentDiscreteTbtRootPort;
+extern UINT8 gCurrentDiscreteTbtRootPortType;
+
+BOOLEAN isLegacyDevice = FALSE;
+STATIC UINT8 TbtSegment = 0;
+
+STATIC
+VOID
+PortInfoInit (
+ IN OUT PORT_INFO *PortInfo
+ )
+{
+ PortInfo->BusNumLimit = 4;
+}
+
+STATIC
+VOID
+UnsetVesc (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Fun
+ )
+{
+ UINT8 Dbus;
+ UINT32 Data32;
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+
+ //
+ // Check for abcence of DS bridge
+ //
+ if(0xFFFF == PciSegmentRead16(gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) {
+ return;
+ }
+
+ //
+ // Unset vesc_reg2[23] bit (to have an option to access below DS)
+ //
+ Data32 = PciSegmentRead32 (gDeviceBaseAddress + PCI_TBT_VESC_REG2);
+ Data32 &= 0xFF7FFFFF;
+ PciSegmentWrite32(gDeviceBaseAddress + PCI_TBT_VESC_REG2, Data32);
+ //
+ // Go to Device behind DS
+ //
+ Dbus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ DEBUG((DEBUG_INFO, "Dbus = %d\n",Dbus));
+ //
+ // Check if there is something behind this Downstream Port (Up or Ep)
+ // If there nothing behind Downstream Port Set vesc_reg2[23] bit -> this will flush all future MemWr
+ //
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Dbus, 0x00, 0x00, 0);
+ if(0xFFFF == PciSegmentRead16(gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET))
+ {
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ Data32 = PciSegmentRead32 (gDeviceBaseAddress + PCI_TBT_VESC_REG2);
+ Data32 |= 0x00800000;
+ PciSegmentWrite32 (gDeviceBaseAddress + PCI_TBT_VESC_REG2, Data32);
+ }
+}// Unset_VESC_REG2
+
+STATIC
+UINT16
+MemPerSlot (
+ IN UINT16 CurrentUsage
+ )
+{
+ if (CurrentUsage == 0) {
+ return 0;
+ }
+
+ if (CurrentUsage <= 16) {
+ return 16;
+ }
+
+ if (CurrentUsage <= 64) {
+ return 64;
+ }
+
+ if (CurrentUsage <= 128) {
+ return 128;
+ }
+
+ if (CurrentUsage <= 256) {
+ return 256;
+ }
+
+ if (CurrentUsage <= 512) {
+ return 512;
+ }
+
+ if (CurrentUsage <= 1024) {
+ return 1024;
+ }
+
+ return CurrentUsage;
+} // MemPerSlot
+
+STATIC
+UINT64
+PMemPerSlot (
+ IN UINT64 CurrentUsage
+ )
+{
+ if (CurrentUsage == 0) {
+ return 0;
+ }
+
+ if (CurrentUsage <= 1024ULL) {
+ return 1024ULL;
+ }
+
+ if (CurrentUsage <= 4096ULL) {
+ return 4096ULL;
+ }
+
+ return CurrentUsage;
+} // PMemPerSlot
+
+STATIC
+VOID
+SetPhyPortResources (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 SubBus,
+ IN INT8 Depth,
+ IN PORT_INFO *CurrentPi,
+ IN OUT PORT_INFO *PortInfo
+ )
+{
+ UINT8 Cmd;
+ UINT16 DeltaMem;
+ UINT64 DeltaPMem;
+
+ Cmd = CMD_BUS_MASTER;
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, 0x00, 0);
+
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, SubBus);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd);
+
+ DeltaMem = PortInfo->MemBase - CurrentPi->MemBase;
+ if (isLegacyDevice) {
+ if (Depth >= 0 && (DeltaMem < MEM_PER_SLOT)) {
+ PortInfo->MemBase += MEM_PER_SLOT - DeltaMem;
+ }
+ } else {
+ if (DeltaMem < MemPerSlot (DeltaMem)) {
+ PortInfo->MemBase += MemPerSlot (DeltaMem) - DeltaMem;
+ }
+ }
+
+ if (PortInfo->MemBase > CurrentPi->MemBase && (PortInfo->MemBase - 0x10) <= PortInfo->MemLimit) {
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), CurrentPi->MemBase);
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), PortInfo->MemBase - 0x10);
+ Cmd |= CMD_BM_MEM;
+ } else {
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), DISBL_MEM32_REG20);
+ PortInfo->MemBase = CurrentPi->MemBase;
+ }
+
+ DeltaPMem = PortInfo->PMemBase64 - CurrentPi->PMemBase64;
+ if (isLegacyDevice) {
+ if ((Depth >= 0) && ((UINTN)DeltaPMem < (UINTN)PMEM_PER_SLOT)) {
+ PortInfo->PMemBase64 += PMEM_PER_SLOT - DeltaPMem;
+ }
+ } else {
+ if (DeltaPMem < PMemPerSlot (DeltaPMem)) {
+ PortInfo->PMemBase64 += PMemPerSlot (DeltaPMem) - DeltaPMem;
+ }
+ }
+
+ if (PortInfo->PMemBase64 > CurrentPi->PMemBase64 && (PortInfo->PMemBase64 - 0x10) <= PortInfo->PMemLimit64) {
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), (UINT16) (CurrentPi->PMemBase64 & 0xFFFF));
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit), (UINT16) ((PortInfo->PMemBase64 - 0x10) & 0xFFFF));
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), (UINT32) (CurrentPi->PMemBase64 >> 16));
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), (UINT32) ((PortInfo->PMemBase64 - 0x10) >> 16));
+ Cmd |= CMD_BM_MEM;
+ } else {
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), DISBL_PMEM_REG24);
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), 0);
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), 0);
+ PortInfo->PMemBase64 = CurrentPi->PMemBase64;
+ }
+
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE);
+} // SetPhyPortResources
+
+STATIC
+UINT32
+SaveSetGetRestoreBar (
+ IN UINTN Bar
+ )
+{
+ UINT32 BarReq;
+ UINT32 OrigBar;
+
+ OrigBar = PciSegmentRead32(Bar); // Save BAR
+ PciSegmentWrite32(Bar, 0xFFFFFFFF); // Set BAR
+ BarReq = PciSegmentRead32(Bar); // Get BAR
+ PciSegmentWrite32(Bar, OrigBar); // Restore BAR
+
+ return BarReq;
+} // SaveSetGetRestoreBar
+
+STATIC
+VOID
+SetIoBar (
+ IN UINTN BAR,
+ IN UINT32 BarReq,
+ IN OUT UINT8 *Cmd,
+ IN OUT IO_REGS *IoReg
+ )
+{
+ UINT16 Alignment;
+ UINT16 Size;
+ UINT16 NewBase;
+
+ Alignment = ~(BarReq & 0xFFFC);
+ Size = Alignment + 1;
+
+ if (IoReg->Base > IoReg->Limit || !Size) {
+ return ;
+
+ }
+
+ NewBase = BAR_ALIGN (IoReg->Base, Alignment);
+ if (NewBase > IoReg->Limit || NewBase + Size - 1 > IoReg->Limit) {
+ return ;
+
+ }
+ PciSegmentWrite16(BAR, NewBase);
+ IoReg->Base = NewBase + Size; // Advance to new position
+ *Cmd |= CMD_BM_IO; // Set Io Space Enable
+} // SetIoBar
+
+STATIC
+VOID
+SetMemBar (
+ IN UINTN BAR,
+ IN UINT32 BarReq,
+ IN OUT UINT8 *Cmd,
+ IN OUT MEM_REGS *MemReg
+ )
+{
+ UINT32 Alignment;
+ UINT32 Size;
+ UINT32 NewBase;
+
+ Alignment = ~(BarReq & 0xFFFFFFF0);
+ Size = Alignment + 1;
+
+ if (MemReg->Base > MemReg->Limit || !Size) {
+ return ;
+
+ }
+
+ NewBase = BAR_ALIGN (MemReg->Base, Alignment);
+ if (NewBase > MemReg->Limit || NewBase + Size - 1 > MemReg->Limit) {
+ return ;
+
+ }
+
+ PciSegmentWrite32(BAR, NewBase);
+ MemReg->Base = NewBase + Size; // Advance to new position
+ *Cmd |= CMD_BM_MEM; // Set Memory Space Enable
+} // SetMemBar
+
+STATIC
+VOID
+SetPMem64Bar (
+ IN UINTN BAR,
+ IN BOOLEAN IsMaxBar,
+ IN UINT32 BarReq,
+ IN OUT UINT8 *Cmd,
+ IN OUT PMEM_REGS *MemReg
+ )
+{
+ UINT32 Alignment;
+ UINT32 Size;
+ UINT64 NewBase;
+
+ Alignment = ~(BarReq & 0xFFFFFFF0);
+ Size = Alignment + 1;
+
+ if (MemReg->Base64 > MemReg->Limit64 || !Size) {
+ return ;
+ }
+
+ NewBase = BAR_ALIGN (MemReg->Base64, Alignment);
+ if (NewBase > MemReg->Limit64 || NewBase + Size - 1 > MemReg->Limit64) {
+ return ;
+ }
+ PciSegmentWrite32(BAR, (UINT32)(NewBase & 0xFFFFFFFF));
+ if (!IsMaxBar) {
+ BAR++;
+ PciSegmentWrite32(BAR, (UINT32)(NewBase >> 32));
+ }
+ MemReg->Base64 = NewBase + Size; // Advance to new position
+ *Cmd |= CMD_BM_MEM; // Set Memory Space Enable
+} // SetPMem64Bar
+
+STATIC
+VOID
+SetDevResources (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 MaxFun, // PCI_MAX_FUNC for devices, 1 for bridge
+ IN UINT8 MaxBar, // PCI_BAR5 for devices, PCI_BAR1 for bridge
+ IN OUT PORT_INFO *PortInfo
+ )
+{
+ UINT8 Fun;
+ UINT8 Reg;
+ UINT32 BarReq;
+ IO_REGS Io;
+ MEM_REGS Mem;
+ PMEM_REGS PMem;
+ UINT8 Cmd;
+
+ Io.Base = PortInfo->IoBase << 8;
+ Io.Limit = (PortInfo->IoLimit << 8) | 0xFF;
+ Mem.Base = PortInfo->MemBase << 16;
+ Mem.Limit = (PortInfo->MemLimit << 16) | 0xFFFF;
+ PMem.Base64 = PortInfo->PMemBase64 << 16;
+ PMem.Limit64 = (PortInfo->PMemLimit64 << 16) | 0xFFFF;
+
+ for (Fun = 0; Fun < MaxFun; ++Fun) {
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BUS_MASTER);
+ Cmd = PciSegmentRead8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET);
+ if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) {
+ continue;
+
+ }
+
+ for (Reg = PCI_BASE_ADDRESSREG_OFFSET; Reg <= MaxBar; Reg += 4) {
+ BarReq = SaveSetGetRestoreBar(gDeviceBaseAddress + Reg); // Perform BAR sizing
+
+ if (BarReq & BIT0) {
+ //
+ // I/O BAR
+ //
+ SetIoBar (
+ (gDeviceBaseAddress + Reg),
+ BarReq,
+ &Cmd,
+ &Io
+ );
+ continue;
+ }
+
+ if (BarReq & BIT3) {
+ //
+ // P-Memory BAR
+ //
+ SetPMem64Bar ((gDeviceBaseAddress + Reg), MaxBar == Reg, BarReq, &Cmd, &PMem);
+ } else {
+ SetMemBar ((gDeviceBaseAddress + Reg), BarReq, &Cmd, &Mem);
+ }
+
+ if (BIT2 == (BarReq & (BIT2 | BIT1))) {
+ //
+ // Base address is 64 bits wide
+ //
+ Reg += 4;
+ if (!(BarReq & BIT3)) {
+ //
+ // 64-bit memory bar
+ //
+ PciSegmentWrite32 (gDeviceBaseAddress + Reg, 0);
+ }
+ }
+ }
+
+ if (Cmd & BIT1) {
+ //
+ // If device uses I/O and MEM mapping use only MEM mepping
+ //
+ Cmd &= ~BIT0;
+ }
+
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE);
+ }
+ //
+ // Update PortInfo if any changes
+ //
+ if (Io.Base > ((UINT32) PortInfo->IoBase << 8)) {
+ PortInfo->IoBase = (UINT8) (BAR_ALIGN (Io.Base, 0xFFF) >> 8);
+ }
+
+ if (Mem.Base > ((UINT32) PortInfo->MemBase << 16)) {
+ PortInfo->MemBase = (UINT16) (BAR_ALIGN (Mem.Base, 0xFFFFF) >> 16);
+ }
+
+ if (PMem.Base64 > (PortInfo->PMemBase64 << 16)) {
+ PortInfo->PMemBase64 = (BAR_ALIGN (PMem.Base64, 0xFFFFF) >> 16);
+ }
+} // SetDevResources
+
+STATIC
+VOID
+InitARHRConfigs(
+ IN HR_CONFIG *Hr_Config,
+ IN UINT8 BusNumLimit,
+ IN OUT BRDG_RES_CONFIG* HrResConf
+)
+{
+ UINT8 i,j;
+
+ //
+ // DS port for USB device
+ //
+ HrConfigs[AR_DS_PORT2].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1;
+ HrConfigs[AR_DS_PORT2].DevId.Dev = 2;
+ HrConfigs[AR_DS_PORT2].DevId.Fun = 0;
+ HrConfigs[AR_DS_PORT2].PBus = HrConfigs[AR_DS_PORT2].DevId.Bus;
+ HrConfigs[AR_DS_PORT2].SBus = HrConfigs[AR_DS_PORT2].PBus + 1;
+ HrConfigs[AR_DS_PORT2].SubBus = HrConfigs[AR_DS_PORT2].PBus + 1;
+ //
+ // CIO port
+ //
+ HrConfigs[AR_DS_PORT1].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1;
+ HrConfigs[AR_DS_PORT1].DevId.Dev = 1;
+ HrConfigs[AR_DS_PORT1].DevId.Fun = 0;
+ HrConfigs[AR_DS_PORT1].PBus = HrConfigs[AR_DS_PORT1].DevId.Bus;
+ HrConfigs[AR_DS_PORT1].SBus = HrConfigs[HR_DS_PORT0].SubBus + 1;
+ HrConfigs[AR_DS_PORT1].SubBus = BusNumLimit;
+
+ switch(Hr_Config->DeviceId)
+ {
+ //
+ // HR with 1 DS and 1 USB
+ //
+ case AR_HR_2C:
+ case AR_HR_LP:
+ case AR_HR_C0_2C:
+ case TR_HR_2C:
+ Hr_Config->MinDSNumber = HrConfigs[AR_DS_PORT1].DevId.Dev;
+ Hr_Config->MaxDSNumber = HrConfigs[AR_DS_PORT2].DevId.Dev;
+ Hr_Config->BridgeLoops = 4;
+ break;
+ //
+ // HR with 2 DS and 1 USB
+ //
+ case AR_HR_4C:
+ case TR_HR_4C:
+ case AR_HR_C0_4C:
+ Hr_Config->MinDSNumber = 1;
+ Hr_Config->MaxDSNumber = 4;
+ Hr_Config->BridgeLoops = 6;
+ for(j = 2, i = Hr_Config->MinDSNumber; j < count(HrConfigs) && i <= Hr_Config->MaxDSNumber; ++j, ++i)
+ {
+ HrConfigs[j].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1;
+ HrConfigs[j].DevId.Dev = i;
+ HrConfigs[j].DevId.Fun = 0;
+ HrConfigs[j].PBus = HrConfigs[j].DevId.Bus;
+ HrConfigs[j].Res.Cls = DEF_CACHE_LINE_SIZE;
+ }
+ break;
+ }
+}//InitARHRConfigs
+
+
+STATIC
+VOID
+InitCommonHRConfigs (
+ IN HR_CONFIG *Hr_Config,
+ IN UINT8 BusNumLimit,
+ IN OUT BRDG_RES_CONFIG *HrResConf
+ )
+{
+ UINT8 i;
+
+ UINT8 j;
+ for(i = 0; i < count(HrConfigs); ++i) {
+ HrConfigs[i].IsDSBridge = TRUE;
+ }
+ //
+ // US(HRBus:0:0)
+ //
+ HrConfigs[HR_US_PORT].DevId.Bus = Hr_Config->HRBus;
+ HrConfigs[HR_US_PORT].DevId.Dev = 0;
+ HrConfigs[HR_US_PORT].DevId.Fun = 0;
+ HrConfigs[HR_US_PORT].Res = *HrResConf;
+ HrConfigs[HR_US_PORT].Res.IoBase = 0xF1;
+ HrConfigs[HR_US_PORT].Res.IoLimit = 0x01;
+ HrConfigs[HR_US_PORT].PBus = HrConfigs[HR_US_PORT].DevId.Bus;
+ HrConfigs[HR_US_PORT].SBus = HrConfigs[HR_US_PORT].PBus + 1;
+ HrConfigs[HR_US_PORT].SubBus = BusNumLimit;
+ HrConfigs[HR_US_PORT].IsDSBridge = FALSE;
+
+ //
+ // HIA resides here
+ //
+ HrConfigs[HR_DS_PORT0].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1;
+ HrConfigs[HR_DS_PORT0].DevId.Dev = 0;
+ HrConfigs[HR_DS_PORT0].DevId.Fun = 0;
+ HrConfigs[HR_DS_PORT0].Res = NOT_IN_USE_BRIDGE;
+ HrConfigs[HR_DS_PORT0].Res.MemBase = HrResConf->MemLimit;
+ HrConfigs[HR_DS_PORT0].Res.MemLimit = HrResConf->MemLimit;
+ HrResConf->MemLimit -= 0x10; //This 1 MB chunk will be used by HIA
+ HrConfigs[HR_DS_PORT0].Res.Cmd = CMD_BM_MEM;
+ HrConfigs[HR_DS_PORT0].Res.Cls = DEF_CACHE_LINE_SIZE;
+ HrConfigs[HR_DS_PORT0].PBus = HrConfigs[HR_DS_PORT0].DevId.Bus;
+ HrConfigs[HR_DS_PORT0].SBus = HrConfigs[HR_DS_PORT0].PBus + 1;
+ HrConfigs[HR_DS_PORT0].SubBus = HrConfigs[HR_DS_PORT0].PBus + 1;
+
+ switch (Hr_Config->DeviceId) {
+ //
+ // Alpine Ridge
+ //
+ case AR_HR_2C:
+ case AR_HR_C0_2C:
+ case AR_HR_LP:
+ case AR_HR_4C:
+ case AR_HR_C0_4C:
+ //
+ // Titan Ridge
+ //
+ case TR_HR_2C:
+ case TR_HR_4C:
+ InitARHRConfigs(Hr_Config, BusNumLimit, HrResConf);
+ break;
+
+ default:
+ //
+ // DS(HRBus+2:3-6:0)
+ //
+ Hr_Config->MinDSNumber = 3;
+ Hr_Config->MaxDSNumber = 6;
+ Hr_Config->BridgeLoops = count (HrConfigs);
+
+ for (j = 2, i = Hr_Config->MinDSNumber; j < count (HrConfigs) && i <= Hr_Config->MaxDSNumber; ++j, ++i) {
+ HrConfigs[j].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1;
+ HrConfigs[j].DevId.Dev = i;
+ HrConfigs[j].DevId.Fun = 0;
+ HrConfigs[j].PBus = HrConfigs[j].DevId.Bus;
+ HrConfigs[j].Res.Cls = DEF_CACHE_LINE_SIZE;
+ }
+ }
+} // InitCommonHRConfigs
+
+STATIC
+VOID
+InitHRDSPort_Disable (
+ IN UINT8 id,
+ IN OUT BRDG_CONFIG *BrdgConf
+ )
+{
+ HrConfigs[id].Res = NOT_IN_USE_BRIDGE;
+ HrConfigs[id].SBus = BrdgConf->SBus;
+ HrConfigs[id].SubBus = BrdgConf->SBus;
+
+ BrdgConf->SBus++;
+} // InitHRDSPort_Disable
+
+//AR only
+
+STATIC
+VOID
+InitARDSPort_1Port(
+ IN OUT BRDG_CONFIG* BrdgConf
+)
+{
+ UINT16 MemBase = BrdgConf->Res.MemBase & 0xFFF0;
+ UINT64 PMemBase64 = BrdgConf->Res.PMemBase64 & ~0xFULL;
+ UINT8 BusRange = BrdgConf->SubBus - BrdgConf->PBus - 2;
+
+ HrConfigs[AR_DS_PORT1].Res = NOT_IN_USE_BRIDGE;
+ HrConfigs[AR_DS_PORT1].Res.Cls = DEF_CACHE_LINE_SIZE;
+ HrConfigs[AR_DS_PORT1].Res.Cmd = CMD_BM_MEM;
+ HrConfigs[AR_DS_PORT1].Res.MemBase = MemBase;
+ HrConfigs[AR_DS_PORT1].Res.MemLimit = BrdgConf->Res.MemLimit - 1;
+ HrConfigs[AR_DS_PORT1].Res.PMemBase64 = PMemBase64;
+ HrConfigs[AR_DS_PORT1].Res.PMemLimit64 = BrdgConf->Res.PMemLimit64;
+ HrConfigs[AR_DS_PORT1].SBus = BrdgConf->SBus;
+ HrConfigs[AR_DS_PORT1].SubBus = BrdgConf->SBus + BusRange;
+
+ BrdgConf->SBus = HrConfigs[AR_DS_PORT1].SubBus + 1;
+
+ HrConfigs[AR_DS_PORT2].Res = NOT_IN_USE_BRIDGE;
+ HrConfigs[AR_DS_PORT2].Res.Cls = DEF_CACHE_LINE_SIZE;
+ HrConfigs[AR_DS_PORT2].Res.Cmd = CMD_BM_MEM;
+ HrConfigs[AR_DS_PORT2].Res.MemBase = BrdgConf->Res.MemLimit;
+ HrConfigs[AR_DS_PORT2].Res.MemLimit = BrdgConf->Res.MemLimit;
+ HrConfigs[AR_DS_PORT2].SBus = BrdgConf->SBus;
+ HrConfigs[AR_DS_PORT2].SubBus = BrdgConf->SBus;
+
+ BrdgConf->SBus = HrConfigs[AR_DS_PORT2].SubBus + 1;
+}//InitARDSPort_1Port
+
+STATIC
+VOID
+InitARDSPort_2Port(
+ IN OUT BRDG_CONFIG* BrdgConf
+)
+{
+ UINT16 MemBase = BrdgConf->Res.MemBase & 0xFFF0;
+ UINT64 PMemBase64 = BrdgConf->Res.PMemBase64 & ~0xFULL;
+ UINT8 BusRange = BrdgConf->SubBus - BrdgConf->PBus - 3;
+
+ // Busses are split between ports 1 and 4
+ BusRange /= 2;
+
+ HrConfigs[AR_DS_PORT1].Res = NOT_IN_USE_BRIDGE;
+ HrConfigs[AR_DS_PORT1].Res.Cls = DEF_CACHE_LINE_SIZE;
+ HrConfigs[AR_DS_PORT1].Res.Cmd = CMD_BM_MEM;
+ HrConfigs[AR_DS_PORT1].Res.MemBase = MemBase;
+ HrConfigs[AR_DS_PORT1].Res.MemLimit = MemBase + 0x17F0 - 1;
+ HrConfigs[AR_DS_PORT1].Res.PMemBase64 = PMemBase64;
+ HrConfigs[AR_DS_PORT1].Res.PMemLimit64 = PMemBase64 + 0x2000 - 1;
+ HrConfigs[AR_DS_PORT1].SBus = BrdgConf->SBus;
+ HrConfigs[AR_DS_PORT1].SubBus = BrdgConf->SBus + BusRange;
+
+ BrdgConf->SBus = HrConfigs[AR_DS_PORT1].SubBus + 1;
+
+ HrConfigs[AR_DS_PORT2].Res = NOT_IN_USE_BRIDGE;
+ HrConfigs[AR_DS_PORT2].Res.Cls = DEF_CACHE_LINE_SIZE;
+ HrConfigs[AR_DS_PORT2].Res.Cmd = CMD_BM_MEM;
+ HrConfigs[AR_DS_PORT2].Res.MemBase = MemBase + 0x17F0;
+ HrConfigs[AR_DS_PORT2].Res.MemLimit = MemBase + 0x1800 - 1;
+ HrConfigs[AR_DS_PORT2].SBus = BrdgConf->SBus;
+ HrConfigs[AR_DS_PORT2].SubBus = BrdgConf->SBus;
+
+ BrdgConf->SBus = HrConfigs[AR_DS_PORT2].SubBus + 1;
+
+
+ HrConfigs[AR_DS_PORT4].Res = NOT_IN_USE_BRIDGE;
+ HrConfigs[AR_DS_PORT4].Res.Cls = DEF_CACHE_LINE_SIZE;
+ HrConfigs[AR_DS_PORT4].Res.Cmd = CMD_BM_MEM;
+ HrConfigs[AR_DS_PORT4].Res.MemBase = MemBase + 0x1800;
+ HrConfigs[AR_DS_PORT4].Res.MemLimit = BrdgConf->Res.MemLimit;
+ HrConfigs[AR_DS_PORT4].Res.PMemBase64 = PMemBase64 + 0x2000;
+ HrConfigs[AR_DS_PORT4].Res.PMemLimit64 = BrdgConf->Res.PMemLimit64;
+ HrConfigs[AR_DS_PORT4].SBus = BrdgConf->SBus;
+ HrConfigs[AR_DS_PORT4].SubBus = BrdgConf->SubBus;
+
+ BrdgConf->SBus = HrConfigs[AR_DS_PORT4].SubBus + 1;
+}//InitARDSPort_2Port
+
+
+STATIC
+BOOLEAN
+CheckLimits (
+ IN BOOLEAN Is2PortDev,
+ IN BRDG_RES_CONFIG *HrResConf,
+ IN UINT8 BusRange
+ )
+{
+ UINT16 MemBase;
+ UINT16 MemLimit;
+ UINT64 PMemBase64;
+ UINT64 PMemLimit64;
+
+ MemBase = HrResConf->MemBase & 0xFFF0;
+ MemLimit = HrResConf->MemLimit & 0xFFF0;
+ PMemBase64 = HrResConf->PMemBase64 & 0xFFF0;
+ PMemLimit64 = HrResConf->PMemLimit64 & 0xFFF0;
+ //
+ // Check memoty alignment
+ //
+ if (MemBase & 0x3FF) {
+ DEBUG((DEBUG_INFO, "M alig\n"));
+ return FALSE;
+ }
+
+ if (PMemBase64 & 0xFFF) {
+ DEBUG((DEBUG_INFO, "PM alig\n"));
+ return FALSE;
+ }
+
+ if (Is2PortDev) {
+ //
+ // Check mem size
+ //
+ if (MemLimit + 0x10 - MemBase < 0x2E00) {
+ DEBUG((DEBUG_INFO, "M size\n"));
+ return FALSE;
+ }
+ //
+ // Check P-mem size
+ //
+ if (PMemLimit64 + 0x10 - PMemBase64 < 0x4A00) {
+ DEBUG((DEBUG_INFO, "PM size\n"));
+ return FALSE;
+ }
+ //
+ // Check bus range
+ //
+ if (BusRange < 106) {
+ DEBUG((DEBUG_INFO, "Bus range\n"));
+ return FALSE;
+ }
+ } else {
+ //
+ // Check mem size
+ //
+ if (MemLimit + 0x10 - MemBase < 0x1600) {
+ DEBUG((DEBUG_INFO, "M size\n"));
+ return FALSE;
+ }
+ //
+ // Check P-mem size
+ //
+ if (PMemLimit64 + 0x10 - PMemBase64 < 0x2200) {
+ DEBUG((DEBUG_INFO, "PM size\n"));
+ return FALSE;
+ }
+ //
+ // Check bus range
+ //
+ if (BusRange < 56) {
+ DEBUG((DEBUG_INFO, "Bus range\n"));
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+} // CheckLimits
+
+STATIC
+BOOLEAN
+InitHRResConfigs (
+ IN OUT HR_CONFIG *Hr_Config,
+ IN UINT8 BusNumLimit,
+ IN OUT BRDG_RES_CONFIG*HrResConf
+ )
+{
+ BRDG_CONFIG BrdgConf = { { 0 } };
+
+ InitCommonHRConfigs (Hr_Config, BusNumLimit, HrResConf);
+ BrdgConf.PBus = Hr_Config->HRBus + 2;// Take into account busses
+ BrdgConf.SBus = Hr_Config->HRBus + 3;// for US and DS of HIA
+ BrdgConf.SubBus = BusNumLimit;
+ BrdgConf.Res = *HrResConf;
+ while (TRUE) {
+ switch (Hr_Config->DeviceId) {
+ case AR_HR_4C:
+ case TR_HR_4C:
+ case AR_HR_C0_4C:
+ //
+ // 2 Port host
+ //
+ if (CheckLimits (TRUE, HrResConf, BusNumLimit - Hr_Config->HRBus)) {
+
+
+ InitARDSPort_2Port(&BrdgConf);
+ DEBUG((DEBUG_INFO, "AR2\n"));
+
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ // AR only
+ case AR_HR_2C: // 1 port host
+ case AR_HR_C0_2C:
+ case AR_HR_LP:
+ case TR_HR_2C:
+ DEBUG((DEBUG_INFO, "AR1\n"));
+ InitARDSPort_1Port(&BrdgConf);
+ return TRUE;
+
+ default:
+ InitHRDSPort_Disable (HR_DS_PORT3, &BrdgConf);
+ InitHRDSPort_Disable (HR_DS_PORT4, &BrdgConf);
+ InitHRDSPort_Disable (HR_DS_PORT5, &BrdgConf);
+ InitHRDSPort_Disable (HR_DS_PORT6, &BrdgConf);
+ return FALSE;
+ }
+ }
+} // InitHRResConfigs
+
+STATIC
+BOOLEAN
+InitializeHostRouter (
+ OUT HR_CONFIG *Hr_Config,
+ IN UINTN RpSegment,
+ IN UINTN RpBus,
+ IN UINTN RpDevice,
+ IN UINTN RpFunction
+ )
+{
+ UINT8 BusNumLimit;
+ BRDG_RES_CONFIG HrResConf = { 0 };
+ UINT8 i;
+ BOOLEAN Ret;
+
+ Ret = TRUE;
+
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0);
+ Hr_Config->HRBus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (RpSegment, Hr_Config->HRBus, 0x00, 0x00, 0);
+ Hr_Config->DeviceId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
+ if (!(IsTbtHostRouter (Hr_Config->DeviceId))) {
+ return FALSE;
+ }
+ TbtSegment = (UINT8)RpSegment;
+
+ HrResConf.Cmd = CMD_BM_MEM;
+ HrResConf.Cls = DEF_CACHE_LINE_SIZE;
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0);
+ HrResConf.IoBase = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase));
+ HrResConf.IoLimit = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit));
+ HrResConf.MemBase = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase));
+ HrResConf.MemLimit = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit));
+ HrResConf.PMemBase64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase));
+ HrResConf.PMemLimit64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit));
+ HrResConf.PMemBase64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32))) << 16;
+ HrResConf.PMemLimit64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32))) << 16;
+ BusNumLimit = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+
+ Ret = InitHRResConfigs (Hr_Config, BusNumLimit, &HrResConf);
+
+ for (i = 0; i < Hr_Config->BridgeLoops; ++i) {
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Fun;
+ Bus = HrConfigs[i].DevId.Bus;
+ Dev = HrConfigs[i].DevId.Dev;
+ Fun = HrConfigs[i].DevId.Fun;
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0);
+
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, HrConfigs[i].Res.Cls);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, HrConfigs[i].PBus);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, HrConfigs[i].SBus);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, HrConfigs[i].SubBus);
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), HrConfigs[i].Res.MemBase);
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), HrConfigs[i].Res.MemLimit);
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), (UINT16) (HrConfigs[i].Res.PMemBase64 & 0xFFFF));
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit), (UINT16) (HrConfigs[i].Res.PMemLimit64 & 0xFFFF));
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), (UINT32) (HrConfigs[i].Res.PMemBase64 >> 16));
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), (UINT32) (HrConfigs[i].Res.PMemLimit64 >> 16));
+ PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), HrConfigs[i].Res.IoBase);
+ PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit), HrConfigs[i].Res.IoLimit);
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBaseUpper16), 0x00000000);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, HrConfigs[i].Res.Cmd);
+ }
+ if (Hr_Config->DeviceId == AR_HR_2C || Hr_Config->DeviceId == AR_HR_4C || Hr_Config->DeviceId == AR_HR_LP) {
+ for (i = 0; i < Hr_Config->BridgeLoops; ++i) {
+ if(HrConfigs[i].IsDSBridge) {
+ UnsetVesc(HrConfigs[i].DevId.Bus, HrConfigs[i].DevId.Dev, HrConfigs[i].DevId.Fun);
+ }
+ }
+ }
+
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,(Hr_Config->HRBus + 2), 0x00, 0x00, 0);
+ PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX0 * 4), HrConfigs[HR_DS_PORT0].Res.MemLimit << 16);
+ PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX1 * 4), (HrConfigs[HR_DS_PORT0].Res.MemLimit + 0x4) << 16);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BM_MEM);
+ return Ret;
+} // InitializeHostRouter
+STATIC
+UINT8
+ConfigureSlot (
+ IN UINT8 Bus,
+ IN UINT8 MAX_DEVICE,
+ IN INT8 Depth,
+ IN BOOLEAN ArPcie,
+ IN OUT PORT_INFO *PortInfo
+ )
+{
+ UINT8 Device;
+ UINT8 SBus;
+ UINT8 UsedBusNumbers;
+ UINT8 RetBusNum;
+ PORT_INFO CurrentSlot;
+
+ RetBusNum = 0;
+
+ for (Device = 0; Device < MAX_DEVICE; Device++) {
+ //
+ // Continue if device is absent
+ //
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Device, 0x00, 0);
+ if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) {
+ continue;
+
+ }
+
+ if (P2P_BRIDGE != PciSegmentRead16 (gDeviceBaseAddress + (PCI_CLASSCODE_OFFSET + 1))) {
+ SetDevResources (
+ Bus,
+ Device,
+ PCI_MAX_FUNC,
+ PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX5 * 4),
+ PortInfo
+ );
+ continue;
+ }
+ //
+ // Else Bridge
+ //
+ CopyMem (&CurrentSlot, PortInfo, sizeof (PORT_INFO));
+
+ ++RetBusNum; // UP Bridge
+ SBus = Bus + RetBusNum; // DS Bridge
+
+ if (SBus + 1 >= PortInfo->BusNumLimit) {
+ continue;
+
+ }
+
+ SetDevResources (Bus, Device, 1, PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX1 * 4), PortInfo);
+
+ //
+ // Init UP Bridge to reach DS Bridge
+ //
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Bus);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, SBus);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, PortInfo->BusNumLimit);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BM_MEM);
+
+ if(ArPcie) {
+ UnsetVesc(Bus, Device, 0x00);
+ }
+
+ UsedBusNumbers = ConfigureSlot(SBus, PCI_MAX_DEVICE + 1, -1, FALSE, PortInfo);
+ RetBusNum += UsedBusNumbers;
+
+ SetPhyPortResources (
+ Bus,
+ Device,
+ SBus + UsedBusNumbers,
+ Depth,
+ &CurrentSlot,
+ PortInfo
+ );
+ }
+ //
+ // for (Device = 0; Device <= PCI_MAX_DEVICE; Device++)
+ //
+ return RetBusNum;
+} // ConfigureSlot
+
+STATIC
+VOID
+SetCioPortResources (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 SBus,
+ IN UINT8 SubBus,
+ IN PORT_INFO *portInfoBeforeChange,
+ IN OUT PORT_INFO *PortInfo
+ )
+{
+ UINT8 Cmd;
+ Cmd = CMD_BUS_MASTER;
+
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, 0x00, 0);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Bus);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, SBus);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, SubBus);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd);
+
+ if (PortInfo->IoBase <= PortInfo->IoLimit) {
+ PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), PortInfo->IoBase);
+ PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit), PortInfo->IoLimit);
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBaseUpper16), 0x00000000);
+ Cmd |= CMD_BM_IO;
+ } else {
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), DISBL_IO_REG1C);
+ }
+
+ if (PortInfo->MemBase <= PortInfo->MemLimit) {
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), PortInfo->MemBase);
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), PortInfo->MemLimit);
+ Cmd |= CMD_BM_MEM;
+ } else {
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), DISBL_MEM32_REG20);
+ }
+
+ if (PortInfo->PMemBase64 <= PortInfo->PMemLimit64) {
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), (UINT16) (PortInfo->PMemBase64 & 0xFFFF));
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit), (UINT16) (PortInfo->PMemLimit64 & 0xFFFF));
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), (UINT32) (PortInfo->PMemBase64 >> 16));
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), (UINT32) (PortInfo->PMemLimit64 >> 16));
+ Cmd |= CMD_BM_MEM;
+ } else {
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), DISBL_PMEM_REG24);
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), 0);
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), 0);
+ }
+
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE);
+} // SetCioPortResources
+
+STATIC
+VOID
+SetSlotsAsUnused (
+ IN UINT8 Bus,
+ IN UINT8 MaxSlotNum,
+ IN UINT8 CioSlot,
+ IN OUT PORT_INFO *PortInfo
+ )
+{
+ UINT8 Slot;
+ for (Slot = MaxSlotNum; Slot > CioSlot; --Slot) {
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Slot, 0x00, 0);
+ if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) {
+ continue;
+ }
+
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Bus);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, PortInfo->BusNumLimit);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, PortInfo->BusNumLimit);
+ PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), DISBL_IO_REG1C);
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), DISBL_MEM32_REG20);
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), DISBL_PMEM_REG24);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BUS_MASTER);
+ PortInfo->BusNumLimit--;
+ }
+} // SetSlotsAsUnused
+
+STATIC
+UINT16
+FindVendorSpecificHeader(
+ IN UINT8 Bus
+)
+{
+ PCI_EXP_EXT_HDR *ExtHdr;
+ UINT32 ExtHdrValue;
+ UINT16 ExtendedRegister;
+
+ ExtHdr = (PCI_EXP_EXT_HDR*) &ExtHdrValue;
+ ExtendedRegister = 0x100;
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, 0x00, 0x00, 0);
+ while (ExtendedRegister) {
+ ExtHdrValue = PciSegmentRead32 (gDeviceBaseAddress + ExtendedRegister);
+ if (ExtHdr->CapabilityId == 0xFFFF) {
+ return 0x0000; // No Vendor-Specific Extended Capability header
+ }
+
+ if (PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_ID == ExtHdr->CapabilityId) {
+ return ExtendedRegister;
+ }
+
+ ExtendedRegister = (UINT16) ExtHdr->NextCapabilityOffset;
+ }
+ return 0x0000; // No Vendor-Specific Extended Capability header
+}
+
+STATIC
+UINT8
+FindSsid_SsvidHeader (
+ IN UINT8 Bus
+ )
+{
+ UINT8 CapHeaderId;
+ UINT8 CapHeaderOffset;
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, 0x00, 0x00, 0);
+ CapHeaderOffset = PciSegmentRead8 (gDeviceBaseAddress + PCI_CAPBILITY_POINTER_OFFSET);
+
+ while (CapHeaderOffset != 0) {
+ CapHeaderId = PciSegmentRead8 (gDeviceBaseAddress + CapHeaderOffset);
+
+ if (CapHeaderId == PCIE_CAP_ID_SSID_SSVID) {
+ return CapHeaderOffset;
+ }
+
+ CapHeaderOffset = PciSegmentRead8 (gDeviceBaseAddress + CapHeaderOffset + 1);
+ }
+
+ DEBUG((DEBUG_INFO, "SID0\n"));
+ return 0;
+} // FindSsid_SsvidHeader
+
+STATIC
+BOOLEAN
+GetCioSlotByDevId (
+ IN UINT8 Bus,
+ OUT UINT8 *CioSlot,
+ OUT UINT8 *MaxSlotNum,
+ OUT BOOLEAN *ArPcie
+ )
+{
+ UINT16 VSECRegister;
+ BRDG_CIO_MAP_REG BridgMap;
+ UINT32 BitScanRes;
+ UINT16 DevId;
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, 0x00, 0x00, 0);
+ DevId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ //
+ // Init out params in case device is not recognised
+ //
+ *CioSlot = 4;
+ *MaxSlotNum = 7;
+ *ArPcie = FALSE;
+
+ switch (DevId) {
+ //
+ // For known device IDs
+ //
+ case 0x1578:
+ *ArPcie = TRUE;
+ }
+
+ switch (DevId) {
+ //
+ // For known device IDs
+ //
+ case 0x1513:
+ case 0x151A:
+ case 0x151B:
+ case 0x1547:
+ case 0x1548:
+ return TRUE; // Just return
+ case 0x1549:
+ return FALSE; // Just return
+ }
+
+ VSECRegister = FindVendorSpecificHeader(Bus);
+ if (!VSECRegister) {
+ return TRUE; // Just return
+ }
+ //
+ // Go to Bridge/CIO map register
+ //
+ VSECRegister += 0x18;
+ BridgMap.AB_REG = PciSegmentRead32(gDeviceBaseAddress + VSECRegister);
+ //
+ // Check for range
+ //
+ if (BridgMap.Bits.NumOfDSPorts < 1 || BridgMap.Bits.NumOfDSPorts > 27) {
+ return TRUE;
+ //
+ // Not a valid register
+ //
+ }
+ //
+ // Set OUT params
+ //
+ *MaxSlotNum = (UINT8) BridgMap.Bits.NumOfDSPorts;
+
+#ifdef _MSC_VER
+ if(!_BitScanForward(&BitScanRes, BridgMap.Bits.CioPortMap)) { // No DS bridge which is CIO port
+ return FALSE;
+ }
+#else
+#ifdef __GNUC__
+ if (BridgMap.Bits.CioPortMap == 0) {
+ return FALSE;
+ }
+ BitScanRes = __builtin_ctz (BridgMap.Bits.CioPortMap);
+#else
+#error Unsupported Compiler
+#endif
+#endif
+
+ *CioSlot = (UINT8)BitScanRes;
+ return TRUE;
+} // GetCioSlotByDevId
+
+#define TBT_LEGACY_SUB_SYS_ID 0x11112222
+
+STATIC
+BOOLEAN
+IsLegacyDevice (
+ IN UINT8 Bus
+ )
+{
+ UINT32 Sid;
+ UINT8 SidRegister;
+ UINT16 DevId;
+
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, 0x00, 0x00, 0);
+ DevId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
+ switch (DevId) {
+ //
+ // For known device IDs
+ //
+ case 0x1513:
+ case 0x151A:
+ case 0x151B:
+ DEBUG((DEBUG_INFO, "Legacy "));
+ DEBUG((DEBUG_INFO, "DevId = %d\n",DevId));
+ return TRUE;
+ //
+ // Legacy device by Device Id
+ //
+ }
+
+ SidRegister = FindSsid_SsvidHeader(Bus);
+
+ if (!SidRegister) {
+ return TRUE; // May be absent for legacy devices
+ }
+ //
+ // Go to register
+ //
+ SidRegister += 0x4;
+ Sid = PciSegmentRead32(gDeviceBaseAddress + SidRegister);
+ DEBUG((DEBUG_INFO, "SID"));
+ DEBUG((DEBUG_INFO, " = %d\n", Sid));
+
+return TBT_LEGACY_SUB_SYS_ID == Sid || 0 == Sid;
+} // IsLegacyDevice
+
+STATIC
+VOID
+UnsetVescEp(
+ IN UINT8 Bus,
+ IN UINT8 MaxSlotNum
+ )
+{
+ UINT8 i;
+
+ for (i = 0; i <= MaxSlotNum; ++i)
+ {
+ UnsetVesc(Bus, i, 0);
+ }
+}// Unset_VESC_REG2_EP
+
+STATIC
+BOOLEAN
+ConfigureEP (
+ IN INT8 Depth,
+ IN OUT UINT8 *Bus,
+ IN OUT PORT_INFO *PortInfo
+ )
+{
+ UINT8 SBus;
+ UINT8 CioSlot;
+ UINT8 MaxSlotNum;
+ BOOLEAN ArPcie;
+ UINT8 MaxPHYSlots;
+ UINT8 UsedBusNumbers;
+ UINT8 cmd;
+ BOOLEAN CioSlotPresent;
+ BOOLEAN Continue;
+ PORT_INFO PortInfoOrg;
+ UINT8 CioBus;
+
+ CioSlot = 4;
+ MaxSlotNum = 7;
+ CopyMem (&PortInfoOrg, PortInfo, sizeof (PORT_INFO));
+
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, *Bus, 0x00, 0x00, 0);
+ cmd = PciSegmentRead8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET);
+ // AR ONLY
+ // Endpoint on CIO slot, but not a bridge device
+ if (P2P_BRIDGE != PciSegmentRead16 (gDeviceBaseAddress + (PCI_CLASSCODE_OFFSET + 1))) {
+ DEBUG((DEBUG_INFO, "UEP\n"));
+ // Check whether EP already configured by examining CMD register
+ if(cmd & CMD_BUS_MASTER) // Yes, no need to touch this EP
+ {
+ DEBUG((DEBUG_INFO, "BMF\n"));
+ return FALSE;
+ }
+ // Configure it as regular PCIe device
+ ConfigureSlot(*Bus, PCI_MAX_DEVICE + 1, -1, FALSE, PortInfo);
+
+ return FALSE;
+ }
+
+ //
+ // Based on Device ID assign Cio slot and max number of PHY slots to scan
+ //
+ CioSlotPresent = GetCioSlotByDevId(*Bus, &CioSlot, &MaxSlotNum, &ArPcie);
+ MaxPHYSlots = MaxSlotNum;
+ //
+ // Check whether EP already configured by examining CMD register
+ //
+
+ if (cmd & CMD_BUS_MASTER) {
+ //
+ // Yes no need to touch this EP, just move to next one in chain
+ //
+ CioBus = *Bus + 1;
+ if(ArPcie){
+ UnsetVescEp(CioBus, MaxSlotNum);
+ }
+ if (!CioSlotPresent) {
+ //
+ // Cio slot is not present in EP, just return FALSE
+ //
+ DEBUG((DEBUG_INFO, "BMF\n"));
+ return FALSE;
+ }
+ //
+ // Take all resources from Cio slot and return
+ //
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,CioBus, CioSlot, 0x00, 0);
+ PortInfo->BusNumLimit = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ PortInfo->IoBase = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase));
+ PortInfo->IoLimit = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit));
+ PortInfo->MemBase = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase));
+ PortInfo->MemLimit = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit));
+ PortInfo->PMemBase64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase)) & 0xFFF0;
+ PortInfo->PMemLimit64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit)) & 0xFFF0;
+ PortInfo->PMemBase64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32))) << 16;
+ PortInfo->PMemLimit64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32))) << 16;
+ PortInfo->PMemLimit64 |= 0xF;
+ //
+ // Jump to next EP
+ //
+ *Bus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ //
+ // Should we continue?
+ //
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,*Bus, 0x00, 0x00, 0);
+ Continue = 0xFFFF != PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
+ return Continue;
+ }
+ //
+ // Set is legacy dvice
+ //
+ isLegacyDevice = IsLegacyDevice (*Bus);
+
+ SetCioPortResources (
+ *Bus,
+ 0, // Assign all available resources to US port of EP
+ *Bus + 1,
+ PortInfo->BusNumLimit,
+ 0,
+ PortInfo
+ );
+
+ SBus = *Bus + 1;// Jump to DS port
+
+ if (CioSlotPresent) {
+ MaxPHYSlots = CioSlot;
+ }
+
+ UsedBusNumbers = ConfigureSlot(SBus, MaxPHYSlots, Depth, ArPcie, PortInfo);
+ if (!CioSlotPresent) {
+ return FALSE;
+ //
+ // Stop resource assignment on this chain
+ //
+ }
+ //
+ // Set rest of slots us unused
+ //
+ SetSlotsAsUnused (SBus, MaxSlotNum, CioSlot, PortInfo);
+
+ SetCioPortResources (
+ SBus,
+ CioSlot,
+ SBus + UsedBusNumbers + 1,
+ PortInfo->BusNumLimit,
+ &PortInfoOrg,
+ PortInfo
+ );
+ *Bus = SBus + UsedBusNumbers + 1;// Go to next EP
+ if(ArPcie) {
+ UnsetVesc(SBus, CioSlot, 0x00);
+ }
+ if (*Bus > PortInfo->BusNumLimit - 2) {
+ //
+ // In case of bus numbers are exhausted stop enumeration
+ //
+ return FALSE;
+ }
+ //
+ // Check whether we should continue on this chain
+ //
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,*Bus, 0x00, 0x00, 0);
+ Continue = 0xFFFF != PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
+ return Continue;
+} // ConfigureEP
+
+STATIC
+VOID
+GetPortResources (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Fun,
+ IN OUT PORT_INFO *PortInfo
+ )
+{
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0);
+ PortInfo->BusNumLimit = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ PortInfo->IoBase = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase)) & 0xF0;
+ PortInfo->IoLimit = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit)) & 0xF0;
+ PortInfo->MemBase = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase)) & 0xFFF0;
+ PortInfo->MemLimit = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit)) & 0xFFF0;
+ PortInfo->PMemBase64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase)) & 0xFFF0;
+ PortInfo->PMemLimit64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit)) & 0xFFF0;
+ PortInfo->PMemBase64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32))) << 16;
+ PortInfo->PMemLimit64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32))) << 16;
+ PortInfo->IoLimit |= 0xF;
+ PortInfo->MemLimit |= 0xF;
+ PortInfo->PMemLimit64 |= 0xF;
+} // GetPortResources
+
+STATIC
+VOID
+ConfigurePort (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Fun,
+ IN OUT PORT_INFO *PortInfo
+ )
+{
+ INT8 i;
+ UINT8 USBusNum;
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0);
+ USBusNum = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, USBusNum, 0x00, 0x00, 0);
+ if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) {
+ //
+ // Nothing to do if TBT device is not connected
+ //
+ return ;
+ }
+
+ GetPortResources(Bus, Dev, Fun, PortInfo);// Take reserved resources from DS port
+ //
+ // Assign resources to EPs
+ //
+ for (i = 0; i < MAX_TBT_DEPTH; ++i) {
+ PortInfo->ConfedEP++;
+ if (!ConfigureEP (i, &USBusNum, PortInfo)) {
+ return ;
+ }
+ }
+} // ConfigurePort
+
+VOID
+ThunderboltCallback (
+ IN UINT8 Type
+ )
+{
+ PORT_INFO PortInfoOrg = { 0 };
+ HR_CONFIG HrConfig = { 0 };
+ UINT8 i;
+ UINTN Segment = 0;
+ UINTN Bus = 0;
+ UINTN Device;
+ UINTN Function;
+
+ DEBUG((DEBUG_INFO, "ThunderboltCallback.Entry\n"));
+
+ DEBUG((DEBUG_INFO, "PortInfo Initialization\n"));
+ PortInfoInit (&PortInfoOrg);
+ if(Type == DTBT_CONTROLLER) {
+ if (gCurrentDiscreteTbtRootPort == 0) {
+ DEBUG((DEBUG_ERROR, "Invalid RP Input\n"));
+ return;
+ }
+ GetDTbtRpDevFun(gCurrentDiscreteTbtRootPortType, gCurrentDiscreteTbtRootPort - 1, &Device, &Function);
+ DEBUG((DEBUG_INFO, "InitializeHostRouter. \n"));
+ if (!InitializeHostRouter (&HrConfig, Segment, Bus, Device, Function)) {
+ return ;
+ }
+ //
+ // Configure DS ports
+ //
+ for (i = HrConfig.MinDSNumber; i <= HrConfig.MaxDSNumber; ++i) {
+ DEBUG((DEBUG_INFO, "ConfigurePort. \n"));
+ ConfigurePort (HrConfig.HRBus + 1, i,0, &PortInfoOrg);
+ }
+
+ DEBUG((DEBUG_INFO, "EndOfThunderboltCallback.\n"));
+ EndOfThunderboltCallback (Segment, Bus, Device, Function);
+
+ }
+ DEBUG((DEBUG_INFO, "ThunderboltCallback.Exit\n"));
+} // ThunderboltCallback
+
+VOID
+DisablePCIDevicesAndBridges (
+ IN UINT8 MinBus,
+ IN UINT8 MaxBus
+ )
+{
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Fun;
+ UINT8 RegVal;
+ //
+ // Disable PCI device First, and then Disable PCI Bridge
+ //
+ for (Bus = MaxBus; Bus > MinBus; --Bus) {
+ for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
+ for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0);
+ if (INVALID_PCI_DEVICE == PciSegmentRead32 (gDeviceBaseAddress + PCI_VENDOR_ID_OFFSET)) {
+ if (Fun == 0) {
+ break;
+
+ }
+
+ continue;
+ }
+
+ RegVal = PciSegmentRead8 (gDeviceBaseAddress + PCI_HEADER_TYPE_OFFSET);
+ if (HEADER_TYPE_DEVICE == (RegVal & 1)) {
+ //
+ // ******** Disable PCI Device ********
+ // BIT0 I/O Space Enabled BIT1 Memory Space Enabled
+ // BIT2 Bus Master Enabled BIT4 Memory Write and Invalidation Enable
+ //
+ PciSegmentAnd8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, (UINT8)~(BIT0 | BIT1 | BIT2 | BIT4));
+ PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX0 * 4), 0);
+ PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX1 * 4), 0);
+ PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX2 * 4), 0);
+ PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX3 * 4), 0);
+ PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX4 * 4), 0);
+ PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX5 * 4), 0);
+ }
+ }
+ }
+ }
+ //
+ // now no more PCI dev on another side of PCI Bridge can safty disable PCI Bridge
+ //
+ for (Bus = MaxBus; Bus > MinBus; --Bus) {
+ for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
+ for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0);
+ if (INVALID_PCI_DEVICE == PciSegmentRead32 (gDeviceBaseAddress + PCI_VENDOR_ID_OFFSET)) {
+ if (Fun == 0) {
+ break;
+ }
+
+ continue;
+ }
+
+ RegVal = PciSegmentRead8 (gDeviceBaseAddress + PCI_HEADER_TYPE_OFFSET);
+ if (HEADER_TYPE_PCI_TO_PCI_BRIDGE == (RegVal & BIT0)) {
+ PciSegmentAnd8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, (UINT8)~(BIT0 | BIT1 | BIT2 | BIT4));
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, 0);
+ PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 0);
+ PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), 0);
+ }
+ } // for ( Fun .. )
+ } // for ( Dev ... )
+ } // for ( Bus ... )
+} // DisablePCIDevicesAndBridges
+
+VOID
+TbtDisablePCIDevicesAndBridges (
+ IN UINT8 Type
+ )
+{
+ UINTN Segment = 0;
+ UINTN Bus = 0;
+ UINTN Device;
+ UINTN Function;
+ UINT8 MinBus;
+ UINT8 MaxBus;
+ UINT16 DeviceId;
+
+ MinBus = 1;
+ if(Type == DTBT_CONTROLLER) {
+ //
+ // for(Dev = 0; Dev < 8; ++Dev)
+ // {
+ // PciOr8(PCI_LIB_ADDRESS(2, Dev, 0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET), 0x40);
+ // gBS->Stall(2000); // 2msec
+ // PciAnd8(PCI_LIB_ADDRESS(2, Dev, 0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET), 0xBF);
+ // }
+ // gBS->Stall(200 * 1000); // 200 msec
+ //
+ if (gCurrentDiscreteTbtRootPort == 0) {
+ DEBUG((DEBUG_ERROR, "Invalid RP Input\n"));
+ return;
+ }
+ GetDTbtRpDevFun(gCurrentDiscreteTbtRootPortType, gCurrentDiscreteTbtRootPort - 1, &Device, &Function);
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0);
+ MinBus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ MaxBus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (Segment, MinBus, 0x00, 0x00, 0);
+ DeviceId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
+ if (!(IsTbtHostRouter (DeviceId))) {
+ return;
+ }
+ TbtSegment = (UINT8)Segment;
+ MinBus++;
+ //
+ // @todo : Move this out when we dont have Loop for ITBT
+ //
+ DisablePCIDevicesAndBridges(MinBus, MaxBus);
+
+ }
+} // DisablePCIDevicesAndBridges
+
+
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmiHandler.h b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmiHandler.h
new file mode 100644
index 0000000000..22f6aeeb7f
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmiHandler.h
@@ -0,0 +1,185 @@
+/**@file
+
+Copyright (c) 2018, Intel Corporation. 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 _TBT_SMI_HANDLER_H_
+#define _TBT_SMI_HANDLER_H_
+
+#include <Library/TbtCommonLib.h>
+#include <Library/IoLib.h>
+#include <IndustryStandard/Pci.h>
+
+#ifdef PROGRESS_CODE
+#undef PROGRESS_CODE
+#endif
+
+#define MAX_TBT_DEPTH 6
+
+#define P2P_BRIDGE (((PCI_CLASS_BRIDGE) << 8) | (PCI_CLASS_BRIDGE_P2P))
+
+#define BAR_ALIGN(v, a) ((((v) - 1) | (a)) + 1)
+
+#define CMD_BUS_MASTER BIT2
+#define CMD_BM_IO (CMD_BUS_MASTER | BIT0)
+#define CMD_BM_MEM (CMD_BUS_MASTER | BIT1)
+#define CMD_BM_MEM_IO (CMD_BUS_MASTER | BIT1 | BIT0)
+
+#define DEF_CACHE_LINE_SIZE 0x20
+#define DEF_RES_IO_PER_DEV 4
+#define DEF_RES_MEM_PER_DEV 32
+#define DEF_RES_PMEM_PER_DEV 32
+
+#define DOCK_BUSSES 8
+
+#define DISBL_IO_REG1C 0x01F1
+#define DISBL_MEM32_REG20 0x0000FFF0
+#define DISBL_PMEM_REG24 0x0001FFF1
+
+#define count(x) (sizeof (x) / sizeof ((x)[0]))
+
+#define PCIE_CAP_ID_SSID_SSVID 0x0D
+#define INVALID_PCI_DEVICE 0xFFFFFFFF
+#define PCI_TBT_VESC_REG2 0x510
+
+typedef struct _PortInfo {
+ UINT8 IoBase;
+ UINT8 IoLimit;
+ UINT16 MemBase;
+ UINT16 MemLimit;
+ UINT64 PMemBase64;
+ UINT64 PMemLimit64;
+ UINT8 BusNumLimit;
+ UINT8 ConfedEP;
+} PORT_INFO;
+
+typedef struct _MEM_REGS {
+ UINT32 Base;
+ UINT32 Limit;
+} MEM_REGS;
+
+typedef struct _PMEM_REGS {
+ UINT64 Base64;
+ UINT64 Limit64;
+} PMEM_REGS;
+
+typedef struct _IO_REGS {
+ UINT16 Base;
+ UINT16 Limit;
+} IO_REGS;
+
+typedef struct _BRDG_RES_CONFIG {
+ UINT8 Cmd;
+ UINT8 Cls;
+ UINT8 IoBase;
+ UINT8 IoLimit;
+ UINT16 MemBase;
+ UINT16 MemLimit;
+ UINT64 PMemBase64;
+ UINT64 PMemLimit64;
+} BRDG_RES_CONFIG;
+
+typedef struct _BRDG_CONFIG {
+ DEV_ID DevId;
+ UINT8 PBus;
+ UINT8 SBus;
+ UINT8 SubBus;
+ BOOLEAN IsDSBridge;
+ BRDG_RES_CONFIG Res;
+} BRDG_CONFIG;
+
+enum {
+ HR_US_PORT,
+ HR_DS_PORT0,
+ HR_DS_PORT3,
+ HR_DS_PORT4,
+ HR_DS_PORT5,
+ HR_DS_PORT6,
+ MAX_CFG_PORTS
+};
+
+enum {
+ HR_DS_PORT1 = HR_DS_PORT3
+};
+
+//
+// Alpine Ridge
+//
+enum {
+ AR_DS_PORT1 = HR_DS_PORT3,
+ AR_DS_PORT2,
+ AR_DS_PORT3,
+ AR_DS_PORT4
+};
+
+typedef struct _HR_CONFIG {
+ UINT16 DeviceId;
+ UINT8 HRBus;
+ UINT8 MinDSNumber;
+ UINT8 MaxDSNumber;
+ UINT8 BridgeLoops;
+} HR_CONFIG;
+
+STATIC const BRDG_RES_CONFIG NOT_IN_USE_BRIDGE = {
+ CMD_BUS_MASTER,
+ 0,
+ DISBL_IO_REG1C & 0xFF,
+ DISBL_IO_REG1C >> 8,
+ DISBL_MEM32_REG20 & 0xFFFF,
+ DISBL_MEM32_REG20 >> 16,
+ DISBL_PMEM_REG24 & 0xFFFF,
+ DISBL_PMEM_REG24 >> 16
+};
+
+typedef union _BRDG_CIO_MAP_REG {
+ UINT32 AB_REG;
+ struct {
+ UINT32 NumOfDSPorts : 5;
+ UINT32 CioPortMap : 27;
+ } Bits;
+} BRDG_CIO_MAP_REG;
+
+//
+// Functions
+//
+VOID
+ThunderboltCallback (
+ IN UINT8 Type
+ );
+
+VOID
+TbtDisablePCIDevicesAndBridges (
+ IN UINT8 Type
+ );
+
+VOID
+EndOfThunderboltCallback(
+ IN UINTN RpSegment,
+ IN UINTN RpBus,
+ IN UINTN RpDevice,
+ IN UINTN RpFunction
+);
+
+VOID
+ConfigureTbtAspm(
+ IN UINT8 Type,
+ IN UINT16 Aspm
+);
+
+UINT8
+PcieFindCapId (
+ IN UINT8 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ );
+
+#endif
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmm.c b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmm.c
new file mode 100644
index 0000000000..f2abfb0db9
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmm.c
@@ -0,0 +1,1771 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. 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.
+
+**/
+
+//
+// Module specific Includes
+//
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/GpioLib.h>
+#include <TbtBoardInfo.h>
+#include <Protocol/TbtNvsArea.h>
+#include <PchAccess.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/IoLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Uefi/UefiSpec.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Guid/HobList.h>
+#include "TbtSmiHandler.h"
+#include <PcieRegs.h>
+#include <Protocol/SaPolicy.h>
+#include <Protocol/DxeTbtPolicy.h>
+#include <Library/PchPmcLib.h>
+#define P2P_BRIDGE (((PCI_CLASS_BRIDGE) << 8) | (PCI_CLASS_BRIDGE_P2P))
+
+#define CMD_BM_MEM_IO (CMD_BUS_MASTER | BIT1 | BIT0)
+
+#define DISBL_IO_REG1C 0x01F1
+#define DISBL_MEM32_REG20 0x0000FFF0
+#define DISBL_PMEM_REG24 0x0001FFF1
+
+#define DOCK_BUSSES 8
+
+#define PCI_CAPABILITY_ID_PCIEXP 0x10
+#define PCI_CAPBILITY_POINTER_OFFSET 0x34
+
+#define LTR_MAX_SNOOP_LATENCY_VALUE 0x0846 ///< Intel recommended maximum value for Snoop Latency can we put like this ?
+#define LTR_MAX_NON_SNOOP_LATENCY_VALUE 0x0846 ///< Intel recommended maximum value for Non-Snoop Latency can we put like this ?
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED TBT_NVS_AREA *mTbtNvsAreaPtr;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 gCurrentDiscreteTbtRootPort;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 gCurrentDiscreteTbtRootPortType;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 TbtLtrMaxSnoopLatency;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 TbtLtrMaxNoSnoopLatency;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 gDTbtPcieRstSupport;
+GLOBAL_REMOVE_IF_UNREFERENCED TBT_INFO_HOB *gTbtInfoHob = NULL;
+STATIC UINTN mPciExpressBaseAddress;
+STATIC UINT8 TbtSegment = 0;
+VOID
+GpioWrite (
+ IN UINT32 GpioNumber,
+ IN BOOLEAN Value
+ )
+{
+ GpioSetOutputValue (GpioNumber, (UINT32)Value);
+}
+
+/**
+ 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
+ @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;
+ UINT64 DeviceBase;
+
+ DeviceBase = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Device, Function, 0);
+
+ ///
+ /// 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 = 0x100;
+ while (CapHeaderOffset != 0 && CapHeaderId != 0xFFFF) {
+ CapHeaderId = PciSegmentRead16 (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 = (PciSegmentRead16 (DeviceBase + CapHeaderOffset + 2) >> 4) & ((UINT16) ~(BIT0 | BIT1));
+ }
+
+ return 0;
+}
+
+/**
+ 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 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ )
+{
+ UINT8 CapHeaderOffset;
+ UINT8 CapHeaderId;
+ UINT64 DeviceBase;
+
+ DeviceBase = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0);
+
+ if ((PciSegmentRead8 (DeviceBase + PCI_PRIMARY_STATUS_OFFSET) & EFI_PCI_STATUS_CAPABILITY) == 0x00) {
+ ///
+ /// Function has no capability pointer
+ ///
+ return 0;
+ }
+
+ ///
+ /// Check the header layout to determine the Offset of Capabilities Pointer Register
+ ///
+ if ((PciSegmentRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) {
+ ///
+ /// If CardBus bridge, start at Offset 0x14
+ ///
+ CapHeaderOffset = 0x14;
+ } else {
+ ///
+ /// Otherwise, start at Offset 0x34
+ ///
+ CapHeaderOffset = 0x34;
+ }
+ ///
+ /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
+ ///
+ CapHeaderId = 0;
+ CapHeaderOffset = PciSegmentRead8 (DeviceBase + CapHeaderOffset) & ((UINT8) ~(BIT0 | BIT1));
+ while (CapHeaderOffset != 0 && CapHeaderId != 0xFF) {
+ CapHeaderId = PciSegmentRead8 (DeviceBase + CapHeaderOffset);
+ if (CapHeaderId == CapId) {
+ return CapHeaderOffset;
+ }
+ ///
+ /// 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 = PciSegmentRead8 (DeviceBase + CapHeaderOffset + 1) & ((UINT8) ~(BIT0 | BIT1));
+ }
+
+ return 0;
+}
+/**
+ 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 UINTN DeviceBase,
+ IN UINT16 L1SubstateExtCapOffset,
+ IN UINT32 PortL1SubstateCapSupport,
+ IN UINT32 PortCommonModeRestoreTime,
+ IN UINT32 PortTpowerOnValue,
+ IN UINT32 PortTpowerOnScale,
+ IN UINT16 MaxLevel
+ )
+{
+
+ PciSegmentAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(0xFF00),
+ (UINT32) PortCommonModeRestoreTime << 8
+ );
+
+ PciSegmentAnd32(DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL2_OFFSET, 0xFFFFFF04);
+
+ PciSegmentOr32(DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL2_OFFSET,(UINT32) ((PortTpowerOnValue << N_PCIE_EX_L1SCTL2_POWT) | PortTpowerOnScale));
+
+ PciSegmentAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(0xE3FF0000),
+ (UINT32) (BIT30 | BIT23 | BIT21)
+ );
+
+}
+
+VOID
+RootportL1sSupport (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Fun,
+ IN UINT16 RootL1SubstateExtCapOffset,
+ IN UINT16 MaxL1Level
+ )
+{
+ UINTN ComponentABaseAddress;
+ UINTN ComponentBBaseAddress;
+ UINT8 SecBus;
+ UINT32 PortL1SubstateCapSupport;
+ UINT32 PortCommonModeRestoreTime;
+ UINT32 PortTpowerOnValue;
+ UINT32 PortTpowerOnScale;
+ UINT16 ComponentBL1SubstateExtCapOffset;
+ UINT32 ComponentBL1Substates;
+ UINT32 ComponentBCommonModeRestoreTime;
+ UINT32 ComponentBTpowerOnValue;
+ UINT32 ComponentBTpowerOnScale;
+ UINT32 Data32;
+
+ PortL1SubstateCapSupport = 0;
+ PortCommonModeRestoreTime = 0;
+ PortTpowerOnValue = 0;
+ PortTpowerOnScale = 0;
+ Data32 = 0;
+
+ ComponentABaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ if (RootL1SubstateExtCapOffset != 0) {
+ Data32 = PciSegmentRead32 (ComponentABaseAddress + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ PortL1SubstateCapSupport = (Data32) & 0x0F;
+ PortCommonModeRestoreTime = (Data32 >> 8) & 0xFF;
+ PortTpowerOnScale = (Data32 >> 16) & 0x3;
+ PortTpowerOnValue = (Data32 >> 19) & 0x1F;
+ } else {
+ MaxL1Level = 0; // If L1 Substates from Root Port side is disable, then Disable from Device side also.
+ }
+
+ SecBus = PciSegmentRead8 (ComponentABaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ ComponentBBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, SecBus, 0, 0, 0);
+
+ if (PciSegmentRead16 (ComponentBBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ ComponentBL1SubstateExtCapOffset = PcieFindExtendedCapId (
+ SecBus,
+ 0,
+ 0,
+ V_PCIE_EX_L1S_CID
+ );
+ if (ComponentBL1SubstateExtCapOffset != 0) {
+ ComponentBL1Substates = PciSegmentRead32 (ComponentBBaseAddress + ComponentBL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ ComponentBCommonModeRestoreTime = (ComponentBL1Substates >> 8) & 0xFF;
+ ComponentBTpowerOnScale = (ComponentBL1Substates >> 16) & 0x3;
+ ComponentBTpowerOnValue = (ComponentBL1Substates >> 19) & 0x1F;
+
+ if (MaxL1Level == 3) {
+ if (Data32 >= ComponentBL1Substates) {
+ if (~(Data32 | BIT2)) {
+ MaxL1Level = 1;
+ }
+ }
+ else {
+ if (~(ComponentBL1Substates | BIT2)) {
+ MaxL1Level = 1;
+ }
+ }
+ }
+
+ if (MaxL1Level == 3) {
+ ConfigureL1s (
+ ComponentABaseAddress,
+ RootL1SubstateExtCapOffset,
+ PortL1SubstateCapSupport,
+ ComponentBCommonModeRestoreTime,
+ ComponentBTpowerOnValue,
+ ComponentBTpowerOnScale,
+ MaxL1Level
+ );
+
+ ConfigureL1s (
+ ComponentBBaseAddress,
+ ComponentBL1SubstateExtCapOffset,
+ ComponentBL1Substates,
+ PortCommonModeRestoreTime,
+ PortTpowerOnValue,
+ PortTpowerOnScale,
+ MaxL1Level
+ );
+ }
+
+ if (MaxL1Level == 1) {
+ PciSegmentOr32 (
+ ComponentABaseAddress + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) (BIT3 | BIT1)
+ );
+
+ PciSegmentOr32 (
+ ComponentBBaseAddress + ComponentBL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) (BIT3 | BIT1)
+ );
+ }
+ else {
+ if (RootL1SubstateExtCapOffset != 0) {
+ PciSegmentOr32 (
+ ComponentABaseAddress + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) (BIT3 | BIT1)
+ );
+
+ PciSegmentOr32 (
+ ComponentABaseAddress + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) (BIT2 | BIT0)
+ );
+ }
+ if (ComponentBL1SubstateExtCapOffset != 0) {
+ PciSegmentOr32 (
+ ComponentBBaseAddress + ComponentBL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) (BIT3 | BIT1)
+ );
+
+ PciSegmentOr32 (
+ ComponentBBaseAddress + ComponentBL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) (BIT2 | BIT0)
+ );
+ }
+ }
+ }
+ }
+}
+
+VOID
+MultiFunctionDeviceAspm (
+ IN UINT8 Bus,
+ IN UINT8 Dev
+ )
+{
+ UINT16 LowerAspm;
+ UINT16 AspmVal;
+ UINT8 Fun;
+ UINT64 DeviceBaseAddress;
+ UINT8 CapHeaderOffset;
+
+ LowerAspm = 3; // L0s and L1 Supported
+ for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
+ //
+ // Check for Device availability
+ //
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ // Device not present
+ continue;
+ }
+
+ CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Dev, Fun, 0x10);
+
+ AspmVal = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x00C) >> 10) & 3;
+ if (LowerAspm > AspmVal) {
+ LowerAspm = AspmVal;
+ }
+ } //Fun
+
+ for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
+ //
+ // Check for Device availability
+ //
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ //
+ // Device not present
+ //
+ continue;
+ }
+
+ CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Dev, Fun, 0x10);
+
+ PciSegmentAndThenOr16 (DeviceBaseAddress + CapHeaderOffset + 0x10, 0xFFFC, LowerAspm);
+ } //Fun
+}
+
+UINT16
+LimitAspmLevel (
+ IN UINT16 SelectedAspm,
+ IN UINT16 MaxAspmLevel
+ )
+{
+ SelectedAspm = SelectedAspm & MaxAspmLevel;
+
+ return SelectedAspm;
+}
+
+UINT16
+FindOptimalAspm (
+ IN UINT16 ComponentAaspm,
+ IN UINT16 ComponentBaspm
+ )
+{
+ UINT16 SelectedAspm;
+
+ SelectedAspm = ComponentAaspm & ComponentBaspm;
+
+ return SelectedAspm;
+}
+
+UINT16
+FindComponentBaspm (
+ IN UINT8 Bus,
+ IN UINT8 MaxBus
+ )
+{
+ UINT8 BusNo;
+ UINT8 DevNo;
+ UINT8 FunNo;
+ UINT64 DevBaseAddress;
+ UINT8 RegVal;
+ UINT8 SecBusNo;
+ UINT16 SelectedAspm; // No ASPM Support
+ UINT8 CapHeaderOffset_B;
+ BOOLEAN AspmFound;
+
+ SelectedAspm = 0;
+ AspmFound = FALSE;
+
+ for (BusNo = MaxBus; (BusNo != 0xFF) && (!AspmFound); --BusNo) {
+ for (DevNo = 0; (DevNo <= PCI_MAX_DEVICE) && (!AspmFound); ++DevNo) {
+ for (FunNo = 0; (FunNo <= PCI_MAX_FUNC) && (!AspmFound); ++FunNo) {
+ //
+ // Check for Device availability
+ //
+ DevBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, BusNo, DevNo, FunNo, 0);
+ if (PciSegmentRead16 (DevBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ //
+ // Device not present
+ //
+ continue;
+ }
+
+ RegVal = PciSegmentRead8 (DevBaseAddress + PCI_HEADER_TYPE_OFFSET);
+ if ((RegVal & (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6)) != 0x01) {
+ //
+ // Not a PCI-to-PCI bridges device
+ //
+ continue;
+ }
+
+ SecBusNo = PciSegmentRead8 (DevBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+
+ if (SecBusNo == Bus) {
+ //
+ // This is the Rootbridge for the given 'Bus' device
+ //
+ CapHeaderOffset_B = PcieFindCapId (TbtSegment, BusNo, DevNo, FunNo, 0x10);
+ SelectedAspm = (PciSegmentRead16 (DevBaseAddress + CapHeaderOffset_B + 0x00C) >> 10) & 3;
+ AspmFound = TRUE;
+ }
+ } //FunNo
+ } //DevNo
+ } //BusNo
+
+ return (SelectedAspm);
+}
+
+VOID
+NoAspmSupport (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Fun,
+ IN UINT8 CapHeaderOffset
+ )
+{
+ UINT64 DeviceBaseAddress;
+
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ PciSegmentAndThenOr16 (DeviceBaseAddress + CapHeaderOffset + 0x10, 0xFFFC, 0x00);
+}
+
+VOID
+EndpointAspmSupport (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Fun,
+ IN UINT8 CapHeaderOffset,
+ IN UINT8 MaxBus,
+ IN UINT16 MaxAspmLevel
+ )
+{
+ UINT64 DeviceBaseAddress;
+ UINT16 ComponentAaspm;
+ UINT16 ComponentBaspm;
+ UINT16 SelectedAspm;
+
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ ComponentAaspm = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x00C) >> 10) & 3;
+ ComponentBaspm = FindComponentBaspm (Bus, MaxBus);
+ SelectedAspm = FindOptimalAspm (ComponentAaspm, ComponentBaspm);
+ SelectedAspm = LimitAspmLevel (SelectedAspm, MaxAspmLevel);
+ PciSegmentAndThenOr16 (DeviceBaseAddress + CapHeaderOffset + 0x10, 0xFFFC, SelectedAspm);
+}
+
+VOID
+UpstreamAspmSupport (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Fun,
+ IN UINT8 CapHeaderOffset,
+ IN UINT8 MaxBus,
+ IN UINT16 MaxAspmLevel
+ )
+{
+ UINT64 DeviceBaseAddress;
+ UINT16 ComponentAaspm;
+ UINT16 ComponentBaspm;
+ UINT16 SelectedAspm;
+
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ ComponentAaspm = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x00C) >> 10) & 3;
+ ComponentBaspm = FindComponentBaspm (Bus, MaxBus);
+ SelectedAspm = FindOptimalAspm (ComponentAaspm, ComponentBaspm);
+ SelectedAspm = LimitAspmLevel (SelectedAspm, MaxAspmLevel);
+ PciSegmentAndThenOr16 (DeviceBaseAddress + CapHeaderOffset + 0x10, 0xFFFC, SelectedAspm);
+}
+
+VOID
+DownstreamAspmSupport (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Fun,
+ IN UINT8 CapHeaderOffset,
+ IN UINT16 MaxAspmLevel
+ )
+{
+ UINT64 ComponentABaseAddress;
+ UINT64 ComponentBBaseAddress;
+ UINT16 ComponentAaspm;
+ UINT16 ComponentBaspm;
+ UINT16 SelectedAspm;
+ UINT8 SecBus;
+ UINT8 CapHeaderOffset_B;
+
+ ComponentABaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ ComponentAaspm = (PciSegmentRead16 (ComponentABaseAddress + CapHeaderOffset + 0x00C) >> 10) & 3;
+
+ SecBus = PciSegmentRead8 (ComponentABaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ ComponentBBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, SecBus, 0, 0, 0);
+ ComponentBaspm = 0; // No ASPM Support
+ if (PciSegmentRead16 (ComponentBBaseAddress + PCI_DEVICE_ID_OFFSET) != 0xFFFF) {
+ CapHeaderOffset_B = PcieFindCapId (TbtSegment, SecBus, 0, 0, 0x10);
+ ComponentBaspm = (PciSegmentRead16 (ComponentBBaseAddress + CapHeaderOffset_B + 0x00C) >> 10) & 3;
+ }
+
+ SelectedAspm = FindOptimalAspm (ComponentAaspm, ComponentBaspm);
+ SelectedAspm = LimitAspmLevel (SelectedAspm, MaxAspmLevel);
+ PciSegmentAndThenOr16 (ComponentABaseAddress + CapHeaderOffset + 0x10, 0xFFFC, SelectedAspm);
+}
+
+VOID
+RootportAspmSupport (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Fun,
+ IN UINT8 CapHeaderOffset,
+ IN UINT16 MaxAspmLevel
+ )
+{
+ UINT64 ComponentABaseAddress;
+ UINT64 ComponentBBaseAddress;
+ UINT16 ComponentAaspm;
+ UINT16 ComponentBaspm;
+ UINT16 SelectedAspm;
+ UINT8 SecBus;
+ UINT8 CapHeaderOffset_B;
+
+ ComponentABaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ ComponentAaspm = (PciSegmentRead16 (ComponentABaseAddress + CapHeaderOffset + 0x00C) >> 10) & 3;
+
+ SecBus = PciSegmentRead8 (ComponentABaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ ComponentBBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, SecBus, 0, 0, 0);
+ ComponentBaspm = 0; // No ASPM Support
+ if (PciSegmentRead16 (ComponentBBaseAddress + PCI_DEVICE_ID_OFFSET) != 0xFFFF) {
+ CapHeaderOffset_B = PcieFindCapId (TbtSegment, SecBus, 0, 0, 0x10);
+ ComponentBaspm = (PciSegmentRead16 (ComponentBBaseAddress + CapHeaderOffset_B + 0x00C) >> 10) & 3;
+ }
+
+ SelectedAspm = FindOptimalAspm (ComponentAaspm, ComponentBaspm);
+ SelectedAspm = LimitAspmLevel (SelectedAspm, MaxAspmLevel);
+ PciSegmentAndThenOr16 (ComponentABaseAddress + CapHeaderOffset + 0x10, 0xFFFC, SelectedAspm);
+}
+
+VOID
+ThunderboltEnableAspmWithoutLtr (
+ IN UINT16 MaxAspmLevel,
+ IN UINTN RpSegment,
+ IN UINTN RpBus,
+ IN UINTN RpDevice,
+ IN UINTN RpFunction
+ )
+{
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Fun;
+ UINT8 RootBus;
+ UINT8 RootDev;
+ UINT8 RootFun;
+ UINT8 MinBus;
+ UINT8 MaxBus;
+ UINT16 DeviceId;
+ UINT64 DeviceBaseAddress;
+ UINT8 RegVal;
+ UINT8 CapHeaderOffset;
+ UINT16 DevicePortType;
+
+ MinBus = 0;
+ MaxBus = 0;
+
+ MinBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
+ MaxBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET));
+ DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, MinBus, 0x00, 0x00, PCI_DEVICE_ID_OFFSET));
+ if (!(IsTbtHostRouter (DeviceId))) {
+ return;
+ }
+
+ TbtSegment = (UINT8)RpSegment;
+
+ RootBus = (UINT8)RpBus;
+ RootDev = (UINT8)RpDevice;
+ RootFun = (UINT8)RpFunction;
+
+ //
+ // Enumerate all the bridges and devices which are available on TBT host controller
+ //
+ for (Bus = MinBus; Bus <= MaxBus; ++Bus) {
+ for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
+ //
+ // Check for Device availability
+ //
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, 0, 0);
+ if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ //
+ // Device not present
+ //
+ continue;
+ }
+
+ RegVal = PciSegmentRead8 (DeviceBaseAddress + PCI_HEADER_TYPE_OFFSET);
+ if ((RegVal & BIT7) == 0) {
+ //
+ // Not a multi-function device
+ //
+ continue;
+ }
+
+ MultiFunctionDeviceAspm(Bus, Dev);
+ } //Dev
+ } //Bus
+
+
+ for (Bus = MinBus; Bus <= MaxBus; ++Bus) {
+ for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
+ for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
+ //
+ // Check for Device availability
+ //
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ //
+ // Device not present
+ //
+ continue;
+ }
+
+ CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Dev, Fun, 0x10);
+ DevicePortType = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x002) >> 4) & 0xF;
+ if(PciSegmentRead8 (DeviceBaseAddress + PCI_CLASSCODE_OFFSET) == PCI_CLASS_SERIAL) {
+ MaxAspmLevel = (UINT16) 0x1;
+ }
+
+ switch (DevicePortType) {
+ case 0:
+ //
+ // PCI Express Endpoint
+ //
+ EndpointAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxBus, MaxAspmLevel);
+ break;
+
+ case 1:
+ //
+ // Legacy PCI Express Endpoint
+ //
+ EndpointAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxBus, MaxAspmLevel);
+ break;
+
+ case 4:
+ //
+ // Root Port of PCI Express Root Complex
+ //
+ RootportAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxAspmLevel);
+ break;
+
+ case 5:
+ //
+ // Upstream Port of PCI Express Switch
+ //
+ UpstreamAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxBus, MaxAspmLevel);
+ break;
+
+ case 6:
+ //
+ // Downstream Port of PCI Express Switch
+ //
+ DownstreamAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxAspmLevel);
+ break;
+
+ case 7:
+ //
+ // PCI Express to PCI/PCI-X Bridge
+ //
+ NoAspmSupport (Bus, Dev, Fun, CapHeaderOffset);
+ break;
+
+ case 8:
+ //
+ // PCI/PCI-X to PCI Express Bridge
+ //
+ NoAspmSupport (Bus, Dev, Fun, CapHeaderOffset);
+ break;
+
+ case 9:
+ //
+ // Root Complex Integrated Endpoint
+ //
+ EndpointAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxBus, MaxAspmLevel);
+ break;
+
+ case 10:
+ //
+ // Root Complex Event Collector
+ //
+ EndpointAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxBus, MaxAspmLevel);
+ break;
+
+ default:
+ break;
+ }
+ //
+ // switch(DevicePortType)
+ //
+ }
+ //
+ // Fun
+ //
+ }
+ //
+ // Dev
+ //
+ }
+ //
+ // Bus
+ //
+ CapHeaderOffset = PcieFindCapId (TbtSegment, RootBus, RootDev, RootFun, 0x10);
+ RootportAspmSupport (RootBus, RootDev, RootFun, CapHeaderOffset, MaxAspmLevel);
+}
+
+
+
+VOID
+ThunderboltEnableL1Sub (
+ IN UINT16 MaxL1Level,
+ IN UINTN RpSegment,
+ IN UINTN RpBus,
+ IN UINTN RpDevice,
+ IN UINTN RpFunction
+ )
+{
+ UINT16 CapHeaderOffsetExtd;
+
+ RpBus = 0;
+
+ CapHeaderOffsetExtd = PcieFindExtendedCapId ((UINT8) RpBus, (UINT8) RpDevice, (UINT8) RpFunction, V_PCIE_EX_L1S_CID);
+ RootportL1sSupport ((UINT8) RpBus, (UINT8) RpDevice, (UINT8) RpFunction, CapHeaderOffsetExtd, MaxL1Level);
+}
+
+VOID
+ThunderboltDisableAspmWithoutLtr (
+ IN UINTN RpSegment,
+ IN UINTN RpBus,
+ IN UINTN RpDevice,
+ IN UINTN RpFunction
+ )
+{
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Fun;
+ UINT8 RootBus;
+ UINT8 RootDev;
+ UINT8 RootFun;
+ UINT8 MinBus;
+ UINT8 MaxBus;
+ UINT16 DeviceId;
+ UINT64 DeviceBaseAddress;
+ UINT8 CapHeaderOffset;
+
+ MinBus = 0;
+ MaxBus = 0;
+
+ MinBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
+ MaxBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET));
+ DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, MinBus, 0x00, 0x00, PCI_DEVICE_ID_OFFSET));
+ if (!(IsTbtHostRouter (DeviceId))) {
+ return;
+ }
+
+ TbtSegment = (UINT8)RpSegment;
+ RootBus = (UINT8)RpBus;
+ RootDev = (UINT8)RpDevice;
+ RootFun = (UINT8)RpFunction;
+
+ //
+ // Enumerate all the bridges and devices which are available on TBT host controller
+ //
+ for (Bus = MinBus; Bus <= MaxBus; ++Bus) {
+ for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
+ for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
+ //
+ // Check for Device availability
+ //
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ //
+ // Device not present
+ //
+ continue;
+ }
+
+ CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Dev, Fun, 0x10);
+ PciSegmentAndThenOr16 (DeviceBaseAddress + CapHeaderOffset + 0x10, 0xFFFC, 0x00);
+ } //Fun
+ } //Dev
+ } //Bus
+
+ CapHeaderOffset = PcieFindCapId (TbtSegment, RootBus, RootDev, RootFun, 0x10);
+ NoAspmSupport(RootBus, RootDev, RootFun, CapHeaderOffset);
+}
+
+VOID
+TbtProgramClkReq (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 ClkReqSetup
+ )
+{
+ UINT64 DeviceBaseAddress;
+ UINT8 CapHeaderOffset;
+ UINT16 Data16;
+
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Device, Function, 0);
+ CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Device, Function, 0x10);
+
+ //
+ // Check if CLKREQ# is supported
+ //
+ if ((PciSegmentRead32 (DeviceBaseAddress + CapHeaderOffset + 0x0C) & BIT18) != 0) {
+ Data16 = PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x010);
+
+ if (ClkReqSetup) {
+ Data16 = Data16 | BIT8; // Enable Clock Power Management
+ } else {
+ Data16 = Data16 & (UINT16)(~BIT8); // Disable Clock Power Management
+ }
+
+ PciSegmentWrite16 (DeviceBaseAddress + CapHeaderOffset + 0x010, Data16);
+ }
+}
+VOID
+TbtProgramPtm(
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 PtmSetup,
+ IN BOOLEAN IsRoot
+)
+{
+ UINT64 DeviceBaseAddress;
+ UINT16 CapHeaderOffset;
+ UINT16 PtmControlRegister;
+ UINT16 PtmCapabilityRegister;
+
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS(TbtSegment, Bus, Device, Function, 0);
+ CapHeaderOffset = PcieFindExtendedCapId(Bus, Device, Function, 0x001F /*V_PCIE_EX_PTM_CID*/);
+ if(CapHeaderOffset != 0) {
+ PtmCapabilityRegister = PciSegmentRead16(DeviceBaseAddress + CapHeaderOffset + 0x04);
+ //
+ // Check if PTM Requester/ Responder capability for the EP/Down stream etc
+ //
+ if ((PtmCapabilityRegister & (BIT1 | BIT0)) != 0) {
+ PtmControlRegister = PciSegmentRead16(DeviceBaseAddress + CapHeaderOffset + 0x08);
+
+ if (PtmSetup) {
+ PtmControlRegister = PtmControlRegister | BIT0; // Enable PTM
+ if(IsRoot) {
+ PtmControlRegister = PtmControlRegister | BIT1; // Enable PTM
+ }
+ PtmControlRegister = PtmControlRegister | (PtmCapabilityRegister & 0xFF00); // Programm Local Clock Granularity
+ } else {
+ PtmControlRegister = PtmControlRegister & (UINT16)(~(BIT0 | BIT1)); // Disable Clock Power Management
+ }
+
+ PciSegmentWrite16(DeviceBaseAddress + CapHeaderOffset + 0x08, PtmControlRegister);
+ }
+ }
+}
+
+VOID
+ConfigureTbtPm (
+ IN UINTN RpSegment,
+ IN UINTN RpBus,
+ IN UINTN RpDevice,
+ IN UINTN RpFunction,
+ IN UINT8 Configuration // 1- Clk Request , 2- PTM ,
+ )
+{
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Fun;
+ UINT8 MinBus;
+ UINT8 MaxBus;
+ UINT16 DeviceId;
+ UINT64 DeviceBaseAddress;
+
+ MinBus = 0;
+ MaxBus = 0;
+
+ if ((Configuration != 1) && (Configuration != 2)) {
+ return;
+ }
+ MinBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
+ MaxBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET));
+ DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, MinBus, 0x00, 0x00, PCI_DEVICE_ID_OFFSET));
+ if (!(IsTbtHostRouter (DeviceId))) {
+ return;
+ }
+
+ TbtSegment = (UINT8)RpSegment;
+ //
+ // Enumerate all the bridges and devices which are available on TBT host controller
+ //
+ for (Bus = MaxBus; Bus >= MinBus; --Bus) {
+ for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
+ for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
+ //
+ // Check for Device availability
+ //
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ if (Fun == 0) {
+ //
+ // IF Fun is zero, stop enumerating other functions of the particular bridge
+ //
+ break;
+ }
+ //
+ // otherwise, just skip checking for CLKREQ support
+ //
+ continue;
+ }
+ switch (Configuration) {
+ case 1:
+ TbtProgramClkReq (Bus, Dev, Fun, (UINT8) mTbtNvsAreaPtr->TbtSetClkReq);
+ break;
+ case 2:
+ TbtProgramPtm (Bus, Dev, Fun, (UINT8) mTbtNvsAreaPtr->TbtPtm, FALSE);
+ TbtProgramPtm((UINT8) RpBus, (UINT8) RpDevice, (UINT8) RpFunction, (UINT8) mTbtNvsAreaPtr->TbtPtm, TRUE);
+ break;
+ default:
+ break;
+ }
+ } //Fun
+ } // Dev
+ } // Bus
+}
+
+/**
+ 1) Check LTR support in device capabilities 2 register (bit 11).
+ 2) If supported enable LTR in device control 2 register (bit 10).
+
+**/
+VOID
+TbtProgramLtr (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 LtrSetup
+ )
+{
+ UINT64 DeviceBaseAddress;
+ UINT8 CapHeaderOffset;
+ UINT16 Data16;
+
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Device, Function, 0);
+ CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Device, Function, 0x10);
+
+ //
+ // Check if LTR# is supported
+ //
+ if ((PciSegmentRead32 (DeviceBaseAddress + CapHeaderOffset + 0x24) & BIT11) != 0) {
+ Data16 = PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x028);
+
+ if (LtrSetup) {
+ Data16 = Data16 | BIT10; // LTR Mechanism Enable
+ } else {
+ Data16 = Data16 & (UINT16)(~BIT10); // LTR Mechanism Disable
+ }
+
+ PciSegmentWrite16 (DeviceBaseAddress + CapHeaderOffset + 0x028, Data16);
+ }
+}
+
+VOID
+ConfigureLtr (
+ IN UINTN RpSegment,
+ IN UINTN RpBus,
+ IN UINTN RpDevice,
+ IN UINTN RpFunction
+ )
+{
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Fun;
+ UINT8 MinBus;
+ UINT8 MaxBus;
+ UINT16 DeviceId;
+ UINT64 DeviceBaseAddress;
+
+ MinBus = 0;
+ MaxBus = 0;
+
+ MinBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
+ MaxBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET));
+ DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, MinBus, 0x00, 0x00, PCI_DEVICE_ID_OFFSET));
+ if (!(IsTbtHostRouter (DeviceId))) {
+ return;
+ }
+
+ TbtSegment = (UINT8)RpSegment;
+ //
+ // Enumerate all the bridges and devices which are available on TBT host controller
+ //
+ for (Bus = MinBus; Bus <= MaxBus; ++Bus) {
+ for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
+ for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
+ //
+ // Check for Device availability
+ //
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ if (Fun == 0) {
+ //
+ // IF Fun is zero, stop enumerating other functions of the particular bridge
+ //
+ break;
+ }
+ //
+ // otherwise, just skip checking for LTR support
+ //
+ continue;
+ }
+
+ TbtProgramLtr (Bus, Dev, Fun, (UINT8) mTbtNvsAreaPtr->TbtLtr);
+
+ } //Fun
+ } // Dev
+ } // Bus
+ TbtProgramLtr ((UINT8) RpBus, (UINT8) RpDevice, (UINT8) RpFunction, (UINT8) mTbtNvsAreaPtr->TbtLtr);
+}
+
+/*
+ US ports and endpoints which declare support must also have the LTR capability structure (cap ID 18h).
+ In this structure you need to enter the max snoop latency and max non-snoop latency in accordance with the format specified in the PCIe spec.
+ The latency value itself is platform specific so you'll need to get it from the platform architect or whatever.
+*/
+VOID
+ThunderboltGetLatencyLtr (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if(gCurrentDiscreteTbtRootPortType == DTBT_TYPE_PEG) {
+ // PEG selector
+ TbtLtrMaxSnoopLatency = LTR_MAX_SNOOP_LATENCY_VALUE;
+ TbtLtrMaxNoSnoopLatency = LTR_MAX_NON_SNOOP_LATENCY_VALUE;
+ } else if (gCurrentDiscreteTbtRootPortType == DTBT_TYPE_PCH) {
+ // PCH selector
+
+ if (PchSeries == PchLp) {
+ TbtLtrMaxSnoopLatency = 0x1003;
+ TbtLtrMaxNoSnoopLatency = 0x1003;
+ }
+ if (PchSeries == PchH) {
+ TbtLtrMaxSnoopLatency = 0x0846;
+ TbtLtrMaxNoSnoopLatency = 0x0846;
+ }
+ }
+}
+
+VOID
+SetLatencyLtr (
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Fun,
+ IN UINT16 CapHeaderOffsetExtd,
+ IN UINT16 LtrMaxSnoopLatency,
+ IN UINT16 LtrMaxNoSnoopLatency
+ )
+{
+ UINT64 DeviceBaseAddress;
+ if(CapHeaderOffsetExtd == 0) {
+ return;
+ }
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ PciSegmentWrite16 (DeviceBaseAddress + CapHeaderOffsetExtd + 0x004, LtrMaxSnoopLatency);
+ PciSegmentWrite16 (DeviceBaseAddress + CapHeaderOffsetExtd + 0x006, LtrMaxNoSnoopLatency);
+}
+
+VOID
+ThunderboltSetLatencyLtr (
+ IN UINTN RpSegment,
+ IN UINTN RpBus,
+ IN UINTN RpDevice,
+ IN UINTN RpFunction
+ )
+{
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Fun;
+ UINT8 MinBus;
+ UINT8 MaxBus;
+ UINT16 DeviceId;
+ UINT64 DeviceBaseAddress;
+ UINT8 CapHeaderOffsetStd;
+ UINT16 CapHeaderOffsetExtd;
+ UINT16 DevicePortType;
+
+ MinBus = 0;
+ MaxBus = 0;
+
+ MinBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
+ MaxBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET));
+ DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, MinBus, 0x00, 0x00, PCI_DEVICE_ID_OFFSET));
+ if (!(IsTbtHostRouter (DeviceId))) {
+ return;
+ }
+
+ TbtSegment = (UINT8)RpSegment;
+
+ for (Bus = MinBus; Bus <= MaxBus; ++Bus) {
+ for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
+ for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
+ //
+ // Check for Device availability
+ //
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
+ if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ //
+ // Device not present
+ //
+ continue;
+ }
+
+ CapHeaderOffsetStd = PcieFindCapId (TbtSegment, Bus, Dev, Fun, 0x10);
+ DevicePortType = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffsetStd + 0x002) >> 4) & 0xF;
+
+ CapHeaderOffsetExtd = PcieFindExtendedCapId (Bus, Dev, Fun, 0x0018);
+
+ switch (DevicePortType) {
+ case 0:
+ //
+ // PCI Express Endpoint
+ //
+ SetLatencyLtr (Bus, Dev, Fun, CapHeaderOffsetExtd, TbtLtrMaxSnoopLatency, TbtLtrMaxNoSnoopLatency);
+ break;
+
+ case 1:
+ //
+ // Legacy PCI Express Endpoint
+ //
+ SetLatencyLtr (Bus, Dev, Fun, CapHeaderOffsetExtd, TbtLtrMaxSnoopLatency, TbtLtrMaxNoSnoopLatency);
+ break;
+
+ case 4:
+ //
+ // Root Port of PCI Express Root Complex
+ //
+ // Do-nothing
+ break;
+
+ case 5:
+ //
+ // Upstream Port of PCI Express Switch
+ //
+ SetLatencyLtr (Bus, Dev, Fun, CapHeaderOffsetExtd, TbtLtrMaxSnoopLatency, TbtLtrMaxNoSnoopLatency);
+ break;
+
+ case 6:
+ //
+ // Downstream Port of PCI Express Switch
+ //
+ // Do-nothing
+ break;
+
+ case 7:
+ //
+ // PCI Express to PCI/PCI-X Bridge
+ //
+ // Do-nothing
+ break;
+
+ case 8:
+ //
+ // PCI/PCI-X to PCI Express Bridge
+ //
+ // Do-nothing
+ break;
+
+ case 9:
+ //
+ // Root Complex Integrated Endpoint
+ //
+ // Do-nothing
+ break;
+
+ case 10:
+ //
+ // Root Complex Event Collector
+ //
+ // Do-nothing
+ break;
+
+ default:
+ break;
+ }
+ //
+ // switch(DevicePortType)
+ //
+ }
+ //
+ // Fun
+ //
+ }
+ //
+ // Dev
+ //
+ }
+ //
+ // Bus
+ //
+}
+
+static
+VOID
+Stall (
+ UINTN Usec
+ )
+{
+ UINTN Index;
+ UINT32 Data32;
+ UINT32 PrevData;
+ UINTN Counter;
+
+ Counter = (UINTN) ((Usec * 10) / 3);
+ //
+ // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick
+ // periods, thus attempting to ensure Microseconds of stall time.
+ //
+ if (Counter != 0) {
+
+ PrevData = IoRead32 (PcdGet16 (PcdAcpiBaseAddress) + R_PCH_ACPI_PM1_TMR);
+ for (Index = 0; Index < Counter;) {
+ Data32 = IoRead32 (PcdGet16 (PcdAcpiBaseAddress) + R_PCH_ACPI_PM1_TMR);
+ if (Data32 < PrevData) {
+ //
+ // Reset if there is a overlap
+ //
+ PrevData = Data32;
+ continue;
+ }
+
+ Index += (Data32 - PrevData);
+ PrevData = Data32;
+ }
+ }
+
+ return ;
+}
+/**
+ Called during Sx entry, initates TbtSetPcie2TbtCommand HandShake to set GO2SX_NO_WAKE
+ for Tbt devices if WakeupSupport is not present.
+
+ @param[in] DispatchHandle - The unique handle assigned to this handler by SmiHandlerRegister().
+ @param[in] DispatchContext - Points to an optional handler context which was specified when the
+ handler was registered.
+ @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 - The interrupt was handled successfully.
+**/
+EFI_STATUS
+EFIAPI
+SxDTbtEntryCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ )
+{
+ UINT16 DeviceId;
+ UINT8 CableConnected;
+ UINT8 RootportSelected;
+ UINT8 HoustRouteBus;
+ volatile UINT32 *PowerState;
+ UINT32 PowerStatePrev;
+ BOOLEAN SecSubBusAssigned;
+ UINT64 DeviceBaseAddress;
+ UINT8 CapHeaderOffset;
+ UINTN RpDev;
+ UINTN RpFunc;
+ EFI_STATUS Status;
+ UINT32 Timeout;
+ UINT32 RegisterValue;
+ UINT64 Tbt2Pcie;
+ UINTN Index;
+ UINT32 TbtCioPlugEventGpioNo;
+ UINT32 TbtFrcPwrGpioNo;
+ UINT8 TbtFrcPwrGpioLevel;
+ UINT32 TbtPcieRstGpioNo;
+ UINT8 TbtPcieRstGpioLevel;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryDispatchContext;
+
+ CableConnected = 0;
+ HoustRouteBus = 3;
+ SecSubBusAssigned = FALSE;
+ Timeout = 600;
+ RootportSelected = 0;
+ TbtCioPlugEventGpioNo = 0;
+ TbtFrcPwrGpioNo = 0;
+ TbtFrcPwrGpioLevel = 0;
+ TbtPcieRstGpioNo = 0;
+ TbtPcieRstGpioLevel = 0;
+ Index = 0;
+
+ EntryDispatchContext = (EFI_SMM_SX_REGISTER_CONTEXT*) DispatchContext;
+
+// CableConnected = GetTbtHostRouterStatus ();
+ //SaveTbtHostRouterStatus (CableConnected & 0xF0);
+ //
+ // Get the Power State and Save
+ //
+ if (((mTbtNvsAreaPtr->DTbtControllerEn0 == 0) && (Index == 0))) {
+
+ RootportSelected = mTbtNvsAreaPtr->RootportSelected0;
+ TbtCioPlugEventGpioNo = mTbtNvsAreaPtr->TbtCioPlugEventGpioNo0;
+ TbtFrcPwrGpioNo = mTbtNvsAreaPtr->TbtFrcPwrGpioNo0;
+ TbtFrcPwrGpioLevel = mTbtNvsAreaPtr->TbtFrcPwrGpioLevel0;
+ TbtPcieRstGpioNo = mTbtNvsAreaPtr->TbtPcieRstGpioNo0;
+ TbtPcieRstGpioLevel = mTbtNvsAreaPtr->TbtPcieRstGpioLevel0;
+ }
+
+ Status = GetDTbtRpDevFun (gCurrentDiscreteTbtRootPortType, RootportSelected - 1, &RpDev, &RpFunc);
+ ASSERT_EFI_ERROR (Status);
+ CapHeaderOffset = PcieFindCapId (TbtSegment, 0x00, (UINT8)RpDev, (UINT8)RpFunc, 0x01);
+ DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, 0x00, (UINT32)RpDev, (UINT32)RpFunc, 0);
+ PowerState = &*((volatile UINT32 *) (mPciExpressBaseAddress + DeviceBaseAddress + CapHeaderOffset + 4)); //PMCSR
+ PowerStatePrev = *PowerState;
+ *PowerState &= 0xFFFFFFFC;
+
+ HoustRouteBus = PciSegmentRead8 (DeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ //
+ // Check the Subordinate bus .If it is Zero ,assign temporary bus to
+ // find the device presence .
+ //
+ if (HoustRouteBus == 0) {
+ PciSegmentWrite8 (DeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 0xF0);
+ PciSegmentWrite8 (DeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, 0xF0);
+ HoustRouteBus = 0xF0;
+ SecSubBusAssigned = TRUE;
+ }
+ //
+ // Clear Interrupt capability of TBT CIO Plug Event Pin to make sure no SCI is getting generated,
+ // This GPIO will be reprogrammed while resuming as part of Platform GPIO Programming.
+ //
+ GpioSetPadInterruptConfig (TbtCioPlugEventGpioNo, GpioIntDis);
+ //
+ // Read the TBT Host router DeviceID
+ //
+ DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (TbtSegment, HoustRouteBus, 0, 0, PCI_DEVICE_ID_OFFSET));
+
+ //
+ // Check For HostRouter Presence
+ //
+ if (IsTbtHostRouter (DeviceId)) {
+ // CableConnected = GetTbtHostRouterStatus ();
+ if (!((CableConnected & (DTBT_SAVE_STATE_OFFSET << Index)) == (DTBT_SAVE_STATE_OFFSET << Index))) {
+ CableConnected = CableConnected | (DTBT_SAVE_STATE_OFFSET << Index);
+ // SaveTbtHostRouterStatus (CableConnected);
+ }
+ }
+
+ //
+ // Check value of Tbt2Pcie reg, if Tbt is not present, bios needs to apply force power prior to sending mailbox command
+ //
+ GET_TBT2PCIE_REGISTER_ADDRESS(TbtSegment, HoustRouteBus, 0x00, 0x00, Tbt2Pcie)
+ RegisterValue = PciSegmentRead32 (Tbt2Pcie);
+ if (0xFFFFFFFF == RegisterValue) {
+
+ GpioWrite (TbtFrcPwrGpioNo,TbtFrcPwrGpioLevel);
+
+ while (Timeout -- > 0) {
+ RegisterValue = PciSegmentRead32 (Tbt2Pcie);
+ if (0xFFFFFFFF != RegisterValue) {
+ break;
+ }
+ Stall(1* (UINTN)1000);
+ }
+ //
+ // Before entering Sx state BIOS should execute GO2SX/NO_WAKE mailbox command for AIC.
+ // However BIOS shall not execute go2sx mailbox command on S5/reboot cycle.
+ //
+
+ if( (EntryDispatchContext->Type == SxS3) || (EntryDispatchContext->Type == SxS4))
+ {
+ if(!mTbtNvsAreaPtr->TbtWakeupSupport) {
+ //Wake Disabled, GO2SX_NO_WAKE Command
+ TbtSetPcie2TbtCommand (PCIE2TBT_GO2SX_NO_WAKE, HoustRouteBus, 0, 0, TBT_5S_TIMEOUT);
+ } else {
+ //Wake Enabled, GO2SX Command
+ TbtSetPcie2TbtCommand (PCIE2TBT_GO2SX, HoustRouteBus, 0, 0, TBT_5S_TIMEOUT);
+ }
+ }
+ if (mTbtNvsAreaPtr->TbtFrcPwrEn == 0) {
+ GpioWrite (TbtFrcPwrGpioNo,!(TbtFrcPwrGpioLevel));
+ }
+ } else {
+ //
+ // Before entering Sx state BIOS should execute GO2SX/NO_WAKE mailbox command for AIC.
+ // However BIOS shall not execute go2sx mailbox command on S5/reboot cycle.
+ //
+ if( (EntryDispatchContext->Type == SxS3) || (EntryDispatchContext->Type == SxS4))
+ {
+ if(!mTbtNvsAreaPtr->TbtWakeupSupport) {
+ //Wake Disabled, GO2SX_NO_WAKE Command
+ TbtSetPcie2TbtCommand (PCIE2TBT_GO2SX_NO_WAKE, HoustRouteBus, 0, 0, TBT_5S_TIMEOUT);
+ } else {
+ //Wake Enabled, GO2SX Command
+ TbtSetPcie2TbtCommand (PCIE2TBT_GO2SX, HoustRouteBus, 0, 0, TBT_5S_TIMEOUT);
+ }
+ }
+ }
+ *PowerState = PowerStatePrev;
+ //
+ // Restore the bus number in case we assigned temporarily
+ //
+ if (SecSubBusAssigned) {
+ PciSegmentWrite8 (DeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 0x00);
+ PciSegmentWrite8 (DeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, 0x00);
+ }
+ if (gDTbtPcieRstSupport) {
+ GpioWrite (TbtPcieRstGpioNo,TbtPcieRstGpioLevel);
+ }
+ return EFI_SUCCESS;
+}
+
+VOID
+ThunderboltSwSmiCallback (
+ IN UINT8 Type
+ )
+{
+ UINT8 ThunderboltSmiFunction;
+
+ DEBUG ((DEBUG_INFO, "ThunderboltSwSmiCallback Entry\n"));
+ ThunderboltSmiFunction = mTbtNvsAreaPtr->ThunderboltSmiFunction;
+ DEBUG ((DEBUG_INFO, "ThunderboltSwSmiCallback. ThunderboltSmiFunction=%d\n", ThunderboltSmiFunction));
+ if (Type == DTBT_CONTROLLER) {
+ gCurrentDiscreteTbtRootPort = mTbtNvsAreaPtr->CurrentDiscreteTbtRootPort;
+ gCurrentDiscreteTbtRootPortType = mTbtNvsAreaPtr->CurrentDiscreteTbtRootPortType;
+ }
+
+ switch (ThunderboltSmiFunction) {
+ case 21:
+ ThunderboltCallback (Type);
+ break;
+
+ case 22:
+ TbtDisablePCIDevicesAndBridges (Type);
+ break;
+
+ case 23:
+ ConfigureTbtAspm (Type, (UINT16) 0x02);
+ break;
+
+ case 24:
+ ConfigureTbtAspm (Type, (UINT16) 0x01);
+ break;
+
+ default:
+ break;
+ }
+ DEBUG ((DEBUG_INFO, "ThunderboltSwSmiCallback Exit.\n"));
+}
+STATIC
+EFI_STATUS
+EFIAPI
+DiscreteThunderboltSwSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN UINTN *CommBufferSize OPTIONAL
+ )
+{
+ ThunderboltSwSmiCallback(DTBT_CONTROLLER);
+ return EFI_SUCCESS;
+}
+EFI_STATUS
+TbtRegisterHandlers (
+ IN BOOLEAN Type
+ )
+{
+ EFI_STATUS Status;
+ UINTN SmiInputValue;
+ EFI_SMM_HANDLER_ENTRY_POINT2 SxHandler;
+ EFI_SMM_HANDLER_ENTRY_POINT2 SwHandler;
+ EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatchProtocol;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
+ EFI_SMM_SX_REGISTER_CONTEXT EntryDispatchContext;
+ EFI_SMM_SW_REGISTER_CONTEXT SwContext;
+ EFI_HANDLE SwDispatchHandle;
+ EFI_HANDLE S3DispatchHandle;
+ EFI_HANDLE S4DispatchHandle;
+ EFI_HANDLE S5DispatchHandle;
+
+ Status = EFI_UNSUPPORTED;
+
+ if(Type == DTBT_CONTROLLER) {
+ SxHandler = SxDTbtEntryCallback;
+ SwHandler = DiscreteThunderboltSwSmiCallback;
+ SmiInputValue = PcdGet8 (PcdSwSmiDTbtEnumerate);
+ gDTbtPcieRstSupport = gTbtInfoHob->DTbtCommonConfig.PcieRstSupport;
+ Status = EFI_SUCCESS;
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SwDispatchHandle = NULL;
+ S3DispatchHandle = NULL;
+ S4DispatchHandle = NULL;
+ S5DispatchHandle = NULL;
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ NULL,
+ (VOID **) &SxDispatchProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Register S3 entry phase call back function
+ //
+ EntryDispatchContext.Type = SxS3;
+ EntryDispatchContext.Phase = SxEntry;
+ Status = SxDispatchProtocol->Register (
+ SxDispatchProtocol,
+ SxHandler,
+ &EntryDispatchContext,
+ &S3DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Register S4 entry phase call back function
+ //
+ EntryDispatchContext.Type = SxS4;
+ EntryDispatchContext.Phase = SxEntry;
+ Status = SxDispatchProtocol->Register (
+ SxDispatchProtocol,
+ SxHandler,
+ &EntryDispatchContext,
+ &S4DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Register S5 entry phase call back function
+ //
+ EntryDispatchContext.Type = SxS5;
+ EntryDispatchContext.Phase = SxEntry;
+ Status = SxDispatchProtocol->Register (
+ SxDispatchProtocol,
+ SxHandler,
+ &EntryDispatchContext,
+ &S5DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Locate the SMM SW dispatch protocol
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ NULL,
+ (VOID **) &SwDispatch
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Register SWSMI handler
+ //
+ SwContext.SwSmiInputValue = SmiInputValue;
+ Status = SwDispatch->Register (
+ SwDispatch,
+ SwHandler,
+ &SwContext,
+ &SwDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+EFI_STATUS
+InSmmFunction (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ Status = TbtRegisterHandlers(DTBT_CONTROLLER);
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+TbtSmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ TBT_NVS_AREA_PROTOCOL *TbtNvsAreaProtocol;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "TbtSmmEntryPoint\n"));
+
+ mPciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress);
+ //
+ // Locate Tbt shared data area
+ //
+ Status = gBS->LocateProtocol (&gTbtNvsAreaProtocolGuid, NULL, (VOID **) &TbtNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mTbtNvsAreaPtr = TbtNvsAreaProtocol->Area;
+
+ //
+ // Get TBT INFO HOB
+ //
+ gTbtInfoHob = (TBT_INFO_HOB *) GetFirstGuidHob (&gTbtInfoHobGuid);
+ if (gTbtInfoHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ return InSmmFunction (ImageHandle, SystemTable);
+}
+
+VOID
+EndOfThunderboltCallback (
+ IN UINTN RpSegment,
+ IN UINTN RpBus,
+ IN UINTN RpDevice,
+ IN UINTN RpFunction
+ )
+{
+ if(mTbtNvsAreaPtr->TbtL1SubStates != 0) {
+ ThunderboltEnableL1Sub (mTbtNvsAreaPtr->TbtL1SubStates, RpSegment, RpBus, RpDevice, RpFunction);
+ }
+ ConfigureTbtPm(RpSegment, RpBus, RpDevice, RpFunction, 1);
+ if (!mTbtNvsAreaPtr->TbtAspm) { //Aspm disable case
+ ThunderboltDisableAspmWithoutLtr (RpSegment, RpBus, RpDevice, RpFunction);
+ } else { //Aspm enable case
+ ThunderboltEnableAspmWithoutLtr ((UINT16)mTbtNvsAreaPtr->TbtAspm, RpSegment, RpBus, RpDevice, RpFunction);
+ }
+
+ if (mTbtNvsAreaPtr->TbtLtr) {
+ ThunderboltGetLatencyLtr ();
+ ThunderboltSetLatencyLtr (RpSegment, RpBus, RpDevice, RpFunction);
+ }
+ ConfigureLtr (RpSegment, RpBus, RpDevice, RpFunction);
+ ConfigureTbtPm(RpSegment, RpBus, RpDevice, RpFunction, 2);
+} // EndOfThunderboltCallback
+
+VOID
+ConfigureTbtAspm (
+ IN UINT8 Type,
+ IN UINT16 Aspm
+ )
+{
+ UINTN RpSegment = 0;
+ UINTN RpBus = 0;
+ UINTN RpDevice;
+ UINTN RpFunction;
+
+ if(Type == DTBT_CONTROLLER) {
+ if (gCurrentDiscreteTbtRootPort == 0) {
+ return;
+ }
+ GetDTbtRpDevFun(DTBT_CONTROLLER, gCurrentDiscreteTbtRootPort - 1, &RpDevice, &RpFunction);
+
+ ConfigureTbtPm (RpSegment, RpBus, RpDevice, RpFunction, 1);
+ if (!mTbtNvsAreaPtr->TbtAspm) { //Aspm disable case
+ ThunderboltDisableAspmWithoutLtr (RpSegment, RpBus, RpDevice, RpFunction);
+ } else { //Aspm enable case
+ ThunderboltEnableAspmWithoutLtr ((UINT16) Aspm, RpSegment, RpBus, RpDevice, RpFunction);
+ }
+
+ if (mTbtNvsAreaPtr->TbtLtr) {
+ ThunderboltGetLatencyLtr ();
+ ThunderboltSetLatencyLtr (RpSegment, RpBus, RpDevice, RpFunction);
+ }
+ ConfigureLtr (RpSegment, RpBus, RpDevice, RpFunction);
+ } // EndOfThunderboltCallback
+} \ No newline at end of file
diff --git a/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmm.inf b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmm.inf
new file mode 100644
index 0000000000..31ecb9767a
--- /dev/null
+++ b/Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmm.inf
@@ -0,0 +1,83 @@
+### @file
+# Component information file for the ThunderBolt Smm module.
+#
+# Copyright (c) 2018, Intel Corporation. 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 = TbtSmm
+ FILE_GUID = 5BDCD685-D80A-42E6-9867-A84CCE7F828E
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_SMM_DRIVER
+ PI_SPECIFICATION_VERSION = 1.10
+ ENTRY_POINT = TbtSmmEntryPoint
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ IoLib
+ PciExpressLib
+ HobLib
+ ReportStatusCodeLib
+ PciSegmentLib
+ UefiLib
+ SmmServicesTableLib
+ GpioLib
+ PchInfoLib
+ TbtCommonLib
+ PchPmcLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ KabylakeOpenBoardPkg/OpenBoardPkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+ gBoardModuleTokenSpaceGuid.PcdSwSmiDTbtEnumerate ## CONSUMES
+ gSiPkgTokenSpaceGuid.PcdPciExpressRegionLength ## CONSUMES
+
+[FixedPcd]
+ gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress ## CONSUMES
+
+[Sources]
+ TbtSmiHandler.h
+ TbtSmiHandler.c
+ TbtSmm.c
+
+[Protocols]
+ gTbtNvsAreaProtocolGuid ## CONSUMES
+ gEfiSmmSxDispatch2ProtocolGuid ## CONSUMES
+ gEfiSmmSwDispatch2ProtocolGuid ## CONSUMES
+ gEfiSmmVariableProtocolGuid ## CONSUMES
+ gDxeTbtPolicyProtocolGuid
+
+[Guids]
+ gTbtInfoHobGuid ## CONSUMES
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
+
+[Depex]
+ gEfiSmmBase2ProtocolGuid AND
+ gEfiSmmSxDispatch2ProtocolGuid AND
+ gEfiSmmSwDispatch2ProtocolGuid AND
+ gEfiGlobalNvsAreaProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiSmmVariableProtocolGuid