/** @file ACPI RTD3 SSDT table for Thunderbolt @copyright INTEL CONFIDENTIAL Copyright 2011 - 2021 Intel Corporation. The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material may contain trade secrets and proprietary and confidential information of Intel Corporation and its suppliers and licensors, and is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel's prior express written permission. No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing. Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way. This file contains a 'Sample Driver' and is licensed as such under the terms of your license agreement with Intel or your vendor. This file may be modified by the user, subject to the additional terms of the license agreement. @par Specification Reference: **/ /// @details /// Code in this file uses following variables: /// SCLK: ICC Clock number - optional /// WAKG: WAKE GPIO pad - optional /// Below objects should be defined according to the format described in PinDriverLib.asl /// RSTG: reset pin definition - mandatory /// PWRG: power GPIO pad - optional /// WAKP: Flag to indicate that power gating must not be performed if WAKE is enabled - optional /// @defgroup pcie_scope PCIe Root Port Scope **/ #define DTBT_TYPE_PCH 0x01 #define TBT_DATA_WIDTH 4 // This represent DATA WIDTH for Each TBT Controller in a Variable External(\MMRP, MethodObj) External(\MMTB, MethodObj) External(PDOF, MethodObj) External(PDON, MethodObj) External(\TVCF, MethodObj) External(\TVRF, MethodObj) // // AcpiPinDriverLib imports(from DSDT in platform) // External(\PIN.STA, MethodObj) External(\PIN.ON, MethodObj) External(\PIN.OFF, MethodObj) // // GpioLib imports(DSDT) // External(\_SB.SHPO, MethodObj) // // HSIO lib imports // External(\_SB.PSD0, MethodObj) External(\_SB.PSD3, MethodObj) // // External decalarations for optional objects. // Defined by board specific code. // External(WAKG) //WAKE GPIO pad External(PWRG) External(SCLK) External(WAKP) External(TUID) External(PSON) External(TBDC) External(NCB7) External(LASX) External(D3HT) External(L23E) External(L23R) External(DPGE) External(HPEX) External(PMEX) External(HPSX) External(PMSX) External(PDCX) External(PDSX) External(PSPX) External(TRDO) External(TRD3) External(TBPE) External(TOFF) External(TEDC) External(PCPB) // PCIe core power veto bitmask, default 0 - allow for core power removal Name(G2SD, 0) // Go2Sx done, set by GO2S, cleaned by _ON Name(RSTF, 0) // Reset Flag Name(CSEN, 0) // If enable wait for RTD3 Exit command respond in _PS0() method Name(PSHR, 0) // Global Variable to Save Power State Value of TBT HR Name(WKEN, 0) // WAKE enable on PCIe device. Method(_S0W, 0, Serialized) { Return(4) } // // TBT Debug Method - Scan hierarchy // Method(TSCH, 0, Serialized) { Store (\MMTB (SLOT, DTBT_TYPE_PCH), Local7) // TODO Make one generic copy OperationRegion(TBDM, SystemMemory, Local7, 0x550)// TBT HR PCICFG MMIO Field(TBDM,DWordAcc, NoLock, Preserve) { DIVI, 32, CMDR, 32, Offset(0x84), TBPS, 2, // PowerState of TBT Offset(0x548), TB2P, 32, P2TB, 32 } If(LNotEqual(VDID,0xFFFFFFFF)) { } If(LNotEqual(DIVI,0xFFFFFFFF)) { } Add(Local7, 0x00108000, Local7) // Advance 1 Bus 1 Dev No. Bus N+1 Device 1 OperationRegion(TDS0, SystemMemory, Local7, 0x100)// TBT DS0 PCICFG MMIO Field(TDS0,DWordAcc, NoLock, Preserve) { Offset (0), P0ID, 32, Offset(0xD0), , 29, LAI0, 1, // PCIe Link Active Indicator of DS port 0 Offset(0xD8), , 19, PDC0, 1, // PCIe Presence Detect Changed Indicator of DS port 0 , 2, PDS0, 1, // PCIe Presence Detect State Indicator of DS port 0 } If(LNotEqual(P0ID,0xFFFFFFFF)) { } Add(Local7, 0x00010000, Local7) // Advacne 2 Dev No. Bus N+1 Device 3 OperationRegion(TDS1, SystemMemory, Local7, 0x100)// TBT DS1 PCICFG MMIO Field(TDS1,DWordAcc, NoLock, Preserve) { Offset (0), P1ID, 32, Offset(0xD0), , 29, LAI1, 1, // PCIe Link Active Indicator of DS port 1 Offset(0xD8), , 19, PDC1, 1, // PCIe Presence Detect Changed Indicator of DS port 1 , 2, PDS1, 1, // PCIe Presence Detect State Indicator of DS port 1 } If(LNotEqual(P1ID,0xFFFFFFFF)) { } TVAL() } // // TBT Debug Method - Dump All Variables // Method(TVAL, 0, Serialized) { } Method (PPS0, 0, Serialized) { // Platform specific PCIe root port _PS0 Hook Function. TSCH() if (LEqual (CSEN, 1)) { Store (\MMRP (SLOT, DTBT_TYPE_PCH), Local7) OperationRegion(L23P,SystemMemory,Local7,0x100) Field(L23P,WordAcc, NoLock, Preserve) { Offset(0xA4),// PMCSR D3HT, 2, // PowerState } CSPL () Store (0, CSEN) // Disable _PS0 once called Store (PSHR, D3HT) // Store Back D3HT value Store (0, PSHR) } TSCH() } Method(PPS3, 0, Serialized) { // Platform specific PCIe root port _PS3 Hook Function. TSCH() } Method (_DSD, 0) { Return ( Package () { ToUUID("6211E2C0-58A3-4AF3-90E1-927A4E0C55A4"), Package () { Package (2) {"HotPlugSupportInD3", 1}, }, ToUUID("EFCC06CC-73AC-4BC3-BFF0-76143807C389"), Package () { Package (2) {"ExternalFacingPort", 1}, // Property 1: This is a TBT/CIO port Package (2) {"UID", TUID}, // Property 2: UID of the TBT RP on platform, range is: 0, 1, ..., NumOfTBTRP - 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 (TVCF (TUID, 2, TBT_DATA_WIDTH, TOFF), TOFF) } Else { /// If Staying in S0 If(LAnd(Arg0, Arg2)) ///- Check if Exiting D0 and arming for wake { ///- Set PME Store (1, WKEN) Store (TVCF (TUID, 1, TBT_DATA_WIDTH, TOFF), TOFF) } Else { ///- Disable runtime PME, either because staying in D0 or disabling wake Store (0, WKEN) Store (TVCF (TUID, 0, TBT_DATA_WIDTH, TOFF), TOFF) } } /** @defgroup pcie_dsw PCIE _DSW **/ } // End _DSW // // PCIe slot power resource definition // PowerResource(PXP, 0, 0) { Method(_STA, 0) { If (LEqual (VDID, 0xFFFFFFFF)) { Return(0) } Return(PSTA()) } Method(_ON) { //Store (TVCF (TUID, 1, TBT_DATA_WIDTH, TRDO), TRDO) TSCH() PON() //Store (TVCF (TUID, 0, TBT_DATA_WIDTH, TRDO), TRDO) TSCH() } Method(_OFF) { //Store (TVCF (TUID, 0, TBT_DATA_WIDTH, TRD3), TRD3) TSCH() POFF() //Store (TVCF (TUID, 1, TBT_DATA_WIDTH, TRD3), TRD3) TSCH() } } // // Returns the status of PCIe slot core power // Method(PSTA, 0) { // // RESET# assertion is mandatory for PCIe RTD3 // So if RESET# is asserted the whole slot is off // If(\PIN.STA(RSTG)) { Return(0) } Else { Return (1) } } Method (CSEX, 0, Serialized) { Store (\MMTB (SLOT, DTBT_TYPE_PCH), 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(200, Local1) Store(0x0209, P2TB) // Write SX_EXIT_TBT_CONNECTED to PCIe2TBT with Data parameter = 0x02 (TBT RTD3 EXIT Command) While (LGreater(Local1, 0)) { Store(Subtract(Local1, 1), Local1) Store(TB2P, Local2) If(LAnd(LEqual(Local2, 0xFFFFFFFF), LEqual(Local1, 0x1))) // Device gone { Return(0) } If(LAnd(LNotEqual(Local2, 0xFFFFFFFF), And(Local2, 1))) // Done { break } Sleep(5) } Store(0x0, P2TB) // Write 0 to PCIe2TBT Return (1) } // End of Method(CSEX, 0, Serialized) Method (CSPL, 0, Serialized) { Store (\MMTB (SLOT, DTBT_TYPE_PCH), 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 } // 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(CSPL, 0, Serialized) Method(PON, 0, Serialized) /// Turn on core power to PCIe Slot { Store (\MMTB (SLOT, DTBT_TYPE_PCH), Local6) OperationRegion(TBDI, SystemMemory, Local6, 0x550)// TBT HR PCICFG MMIO Field(TBDI,DWordAcc, NoLock, Preserve) { DIVI, 32, CMDR, 32, Offset(0x84), TBPS, 2, // PowerState of TBT Offset(0x548), TB2P, 32, P2TB, 32 } // Check RTD3 power enable, if already ON, no need to execute sx_exit If (TVRF (TUID, TBT_DATA_WIDTH, TBPE)) { Return() } Store(0,G2SD) // // dTBT special requirement on RTD3 exit: // 1. Guarantee that PCIe clock is running - MR clock request is asserted and BIOS can unmask the request and plus custom delay. // 2. Toggle RTD3 pin - This will indicate to MR that it can reset the PHY. Reset of the PHY requires a running clock. // 3. After 10ms de-assert the PERST (same as done today) // // // On RTD3 Exit, BIOS will instruct the PMC to Enable source clocks. // This is done through sending a PMC IPC command. // If (CondRefOf (\DTRC)) { If (\DTRC) { /// de-assert CLK_REQ MSK If (CondRefOf (SCLK)) { SPCO (SCLK, 1) } If (CondRefOf (\DTRD)) { Sleep (\DTRD) } } } /// Turn ON Power for PCIe Slot If (CondRefOf (PWRG)) { \PIN.ON (PWRG) Sleep (PEP0) } /// De-Assert Reset Pin \PIN.OFF(RSTG) Store(0, RSTF) // Clear Reset Flag Store(TVCF (TUID, 1, TBT_DATA_WIDTH, TBPE), TBPE) L23D() // Check if any TBT Endpoint Device was connected, if no TBT Endpoint Device is Connected, no need to execute sx_exit If (LEqual (TVRF (TUID, TBT_DATA_WIDTH, TEDC), 0)) { Return() } // TBT special sleep. Store (D3HT, PSHR) // Save D3HT Value to PSHR Global Variable Store (0, D3HT)// 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) } TSCH() If (LLessEqual(Local2, 0)) { } If ( LEqual (CSEX(), 1)) { If (CondRefOf (TBDC)) { If (LGreater (TBDC, 0)) { CSPL () } else { Store (1, CSEN) } } } // If ( LEqual (CSEX(), 1)) if (LEqual(CSEN, 0)) { Store (PSHR, D3HT) // Store Back D3HT value } If(CondRefOf(PDON)) { PDON() } } // End of ON Method(POFF, 0, Serialized) { /// Turn off core power to PCIe Slot If (LEqual (TVRF (TUID, TBT_DATA_WIDTH, TOFF), 0)) { Return() } Store (\MMTB (SLOT, DTBT_TYPE_PCH), Local6) OperationRegion(TBDI, SystemMemory, Local6, 0x550)// TBT HR PCICFG MMIO Field(TBDI,DWordAcc, NoLock, Preserve) { DIVI, 32, CMDR, 32, Offset(0x84), TBPS, 2, // PowerState of TBT Offset(0x548), TB2P, 32, P2TB, 32 } Add(Local6, 0x00108000, Local6) // Advance 1 Bus 1 Dev No. Bus N+1 Device 1 OperationRegion(DSP0, SystemMemory, Local6, 0x100)// TBT DS0 PCICFG MMIO Field(DSP0,DWordAcc, NoLock, Preserve) { Offset (0), P0ID, 32, Offset(0xD0), , 29, LAI0, 1, // PCIe Link Active Indicator of DS port 0 Offset(0xD8), , 19, PDC0, 1, // PCIe Presence Detect Changed Indicator of DS port 0 , 2, PDS0, 1, // PCIe Presence Detect State Indicator of DS port 0 } Add(Local6, 0x00010000, Local6) // Advacne 2 Dev No. Bus N+1 Device 3 OperationRegion(DSP1, SystemMemory, Local6, 0x100)// TBT DS1 PCICFG MMIO Field(DSP1,DWordAcc, NoLock, Preserve) { Offset (0), P1ID, 32, Offset(0xD0), , 29, LAI1, 1, // PCIe Link Active Indicator of DS port 1 Offset(0xD8), , 19, PDC1, 1, // PCIe Presence Detect Changed Indicator of DS port 1 , 2, PDS1, 1, // PCIe Presence Detect State Indicator of DS port 1 } If (Lgreater(TVRF (TUID, TBT_DATA_WIDTH, TOFF), 1)) { Store (TVCF (TUID, 0, TBT_DATA_WIDTH, TOFF), TOFF) Store(1, RSTF) // Set Reset Flag Return() } Store(D3HT, Local1) Store(0, D3HT)// D0 Store(P2TB, Local3) Store (TVCF (TUID, 0, TBT_DATA_WIDTH, TOFF), TOFF) Sleep(10) Store(TBPS, Local6) Store(0, TBPS) Sleep(10) Store(PDS0, Local2) // Store Device Presence under DS0 Store(PDS1, Local3) // Store Device Presence under DS1 TSCH() If(LAnd(LNotEqual(P0ID, 0xFFFFFFFF), LNotEqual(P1ID, 0xFFFFFFFF))) { If(LOr(LEqual(PDC0, 1), LEqual(PDC1, 1))) { Notify (^, 0) Return() } } // Updating TEDC value if any TBT Endpoint device is connected behind TUID TBT Controller. Store (TVCF (TUID, Or (PDS0, PDS1), TBT_DATA_WIDTH, TEDC), TEDC) Store(Local6, TBPS) Store(Local1, D3HT) // Back to Local1 DL23() // Assert Reset Pin // Reset pin is mandatory for correct PCIe RTD3 flow \PIN.ON(RSTG) Store(1, RSTF) // Set Reset Flag // // On RTD3 entry, BIOS will instruct the PMC to disable source clocks. // This is done through sending a PMC IPC command. // If (\DTRC) { /// assert CLK_REQ MSK If (CondRefOf (SCLK)) { SPCO (SCLK, 0) } If (CondRefOf (\DTRD)) { Sleep (\DTRD) } } Sleep (10) /// Power OFF for TBT If(CondRefOf(PWRG)) { // If WAKP has not been defined we can safely disable power. // If WAKP is defined this slot does not supply device with auxilary power and we have to keep primary power // to allow for WAKE. If WAKP is not equal to 0 and WKEN has been enabled do not disable the power. If(CondRefOf (WAKP)) { If(LOr(LEqual(WAKP, 0), LNot(WKEN))) { If(CondRefOf(PCPB)) { If(LEqual(PCPB, 0)) { \PIN.OFF(PWRG) } } Else { \PIN.OFF(PWRG) } } Else { } } Else { If(CondRefOf(PCPB)) { If(LEqual(PCPB, 0)) { \PIN.OFF(PWRG) } } Else { \PIN.OFF(PWRG) } } } // enable WAKE If(CondRefOf (WAKG)) { If(LAnd(LNotEqual(WAKG, 0), WKEN)) { \_SB.SHPO(WAKG, 0) } } Store(TVCF (TUID, 0, TBT_DATA_WIDTH, TBPE), TBPE) If (LEqual(\DTOE, 0)) { // Optimization not enabled, Sleep (DTRO) Sleep (\DTRO) } Else { If (LOr(LEqual(Local2, 1), LEqual(Local3, 1))) { // If there is a device present under DS0 or DS1, Sleep(DTRO) Sleep (\DTRO) } Else { // Otherwise, Sleep (1000) Sleep (1000) } } If(CondRefOf(PDOF)) { If (PSON) { PDOF() } } } // End of Method_OFF Method (NFRP, 0, Serialized) /// Notify root port { If (LEqual (VDID, 0xFFFFFFFF)) { Return () } Store (0, Local1) Store (0, Local2) If (LEqual (\DTFS, 0x01)) {// if Thunderbolt(TM) support is enabled Store (0, HPEX) //Hot Plug SCI Disable Store (0, PMEX) //Power Management SCI Enable Notify (^, 0) If (LEqual (PMSX, 1)) { //clear the PME SCI status bit Store (1, Local2) } Notify (^, 2) Store (1, Local1) // Enable clear status bit } If (LEqual (Local1, 1)) { Store (1, HPSX) If (LEqual (Local2, 1)) { Store (1, PMSX) } } }