From 62f1e1e58965702030f722dcdf6de58998cf08a1 Mon Sep 17 00:00:00 2001 From: Jiewen Yao Date: Mon, 26 Mar 2018 20:50:41 +0800 Subject: KabylakeOpenBoardPkg: Add TBT support. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Vishal P Adodariya Reviewed-by: Jiewen Yao --- .../Features/Tbt/AcpiTables/Rtd3SptPcieTbt.asl | 410 +++++ .../Features/Tbt/AcpiTables/Tbt.asl | 1909 ++++++++++++++++++++ .../Features/Tbt/Include/Acpi/TbtNvs.asl | 66 + .../Features/Tbt/Include/Acpi/TbtNvsAreaDef.h | 70 + .../Features/Tbt/Include/Library/DxeTbtPolicyLib.h | 53 + .../Features/Tbt/Include/Library/PeiTbtPolicyLib.h | 47 + .../Features/Tbt/Include/Library/TbtCommonLib.h | 247 +++ .../Features/Tbt/Include/Ppi/PeiTbtPolicy.h | 36 + .../Tbt/Include/Private/Library/PeiDTbtInitLib.h | 114 ++ .../Include/Private/Library/PeiTbtCommonInitLib.h | 47 + .../Features/Tbt/Include/Protocol/DxeTbtPolicy.h | 117 ++ .../Features/Tbt/Include/Protocol/TbtNvsArea.h | 48 + .../Features/Tbt/Include/TbtBoardInfo.h | 28 + .../Tbt/Include/TbtPolicyCommonDefinition.h | 84 + .../Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.c | 167 ++ .../Library/DxeTbtPolicyLib/DxeTbtPolicyLib.inf | 73 + .../Library/DxeTbtPolicyLib/DxeTbtPolicyLibrary.h | 28 + .../Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.c | 321 ++++ .../Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.inf | 69 + .../Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.c | 210 +++ .../Library/PeiTbtPolicyLib/PeiTbtPolicyLib.inf | 62 + .../Library/PeiTbtPolicyLib/PeiTbtPolicyLibrary.h | 23 + .../Private/PeiDTbtInitLib/PeiDTbtInitLib.c | 572 ++++++ .../Private/PeiDTbtInitLib/PeiDTbtInitLib.inf | 48 + .../Features/Tbt/TbtInit/Dxe/TbtDxe.c | 233 +++ .../Features/Tbt/TbtInit/Dxe/TbtDxe.inf | 54 + .../Features/Tbt/TbtInit/Pei/PeiTbtInit.c | 216 +++ .../Features/Tbt/TbtInit/Pei/PeiTbtInit.inf | 50 + .../Features/Tbt/TbtInit/Smm/TbtSmiHandler.c | 1615 +++++++++++++++++ .../Features/Tbt/TbtInit/Smm/TbtSmiHandler.h | 185 ++ .../Features/Tbt/TbtInit/Smm/TbtSmm.c | 1771 ++++++++++++++++++ .../Features/Tbt/TbtInit/Smm/TbtSmm.inf | 83 + 32 files changed, 9056 insertions(+) create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/AcpiTables/Rtd3SptPcieTbt.asl create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/AcpiTables/Tbt.asl create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Acpi/TbtNvs.asl create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Acpi/TbtNvsAreaDef.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/DxeTbtPolicyLib.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/PeiTbtPolicyLib.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Library/TbtCommonLib.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Ppi/PeiTbtPolicy.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Private/Library/PeiDTbtInitLib.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Private/Library/PeiTbtCommonInitLib.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Protocol/DxeTbtPolicy.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/Protocol/TbtNvsArea.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/TbtBoardInfo.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Include/TbtPolicyCommonDefinition.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.c create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLib.inf create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/DxeTbtPolicyLib/DxeTbtPolicyLibrary.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.c create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiDxeSmmTbtCommonLib/TbtCommonLib.inf create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.c create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLib.inf create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/PeiTbtPolicyLib/PeiTbtPolicyLibrary.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/Private/PeiDTbtInitLib/PeiDTbtInitLib.c create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/Library/Private/PeiDTbtInitLib/PeiDTbtInitLib.inf create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Dxe/TbtDxe.c create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Dxe/TbtDxe.inf create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Pei/PeiTbtInit.c create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Pei/PeiTbtInit.inf create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmiHandler.c create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmiHandler.h create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmm.c create mode 100644 Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt/TbtInit/Smm/TbtSmm.inf (limited to 'Platform/Intel/KabylakeOpenBoardPkg/Features/Tbt') 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include + +#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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 + +#pragma pack(push, 1) + +#define PEI_TBT_POLICY_REVISION 1 + +/** + TBT PEI configuration\n + Revision 1: + - 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 + +/** + 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 + +#pragma pack(push, 1) + +#define DXE_TBT_POLICY_REVISION 1 + +// +// TBT Common Data Structure +// +typedef struct _TBT_COMMON_CONFIG{ + /** + TBT Security Level + 0: SL0 No Security, 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 + 0: Disabled, 1: Enabled + **/ + UINT32 Gpio5Filter : 1; + /** + Send Go2SxNoWake or GoSxWake according to TbtWakeupSupport + 0: Disabled, 1: Enabled + **/ + UINT32 TbtWakeupSupport : 1; + /** + SMI TBT enumeration + 0: Disabled, 1: Enabled + **/ + UINT32 TbtHotSMI : 1; + /** + Notify PCIe RP after Hot-Plug/Hot-Unplug occurred. + 0: Disabled, 1: Enabled + **/ + UINT32 TbtHotNotify : 1; + /** + CLK REQ for all the PCIe device in TBT daisy chain. + 0: Disabled, 1: Enabled + **/ + UINT32 TbtSetClkReq : 1; + /** + ASPM setting for all the PCIe device in TBT daisy chain. + 0: Disabled, 1: L0s, 2: L1, 3: L0sL1 + **/ + UINT32 TbtAspm : 2; + /** + LTR for for all the PCIe device in TBT daisy chain. + 0: Disabled, 1: Enabled + **/ + UINT32 TbtLtr : 1; + /** + TBT Dynamic AC/DC L1. + 0: Disabled, 1: Enabled + **/ + UINT32 TbtAcDcSwitch : 1; + /** + TBT RTD3 Support. + 0: Disabled, 1: Enabled + **/ + UINT32 Rtd3Tbt : 1; + /** + TBT ClkReq for RTD3 Flow. + 0: Disabled, 1: Enabled + **/ + UINT32 Rtd3TbtClkReq : 1; + /** + TBT Win10support for Tbt FW execution mode. + 0: Disabled, 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 + Revision 1: + - 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 + +// +// 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 + +#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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include + +#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. + UINT8 PcieRpNumber; ///< RP Number/ PEG Port (0,1,2) that connecet to dTBT controller. + DTBT_FORCE_POWER_GPIO_CONFIG ForcePwrGpio; ///< The GPIO pin that can force dTBT Power On. + DTBT_CIO_PLUG_EVENT_GPIO_CONFIG CioPlugEventGpio; ///< The GPIO pin that can generate Hot-Plug event. + 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 + 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 + 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include + + +/** +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.
+# +# 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include +#include +#include +#include + + +/** + 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.
+# +# 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include +#include +#include +#include + +/** + 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.
+# +# 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include + +#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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** +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, " 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, " 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, " 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.
+# +# 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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.
+# +# 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* +/** + 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.
+# +# 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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include +#include +#include +#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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include + +#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.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "TbtSmiHandler.h" +#include +#include +#include +#include +#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.
+# +# 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 -- cgit v1.2.3