blob: 2d40dc31e4331fd1662cef0e18c3712418c9dec0 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* The PCI-SIG engineering change requirement provides the ACPI additions for firmware latency
* optimization. Both of FW_RESET_TIME and FW_D3HOT_TO_D0_TIME are applicable to the upstream
* port of the USB4/TBT topology.
*/
/* Number of microseconds to wait after a conventional reset */
#define FW_RESET_TIME 50000
/* Number of microseconds to wait after data link layer active report */
#define FW_DL_UP_TIME 1
/* Number of microseconds to wait after a function level reset */
#define FW_FLR_RESET_TIME 1
/* Number of microseconds to wait from D3 hot to D0 transition */
#define FW_D3HOT_TO_D0_TIME 50000
/* Number of microseconds to wait after setting the VF enable bit */
#define FW_VF_ENABLE_TIME 1
OperationRegion (PXCS, SystemMemory, BASE(_ADR), 0x800)
Field (PXCS, AnyAcc, NoLock, Preserve)
{
VDID, 32,
Offset(0x50), /* LCTL - Link Control Register */
L0SE, 1, /* 0, L0s Entry Enabled */
, 3,
LDIS, 1, /* 1, Link Disable */
, 3,
Offset(0x52), /* LSTS - Link Status Register */
, 13,
LASX, 1, /* 0, Link Active Status */
Offset(0x5A), /* SLSTS[7:0] - Slot Status Register */
ABPX, 1, /* 0, Attention Button Pressed */
, 2,
PDCX, 1, /* 3, Presence Detect Changed */
, 2,
PDSX, 1, /* 6, Presence Detect State */
, 1,
DLSC, 1, /* 8, Data Link Layer State Changed */
Offset(0x60), /* RSTS - Root Status Register */
, 16,
PSPX, 1, /* 16, PME Status */
Offset(0xA4),
D3HT, 2, /* Power State */
Offset(0xD8), /* 0xD8, MPC - Miscellaneous Port Configuration Register */
, 30,
HPEX, 1, /* 30, Hot Plug SCI Enable */
PMEX, 1, /* 31, Power Management SCI Enable */
Offset(0xE2), /* 0xE2, RPPGEN - Root Port Power Gating Enable */
, 2,
L23E, 1, /* 2, L23_Rdy Entry Request (L23ER) */
L23R, 1, /* 3, L23_Rdy to Detect Transition (L23R2DT) */
Offset(0x420), /* 0x420, PCIEPMECTL (PCIe PM Extension Control) */
, 30,
DPGE, 1, /* PCIEPMECTL[30]: Disabled, Detect and L23_Rdy State PHY Lane */
/* Power Gating Enable (DLSULPPGE) */
Offset(0x5BC), /* 0x5BC, PCIE ADVMCTRL */
, 3,
RPER, 1, /* RTD3PERST[3] */
RPFE, 1, /* RTD3PFETDIS[4] */
}
Field (PXCS, AnyAcc, NoLock, WriteAsZeros)
{
Offset(0xDC), /* 0xDC, SMSCS - SMI/SCI Status Register */
, 30,
HPSX, 1, /* 30, Hot Plug SCI Status */
PMSX, 1 /* 31, Power Management SCI Status */
}
/*
* _DSM Device Specific Method
*
* Arg0: UUID Unique function identifier
* Arg1: Integer Revision Level
* Arg2: Integer Function Index (0 = Return Supported Functions)
* Arg3: Package Parameters
*/
Method (_DSM, 4, Serialized)
{
Return (Buffer() { 0x00 })
}
/*
* A bitmask of functions support
*/
Name(OPTS, Buffer(2) {0, 0})
Device (PXSX)
{
Name (_ADR, 0x00000000)
/*
* _DSM Device Specific Method
*
* Arg0: UUID: E5C937D0-3553-4d7a-9117-EA4D19C3434D
* Arg1: Revision ID: 3
* Arg2: Function index: 0, 9
* Arg3: Empty package
*/
Method (_DSM, 4, Serialized)
{
If (Arg0 == ToUUID("E5C937D0-3553-4d7a-9117-EA4D19C3434D")) {
If (Arg1 >= 3) {
If (Arg2 == 0) {
/*
* Function index: 0
* Standard query - A bitmask of functions supported
*/
CreateBitField(OPTS, 9, FUN9)
FUN9 = 1
Return (OPTS)
} ElseIf (Arg2 == 9) {
/*
* Function index: 9
* Specifying device readiness durations
*/
Return (Package() { FW_RESET_TIME, FW_DL_UP_TIME,
FW_FLR_RESET_TIME, FW_D3HOT_TO_D0_TIME,
FW_VF_ENABLE_TIME })
}
}
}
Return (Buffer() { 0x0 })
}
Method (_PRW, 0)
{
Return (Package() { 0x69, 4 })
}
}
Method (_DSW, 3)
{
/* If entering Sx (Arg1 > 1), need to skip TCSS D3Cold & TBT RTD3/D3Cold. */
If ((TUID == 0) || (TUID == 1)) {
\_SB.PCI0.TDM0.SD3C = Arg1
} Else {
\_SB.PCI0.TDM1.SD3C = Arg1
}
C2PM (Arg0, Arg1, Arg2, DCPM)
}
Method (_PRW, 0)
{
Return (Package() { 0x69, 4 })
}
/*
* Sub-Method of _L61 Hot-Plug event
* _L61 event handler should invoke this method to support HotPlug wake event from TBT RP.
*/
Method (HPEV, 0, Serialized)
{
If ((VDID != 0xFFFFFFFF) && HPSX) {
If ((PDCX == 1) && (DLSC == 1)) {
/* Clear all status bits first. */
PDCX = 1
HPSX = 1
/* Perform proper notification to the OS. */
Notify (^, 0)
} Else {
/* False event. Clear Hot-Plug Status, then exit. */
HPSX = 1
}
}
}
/*
* Power Management routine for D3
*/
Name (STAT, 0x1) /* Variable to save power state 1 - D0, 0 - D3C */
/*
* RTD3 Exit Method to bring TBT controller out of RTD3 mode.
*/
Method (D3CX, 0, Serialized)
{
If (STAT == 0x1) {
Return
}
RPFE = 0 /* Set RTD3PFETDIS = 0 */
RPER = 0 /* Set RTD3PERST = 0 */
L23R = 1 /* Set L23r2dt = 1 */
/*
* Poll for L23r2dt == 0. Wait for transition to Detect.
*/
Local0 = 0
Local1 = L23R
While (Local1) {
If (Local0 > 20) {
Break
}
Sleep(5)
Local0++
Local1 = L23R
}
STAT = 0x1
}
/*
* RTD3 Entry method to enable TBT controller RTD3 mode.
*/
Method (D3CE, 0, Serialized)
{
If (STAT == 0x0) {
Return
}
L23E = 1 /* Set L23er = 1 */
/* Poll until L23er == 0 */
Local0 = 0
Local1 = L23E
While (Local1) {
If (Local0 > 20) {
Break
}
Sleep(5)
Local0++
Local1 = L23E
}
STAT = 0 /* D3Cold */
RPFE = 1 /* Set RTD3PFETDIS = 1 */
RPER = 1 /* Set RTD3PERST = 1 */
}
Method (_PS0, 0, Serialized)
{
HPEV () /* Check and handle Hot Plug SCI status. */
If (HPEX == 1) {
HPEX = 0 /* Disable Hot Plug SCI */
}
HPME () /* Check and handle PME SCI status */
If (PMEX == 1) {
PMEX = 0 /* Disable Power Management SCI */
}
}
Method (_PS3, 0, Serialized)
{
/* Check it is hotplug SCI or not, then clear PDC accordingly */
If (PDCX == 1) {
If (DLSC == 0) {
/* Clear PDC since it is not a hotplug. */
PDCX = 1
}
}
If (HPEX == 0) {
HPEX = 1 /* Enable Hot Plug SCI. */
HPEV () /* Check and handle Hot Plug SCI status. */
}
If (PMEX == 0) {
PMEX = 1 /* Enable Power Management SCI. */
HPME () /* Check and handle PME SCI status. */
}
}
Method (_S0W, 0x0, NotSerialized)
{
If (S0IX == 1) {
Return (0x4)
} Else {
Return (0x3)
}
}
Method (_PR0)
{
If (S0IX == 1) {
If ((TUID == 0) || (TUID == 1)) {
Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT0 })
} Else {
Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT1 })
}
} Else {
If ((TUID == 0) || (TUID == 1)) {
Return (Package() { \_SB.PCI0.TBT0 })
} Else {
Return (Package() { \_SB.PCI0.TBT1 })
}
}
}
Method (_PR3)
{
If (S0IX == 1) {
If ((TUID == 0) || (TUID == 1)) {
Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT0 })
} Else {
Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT1 })
}
} Else {
If ((TUID == 0) || (TUID == 1)) {
Return (Package() { \_SB.PCI0.TBT0 })
} Else {
Return (Package() { \_SB.PCI0.TBT1 })
}
}
}
/*
* PCI_EXP_STS Handler for PCIE Root Port
*/
Method (HPME, 0, Serialized)
{
If ((VDID != 0xFFFFFFFF) && (PMSX == 1)) { /* if port exists and PME SCI Status set */
/*
* Notify child device; this will cause its driver to clear PME_Status from
* device.
*/
Notify (PXSX, 0x2)
PMSX = 1 /* clear rootport's PME SCI status */
/*
* Consume one pending PME notification to prevent it from blocking the queue.
*/
PSPX = 1
Return (0x01)
}
Return (0x00)
}