diff options
author | John Zhao <john.zhao@intel.com> | 2020-03-16 15:33:06 -0700 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2020-04-22 13:47:05 +0000 |
commit | ca584085d774b47c01bbc32cdb28678f7dc6e652 (patch) | |
tree | 0b045e832165cc8d68b78998f42f9a574fc71f78 /src/soc/intel/tigerlake/acpi | |
parent | e8abb5ab8887969498f9953e76b7e0f4c68d3e47 (diff) | |
download | coreboot-ca584085d774b47c01bbc32cdb28678f7dc6e652.tar.xz |
soc/intel/tigerlake: Configure TCSS power management
Add Type-C subsystem power management support for RTD3.
BUG=b:140290596
TEST=Include "tcss.asl" in platform "dsdt.asl" for coreboot build
with the firmware CM. Added acpi debug and booted to kernel. Probed
devices PM_STATE transition from D0 to D3 entry/exit while system at S0.
TBT PCIe root ports: 00:07.0/00:07.1/00:07.2/00:07.3, offset:0xA4, PM_STATE:D3HT.
xhci:00:0d.0, offset:0x74, PM_STATE:D0D3.
dma:00:0d.2/00.0d.3, offset:0x84, PM_STATE:PMST.
Verified xhci/dma/pcie root ports power runtime_status to be suspended and suspended
time tick through /sys/bus/pci/devices/bus:device:func/power.
Change-Id: I127d3700ad426a44639ee93b4477be6638b42e1b
Signed-off-by: John Zhao <john.zhao@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/39785
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Diffstat (limited to 'src/soc/intel/tigerlake/acpi')
-rw-r--r-- | src/soc/intel/tigerlake/acpi/tcss.asl | 784 | ||||
-rw-r--r-- | src/soc/intel/tigerlake/acpi/tcss_dma.asl | 227 | ||||
-rw-r--r-- | src/soc/intel/tigerlake/acpi/tcss_pcierp.asl | 315 | ||||
-rw-r--r-- | src/soc/intel/tigerlake/acpi/tcss_xhci.asl | 138 |
4 files changed, 1464 insertions, 0 deletions
diff --git a/src/soc/intel/tigerlake/acpi/tcss.asl b/src/soc/intel/tigerlake/acpi/tcss.asl new file mode 100644 index 0000000000..9f03aa94dd --- /dev/null +++ b/src/soc/intel/tigerlake/acpi/tcss.asl @@ -0,0 +1,784 @@ +/* + * This file is part of the coreboot project. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include <soc/iomap.h> + +/* + * Type C Subsystem(TCSS) topology provides Runtime D3 support for USB host controller(xHCI), + * USB device controller(xDCI), Thunderbolt DMA devices and Thunderbolt PCIe controllers. + * PCIe RP0/RP1 is grouped with DMA0 and PCIe RP2/RP3 is grouped with DMA1. + */ +#define TCSS_TBT_PCIE0_RP0 0 +#define TCSS_TBT_PCIE0_RP1 1 +#define TCSS_TBT_PCIE0_RP2 2 +#define TCSS_TBT_PCIE0_RP3 3 +#define TCSS_XHCI 4 +#define TCSS_XDCI 5 +#define TCSS_DMA0 6 +#define TCSS_DMA1 7 + +/* + * MAILBOX_BIOS_CMD_TCSS_DEVEN_INTERFACE + * Command code 0x15 + * Description: Gateway command for handling TCSS DEVEN clear/restore. + * Field PARAM1[15:8] of the _INTERFACE register is used in this command to select from + * a pre-defined set of subcommands. + */ +#define MAILBOX_BIOS_CMD_TCSS_DEVEN_INTERFACE 0x00000015 +#define TCSS_DEVEN_MAILBOX_SUBCMD_GET_STATUS 0 /* Sub-command 0 */ +#define TCSS_DEVEN_MAILBOX_SUBCMD_TCSS_CHANGE_REQ 1 /* Sub-command 1 */ + +#define TCSS_IOM_ACK_TIMEOUT_IN_MS 100 + +Scope (\_SB) +{ + /* Device base address */ + Method (BASE, 1) + { + Local0 = Arg0 & 0x7 /* Function number */ + Local1 = (Arg0 >> 16) & 0x1F /* Device number */ + Local2 = (Local0 << 12) + (Local1 << 15) + Local3 = \_SB.PCI0.GPCB() + Local2 + Return (Local3) + } + + /* + * Define PCH ACPIBASE I/O as an ACPI operating region. The base address can be + * found in Device 31, Function 2, Offset 40h. + */ + OperationRegion (PMIO, SystemIO, PCH_PWRM_BASE_ADDRESS, 0x80) + Field (PMIO, ByteAcc, NoLock, Preserve) { + Offset(0x6C), /* 0x6C, General Purpose Event 0 Status [127:96] */ + , 19, + CPWS, 1, /* CPU WAKE STATUS */ + Offset(0x7C), /* 0x7C, General Purpose Event 0 Enable [127:96] */ + , 19, + CPWE, 1 /* CPU WAKE EN */ + } + + Name (C2PW, 0) /* Set default value to 0. */ + + /* + * C2PM (CPU to PCH Method) + * + * This object is Enable/Disable GPE_CPU_WAKE_EN. + * Arguments: (4) + * Arg0 - An Integer containing the device wake capability + * Arg1 - An Integer containing the target system state + * Arg2 - An Integer containing the target device state + * Arg3 - An Integer containing the request device type + * Return Value: + * return 0 + */ + Method (C2PM, 4, NotSerialized) + { + Local0 = 0x1 << Arg3 + /* This method is used to enable/disable wake from Tcss Device (WKEN). */ + If (Arg0 && Arg1) + { /* If entering Sx and enabling wake, need to enable WAKE capability. */ + If (CPWE == 0) { /* If CPU WAKE EN is not set, Set it. */ + If (CPWS) { /* If CPU WAKE STATUS is set, Clear it. */ + /* Clear CPU WAKE STATUS by writing 1. */ + CPWS = 1 + } + CPWE = 1 /* Set CPU WAKE EN by writing 1. */ + } + If ((C2PW & Local0) == 0) { + /* Set Corresponding Device En BIT in C2PW. */ + C2PW |= Local0 + } + } Else { /* If Staying in S0 or Disabling Wake. */ + If (Arg0 || Arg2) { /* Check if Exiting D0 and arming for wake. */ + /* If CPU WAKE EN is not set, Set it. */ + If (CPWE == 0) { + /* If CPU WAKE STATUS is set, Clear it. */ + If (CPWS) { + /* Clear CPU WAKE STATUS by writing 1. */ + CPWS = 1 + } + CPWE = 1 /* Set CPU WAKE EN by writing 1. */ + } + If ((C2PW & Local0) == 0) { + /* Set Corresponding Device En BIT in C2PW. */ + C2PW |= Local0 + } + } Else { + /* + * Disable runtime PME, either because staying in D0 or + * disabling wake. + */ + If ((C2PW & Local0) != 0) { + /* + * Clear Corresponding Device En BIT in C2PW. + */ + C2PW &= ~Local0 + } + If ((CPWE != 0) && (C2PW == 0)) { + /* + * If CPU WAKE EN is set, Clear it. Clear CPU WAKE EN + * by writing 0. + */ + CPWE = 0 + } + } + } + Return (0) + } +} + +Scope (\_SB.PCI0) +{ + /* + * Operation region defined to access the IOM REGBAR. Get the MCHBAR in offset + * 0x48 in B0:D0:F0. REGBAR Base address is in offset 0x7110 of MCHBAR. + */ + OperationRegion (MBAR, SystemMemory, (GMHB() + 0x7100), 0x1000) + Field (MBAR, ByteAcc, NoLock, Preserve) + { + Offset(0x10), + RBAR, 64 /* RegBar, offset 0x7110 in MCHBAR */ + } + Field (MBAR, DWordAcc, NoLock, Preserve) + { + Offset(0x304), /* PRIMDN_MASK1_0_0_0_MCHBAR_IMPH, offset 0x7404 */ + , 31, + TCD3, 1 /* [31:31] TCSS IN D3 bit */ + } + + /* + * Operation region defined to access the pCode mailbox interface. Get the MCHBAR + * in offset 0x48 in B0:D0:F0. MMIO address is in offset 0x5DA0 of MCHBAR. + */ + OperationRegion (PBAR, SystemMemory, (GMHB() + 0x5DA0), 0x08) + Field (PBAR, DWordAcc, NoLock, Preserve) + { + PMBD, 32, /* pCode MailBox Data, offset 0x5DA0 in MCHBAR */ + PMBC, 8, /* pCode MailBox Command, [7:0] of offset 0x5DA4 in MCHBAR */ + PSCM, 8, /* pCode MailBox Sub-Command, [15:8] of offset 0x5DA4 in MCHBAR */ + , 15, /* Reserved */ + PMBR, 1 /* pCode MailBox RunBit, [31:31] of offset 0x5DA4 in MCHBAR */ + } + + /* + * Poll pCode MailBox Ready + * + * Return 0xFF - Timeout + * 0x00 - Ready + */ + Method (PMBY, 0) + { + Local0 = 0 + While (PMBR && (Local0 < 1000)) { + Local0++ + Stall (1) + } + If (Local0 == 1000) { + Printf("Timeout occurred.") + Return (0xFF) + } + Return (0) + } + + /* + * Method to send pCode MailBox command TCSS_DEVEN_MAILBOX_SUBCMD_GET_STATUS + * + * Result will be updated in DATA[1:0] + * DATA[0:0] TCSS_DEVEN_CURRENT_STATE: + * 0 - TCSS Deven in normal state. + * 1 - TCSS Deven is cleared by BIOS Mailbox request. + * DATA[1:1] TCSS_DEVEN_REQUEST_STATUS: + * 0 - IDLE. TCSS DEVEN has reached its final requested state. + * 1 - In Progress. TCSS DEVEN is currently in progress of switching state + * according to given request (bit 0 reflects source state). + * + * Return 0x00 - TCSS Deven in normal state + * 0x01 - TCSS Deven is cleared by BIOS Mailbox request + * 0x1x - TCSS Deven is in progress of switching state according to given request + * 0xFE - Command timeout + * 0xFF - Command corrupt + */ + Method (DSGS, 0) + { + If ((PMBY () == 0)) { + PMBC = MAILBOX_BIOS_CMD_TCSS_DEVEN_INTERFACE + PSCM = TCSS_DEVEN_MAILBOX_SUBCMD_GET_STATUS + PMBR = 1 + If (PMBY () == 0) { + Local0 = PMBD + Local1 = PMBC + Stall (10) + If ((Local0 != PMBD) || (Local1 != PMBC)) { + Printf("pCode MailBox is corrupt.") + Return (0xFF) + } + Return (Local0) + } Else { + Printf("pCode MailBox is not ready.") + Return (0xFE) + } + } Else { + Printf("pCode MailBox is not ready.") + Return (0xFE) + } + } + + /* + * Method to send pCode MailBox command TCSS_DEVEN_MAILBOX_SUBCMD_TCSS_CHANGE_REQ + * + * Arg0 : 0 - Restore to previously saved value of TCSS DEVEN + * 1 - Save current TCSS DEVEN value and clear it + * + * Return 0x00 - MAILBOX_BIOS_CMD_CLEAR_TCSS_DEVEN command completed + * 0xFD - Input argument is invalid + * 0xFE - Command timeout + * 0xFF - Command corrupt + */ + Method (DSCR, 1) + { + If (Arg0 > 1) { + Printf("pCode MailBox is corrupt.") + Return (0xFD) + } + If ((PMBY () == 0)) { + PMBC = MAILBOX_BIOS_CMD_TCSS_DEVEN_INTERFACE + PSCM = TCSS_DEVEN_MAILBOX_SUBCMD_TCSS_CHANGE_REQ + PMBD = Arg0 + PMBR = 1 + If ((PMBY () == 0)) { + Local0 = PMBD + Local1 = PMBC + Stall (10) + If ((Local0 != PMBD) || (Local1 != PMBC)) { + Printf("pCode MailBox is corrupt.") + Return (0xFF) + } + /* Poll TCSS_DEVEN_REQUEST_STATUS, timeout value is 10ms. */ + Local0 = 0 + While ((DSGS () & 0x10) && (Local0 < 100)) { + Stall (100) + Local0++ + } + If (Local0 == 100) { + Printf("pCode MailBox is not ready.") + Return (0xFE) + } Else { + Return (0x00) + } + } Else { + Printf("pCode MailBox is not ready.") + Return (0xFE) + } + } Else { + Printf("pCode MailBox is not ready.") + Return (0xFE) + } + } + + /* + * IOM REG BAR Base address is in offset 0x7110 in MCHBAR. + */ + Method (IOMA, 0) + { + Return (^RBAR & ~0x1) + } + + /* + * From RegBar Base, IOM_TypeC_SW_configuration_1 is in offset 0xC10040, where + * 0x40 is the register offset. + */ + OperationRegion (IOMR, SystemMemory, (IOMA() + 0xC10000), 0x100) + Field (IOMR, DWordAcc, NoLock, Preserve) + { + Offset(0x40), + , 15, + TD3C, 1, /* [15:15] Type C D3 cold bit */ + TACK, 1, /* [16:16] IOM Acknowledge bit */ + DPOF, 1, /* [17:17] Set 1 to indicate IOM, all the */ + /* display is OFF, clear otherwise */ + Offset(0x70), /* Pyhsical addr is offset 0x70. */ + IMCD, 32, /* R_SA_IOM_BIOS_MAIL_BOX_CMD */ + IMDA, 32 /* R_SA_IOM_BIOS_MAIL_BOX_DATA */ + } + + /* + * Below is a variable to store devices connect state for TBT PCIe RP before + * entering D3 cold. + * Value 0 - no device connected before enter D3 cold, no need to send + * CONNECT_TOPOLOGY in D3 cold exit. + * Value 1 - has device connected before enter D3 cold, need to send + * CONNECT_TOPOLOGY in D3 cold exit. + */ + Name (CTP0, 0) /* Variable of device connecet status for TBT0 group. */ + Name (CTP1, 0) /* Variable of device connecet status for TBT1 group. */ + + /* + * TBT Group0 ON method + */ + Method (TG0N, 0) + { + If (\_SB.PCI0.TDM0.VDID == 0xFFFFFFFF) { + Printf("TDM0 does not exist.") + } + + If (\_SB.PCI0.TDM0.STAT == 0) { + /* DMA0 is in D3Cold early. */ + \_SB.PCI0.TDM0.D3CX() /* RTD3 Exit */ + + Printf("Bring TBT RPs out of D3Code.") + If (\_SB.PCI0.TRP0.VDID != 0xFFFFFFFF) { + /* RP0 D3 cold exit. */ + \_SB.PCI0.TRP0.D3CX() + } + If (\_SB.PCI0.TRP1.VDID != 0xFFFFFFFF) { + /* RP1 D3 cold exit. */ + \_SB.PCI0.TRP1.D3CX() + } + + /* + * Need to send Connect-Topology command when TBT host + * controller back to D0 from D3. + */ + If (\_SB.PCI0.TDM0.ALCT == 1) { + If (CTP0 == 1) { + /* + * Send Connect-Topology command if there is + * device present on PCIe RP. + */ + \_SB.PCI0.TDM0.CNTP() + + /* Indicate to wait Connect-Topology command. */ + \_SB.PCI0.TDM0.WACT = 1 + + /* Clear the connect states. */ + CTP0 = 0 + } + /* Disallow to send Connect-Topology command. */ + \_SB.PCI0.TDM0.ALCT = 0 + } + } Else { + Printf("Drop TG0N due to it is already exit D3 cold.") + } + /* TBT RTD3 exit 10ms delay. */ + Sleep (10) + } + + /* + * TBT Group0 OFF method + */ + Method (TG0F, 0) + { + If (\_SB.PCI0.TDM0.VDID == 0xFFFFFFFF) { + Printf("TDM0 does not exist.") + } + + If (\_SB.PCI0.TDM0.STAT == 1) { + /* DMA0 is not in D3Cold now. */ + \_SB.PCI0.TDM0.D3CE() /* Enable DMA RTD3 */ + + Printf("Push TBT RPs to D3Cold together") + If (\_SB.PCI0.TRP0.VDID != 0xFFFFFFFF) { + If (\_SB.PCI0.TRP0.PDSX == 1) { + CTP0 = 1 + } + /* Put RP0 to D3 cold. */ + \_SB.PCI0.TRP0.D3CE() + } + If (\_SB.PCI0.TRP1.VDID != 0xFFFFFFFF) { + If (\_SB.PCI0.TRP1.PDSX == 1) { + CTP0 = 1 + } + /* Put RP1 to D3 cold. */ + \_SB.PCI0.TRP1.D3CE() + } + } + } + + /* + * TBT Group1 ON method + */ + Method (TG1N, 0) + { + If (\_SB.PCI0.TDM1.VDID == 0xFFFFFFFF) { + Printf("TDM1 does not exist.") + } + + If (\_SB.PCI0.TDM1.STAT == 0) { + /* DMA1 is in D3Cold early. */ + \_SB.PCI0.TDM1.D3CX() /* RTD3 Exit */ + + Printf("Bring TBT RPs out of D3Code.") + If (\_SB.PCI0.TRP2.VDID != 0xFFFFFFFF) { + /* RP2 D3 cold exit. */ + \_SB.PCI0.TRP2.D3CX() + } + If (\_SB.PCI0.TRP3.VDID != 0xFFFFFFFF) { + /* RP3 D3 cold exit. */ + \_SB.PCI0.TRP3.D3CX() + } + + /* + * Need to send Connect-Topology command when TBT host + * controller back to D0 from D3. + */ + If (\_SB.PCI0.TDM1.ALCT == 1) { + If (CTP1 == 1) { + /* + * Send Connect-Topology command if there is + * device present on PCIe RP. + */ + \_SB.PCI0.TDM1.CNTP() + + /* Indicate to wait Connect-Topology command. */ + \_SB.PCI0.TDM1.WACT = 1 + + /* Clear the connect states. */ + CTP1 = 0 + } + /* Disallow to send Connect-Topology cmd. */ + \_SB.PCI0.TDM1.ALCT = 0 + } + } Else { + Printf("Drop TG1N due to it is already exit D3 cold.") + } + /* TBT RTD3 exit 10ms delay. */ + Sleep (10) + } + + /* + * TBT Group1 OFF method + */ + Method (TG1F, 0) + { + If (\_SB.PCI0.TDM1.VDID == 0xFFFFFFFF) { + Printf("TDM1 does not exist.") + } + + If (\_SB.PCI0.TDM1.STAT == 1) { + /* DMA1 is not in D3Cold now */ + \_SB.PCI0.TDM1.D3CE() /* Enable DMA RTD3. */ + + Printf("Push TBT RPs to D3Cold together") + If (\_SB.PCI0.TRP2.VDID != 0xFFFFFFFF) { + If (\_SB.PCI0.TRP2.PDSX == 1) { + CTP1 = 1 + } + /* Put RP2 to D3 cold. */ + \_SB.PCI0.TRP2.D3CE() + } + If (\_SB.PCI0.TRP3.VDID != 0xFFFFFFFF) { + If (\_SB.PCI0.TRP3.PDSX == 1) { + CTP1 = 1 + } + /* Put RP3 to D3 cold */ + \_SB.PCI0.TRP3.D3CE() + } + } + } + + PowerResource (TBT0, 5, 1) + { + Method (_STA, 0) + { + Return (\_SB.PCI0.TDM0.STAT) + } + + Method (_ON, 0) + { + TG0N() + } + + Method (_OFF, 0) + { + If (\_SB.PCI0.TDM0.SD3C == 0) { + TG0F() + } + } + } + + PowerResource (TBT1, 5, 1) + { + Method (_STA, 0) + { + Return (\_SB.PCI0.TDM1.STAT) + } + + Method (_ON, 0) + { + TG1N() + } + + Method (_OFF, 0) + { + If (\_SB.PCI0.TDM1.SD3C == 0) { + TG1F() + } + } + } + + Method (TCON, 0) + { + /* Reset IOM D3 cold bit if it is in D3 cold now. */ + If (TD3C == 1) /* It was in D3 cold before. */ + { + /* Reset IOM D3 cold bit. */ + TD3C = 0 /* Request IOM for D3 cold exit sequence. */ + Local0 = 0 /* Time check counter variable */ + /* Wait for ack, the maximum wait time for the ack is 100 msec. */ + While ((TACK != 0) && (Local0 < TCSS_IOM_ACK_TIMEOUT_IN_MS)) { + /* + * Wait in this loop until TACK becomes 0 with timeout + * TCSS_IOM_ACK_TIMEOUT_IN_MS by default. + */ + Sleep (1) /* Delay of 1ms. */ + Local0++ + } + + If (Local0 == TCSS_IOM_ACK_TIMEOUT_IN_MS) { + Printf("Error: Error: Timeout occurred.") + } + Else + { + /* + * Program IOP MCTP Drop (TCSS_IN_D3) after D3 cold exit and + * acknowledgement by IOM. + */ + TCD3 = 0 + /* + * If the TCSS Deven is cleared by BIOS Mailbox request, then + * restore to previously saved value of TCSS DEVNE. + */ + Local0 = 0 + While (\_SB.PCI0.TXHC.VDID == 0xFFFFFFFF) { + If (DSGS () == 1) { + DSCR (0) + } + Local0++ + If (Local0 == 5) { + Printf("pCode mailbox command failed.") + Break + } + } + } + } + Else { + Printf("Drop TCON due to it is already exit D3 cold.") + } + } + + Method (TCOF, 0) + { + If ((\_SB.PCI0.TXHC.SD3C != 0) || (\_SB.PCI0.TDM0.SD3C != 0) + || (\_SB.PCI0.TDM1.SD3C != 0)) + { + Printf("Skip D3C entry.") + Return + } + + /* + * If the TCSS Deven in normal state, then Save current TCSS DEVEN value and + * clear it. + */ + Local0 = 0 + While (\_SB.PCI0.TXHC.VDID != 0xFFFFFFFF) { + If (DSGS () == 0) { + DSCR (1) + } + Local0++ + If (Local0 == 5) { + Printf("pCode mailbox command failed.") + Break + } + } + + /* + * Program IOM MCTP Drop (TCSS_IN_D3) in D3Cold entry before entering D3 cold. + */ + TCD3 = 1 + + /* Request IOM for D3 cold entry sequence. */ + TD3C = 1 + } + + PowerResource (D3C, 5, 0) + { + /* + * Variable to save power state + * 1 - TC Cold request cleared. + * 0 - TC Cold request sent. + */ + Name (STAT, 0x1) + + Method (_STA, 0) + { + Return (STAT) + } + + Method (_ON, 0) + { + \_SB.PCI0.TCON() + STAT = 1 + } + + Method (_OFF, 0) + { + \_SB.PCI0.TCOF() + STAT = 0 + } + } + + /* + * TCSS xHCI device + */ + Device (TXHC) + { + Name (_ADR, 0x000D0000) + Name (_DDN, "North XHCI controller") + Name (_STR, Unicode ("North XHCI controller")) + Name (DCPM, TCSS_XHCI) + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + #include "tcss_xhci.asl" + } + + /* + * TCSS DMA0 device + */ + Device (TDM0) + { + Name (_ADR, 0x000D0002) + Name (_DDN, "TBT DMA0 controller") + Name (_STR, Unicode ("TBT DMA0 controller")) + Name (DUID, 0) /* TBT DMA number */ + Name (DCPM, TCSS_DMA0) + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + #include "tcss_dma.asl" + } + + /* + * TCSS DMA1 device + */ + Device (TDM1) + { + Name (_ADR, 0x000D0003) + Name (_DDN, "TBT DMA1 controller") + Name (_STR, Unicode ("TBT DMA1 controller")) + Name (DUID, 1) /* TBT DMA number */ + Name (DCPM, TCSS_DMA1) + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + #include "tcss_dma.asl" + } + + /* + * TCSS PCIE Root Port #00 + */ + Device (TRP0) + { + Name (_ADR, 0x00070000) + Name (TUID, 0) /* TBT PCIE RP Number 0 for RP00 */ + Name (LTEN, 0) /* Latency Tolerance Reporting Mechanism, 0:Disable, 1:Enable */ + Name (LMSL, 0) /* PCIE LTR max snoop Latency */ + Name (LNSL, 0) /* PCIE LTR max no snoop Latency */ + Name (DCPM, TCSS_TBT_PCIE0_RP0) + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + Method (_INI) + { + LTEN = 0 + LMSL = 0x88C8 + LNSL = 0x88C8 + } + #include "tcss_pcierp.asl" + } + + /* + * TCSS PCIE Root Port #01 + */ + Device (TRP1) + { + Name (_ADR, 0x00070001) + Name (TUID, 1) /* TBT PCIE RP Number 1 for RP01 */ + Name (LTEN, 0) /* Latency Tolerance Reporting Mechanism, 0:Disable, 1:Enable */ + Name (LMSL, 0) /* PCIE LTR max snoop Latency */ + Name (LNSL, 0) /* PCIE LTR max no snoop Latency */ + Name (DCPM, TCSS_TBT_PCIE0_RP1) + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + Method (_INI) + { + LTEN = 0 + LMSL = 0x88C8 + LNSL = 0x88C8 + } + #include "tcss_pcierp.asl" + } + + /* + * TCSS PCIE Root Port #02 + */ + Device (TRP2) + { + Name (_ADR, 0x00070002) + Name (TUID, 2) /* TBT PCIE RP Number 2 for RP02 */ + Name (LTEN, 0) /* Latency Tolerance Reporting Mechanism, 0:Disable, 1:Enable */ + Name (LMSL, 0) /* PCIE LTR max snoop Latency */ + Name (LNSL, 0) /* PCIE LTR max no snoop Latency */ + Name (DCPM, TCSS_TBT_PCIE0_RP2) + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + Method (_INI) + { + LTEN = 0 + LMSL = 0x88C8 + LNSL = 0x88C8 + } + #include "tcss_pcierp.asl" + } + + /* + * TCSS PCIE Root Port #03 + */ + Device (TRP3) + { + Name (_ADR, 0x00070003) + Name (TUID, 3) /* TBT PCIE RP Number 3 for RP03 */ + Name (LTEN, 0) /* Latency Tolerance Reporting Mechanism, 0:Disable, 1:Enable */ + Name (LMSL, 0) /* PCIE LTR max snoop Latency */ + Name (LNSL, 0) /* PCIE LTR max no snoop Latency */ + Name (DCPM, TCSS_TBT_PCIE0_RP3) + + Method (_STA, 0x0, NotSerialized) + { + Return (0x0F) + } + Method (_INI) + { + LTEN = 0 + LMSL = 0x88C8 + LNSL = 0x88C8 + } + #include "tcss_pcierp.asl" + } +} diff --git a/src/soc/intel/tigerlake/acpi/tcss_dma.asl b/src/soc/intel/tigerlake/acpi/tcss_dma.asl new file mode 100644 index 0000000000..a2f86baf09 --- /dev/null +++ b/src/soc/intel/tigerlake/acpi/tcss_dma.asl @@ -0,0 +1,227 @@ +/* + * This file is part of the coreboot project. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +OperationRegion (DPME, SystemMemory, BASE(_ADR), 0x100) +Field (DPME, AnyAcc, NoLock, Preserve) +{ + VDID, 32, + Offset(0x84), /* 0x84, DMA CFG PM CAP */ + PMST, 2, /* 1:0, PM_STATE */ + , 6, + PMEE, 1, /* 8, PME_EN */ + , 6, + PMES, 1, /* 15, PME_STATUS */ + Offset(0xC8), /* 0xC8, TBT NVM FW Revision */ + , 31, + INFR, 1, /* TBT NVM FW Ready */ + Offset(0xEC), /* 0xEC, TBT TO PCIE Register */ + TB2P, 32, /* TBT to PCIe */ + P2TB, 32, /* PCIe to TBT */ + Offset(0xFC), /* 0xFC, DMA RTD3 Force Power */ + DD3E, 1, /* 0:0 DMA RTD3 Enable */ + DFPE, 1, /* 1:1 DMA Force Power */ + , 22, + DMAD, 8 /* 31:24 DMA Active Delay */ +} + +/* + * TBT MailBox Command Method + * Arg0 - MailBox Cmd ID + */ +Method (ITMB, 1, Serialized) +{ + Local0 = Arg0 | 0x1 /* 0x1, PCIE2TBT_VLD_B */ + P2TB = Local0 +} + +/* + * Wait For Command Completed + * Arg0 - TimeOut value (unit is 1 millisecond) + */ +Method (WFCC, 1, Serialized) +{ + WTBS (Arg0) + P2TB = 0 + WTBC (Arg0) +} + +/* + * Wait For Command Set + * Arg0 - TimeOut value + */ +Method (WTBS, 1, Serialized) +{ + Local0 = Arg0 + While (Local0 > 0) { + /* Wait for Bit to Set. */ + If (TB2P & 0x1) { /* 0x1, TBT2PCIE_DON_R */ + Break + } + Local0-- + Sleep (1) + } +} + +/* + * Wait For Command Clear + * Arg0 - TimeOut value + */ +Method (WTBC, 1, Serialized) +{ + Local0 = Arg0 + While (Local0 > 0) { + /* Wait for Bit to Clear. */ + If ((TB2P & 0x1) != 0x0) { /* 0x1, TBT2PCIE_DON_R */ + Break + } + Local0-- + Sleep (1) + } +} + +/* + * TCSS TBT CONNECT_TOPOLOGY MailBox Command Method + */ +Method (CNTP, 0, Serialized) +{ + Local0 = 0 + /* Set Force Power if it is not set */ + If (DFPE == 0) { + DMAD = 0x22 + DFPE = 1 + /* + * Poll the TBT NVM FW Ready bit with timeout(default is 500ms) before + * send the TBT MailBox command. + */ + While ((INFR == 0) && (Local0 < 500)) { + Sleep (1) + Local0++ + } + } + If (Local0 != 100) { + ITMB (0x3E) /* 0x3E, PCIE2TBT_CONNECT_TOPOLOGY_COMMAND */ + } +} + +Name (STAT, 0x1) /* Variable to save power state 1 - D0, 0 - D3C */ +Name (ALCT, 0x0) /* Connect-Topology cmd can be sent or not 1 - yes, 0 - no */ +/* + * Wait Connect-Topology cmd done + * 0 - no need to wait + * 1 - need to wait + * 2 - wait in progress + */ +Name (WACT, 0x0) + +Method (_PS0, 0, Serialized) +{ + If (WACT == 1) { + /* + * PCIe rp0/rp1 is grouped with DMA0 and PCIe rp2/rp3 is grouped wit DMA1. + * Whenever the Connect-Topology command is in the process, WACT flag is set 1. + * PCIe root ports 0/1/2/3/ and DMA 0/1 _PS0 method set WACT to 2 to indicate + * other thread's _PS0 to wait for the command completion. WACT is cleared to + * be 0 after command is finished. + */ + WACT = 2 + WFCC (100) /* Wait for command complete. */ + WACT = 0 + } ElseIf (WACT == 2) { + While (WACT != 0) { + Sleep (5) + } + } +} + +Method (_PS3, 0, Serialized) +{ +} + +Method (_S0W, 0x0) +{ + Return (0x4) +} + +Method (_PR0) +{ + If (DUID == 0) { + Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT0 }) + } Else { + Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT1 }) + } +} + +Method (_PR3) +{ + If (DUID == 0) { + Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT0 }) + } Else { + Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT1 }) + } +} + +/* + * RTD3 Exit Method to bring TBT controller out of RTD3 mode. + */ +Method (D3CX, 0, Serialized) +{ + DD3E = 0 /* Disable DMA RTD3 */ + STAT = 0x1 +} + +/* + * RTD3 Entry method to enable TBT controller RTD3 mode. + */ +Method (D3CE, 0, Serialized) +{ + DD3E = 1 /* Enable DMA RTD3 */ + STAT = 0 + ALCT = 0x1 /* Allow to send Connect-Topology cmd. */ +} + +/* + * Variable to skip TCSS/TBT D3 cold; 1+: Skip D3CE, 0 - Enable D3CE + * TCSS D3 Cold and TBT RTD3 is only available when system power state is in S0. + */ +Name (SD3C, 0) + +Method (_DSW, 3) +{ + /* If entering Sx (Arg1 > 1), need to skip TCSS D3Cold & TBT RTD3/D3Cold. */ + SD3C = Arg1 +} + +Method (_PRW, 0) +{ + Return (Package() { 0x6D, 4 }) +} + +Method (_DSD, 0) +{ + Return( + Package() + { + /* Thunderbolt GUID for IMR_VALID at ../drivers/acpi/property.c */ + ToUUID("C44D002F-69F9-4E7D-A904-A7BAABDF43F7"), + Package () + { + Package (2) { "IMR_VALID", 1 } + }, + + /* Thunderbolt GUID for WAKE_SUPPORTED at ../drivers/acpi/property.c */ + ToUUID("6C501103-C189-4296-BA72-9BF5A26EBE5D"), + Package () + { + Package (2) { "WAKE_SUPPORTED", 1 } + } + } + ) +} + +Method (_DSM, 4, Serialized) +{ + Return (Buffer() { 0 }) +} diff --git a/src/soc/intel/tigerlake/acpi/tcss_pcierp.asl b/src/soc/intel/tigerlake/acpi/tcss_pcierp.asl new file mode 100644 index 0000000000..653266175d --- /dev/null +++ b/src/soc/intel/tigerlake/acpi/tcss_pcierp.asl @@ -0,0 +1,315 @@ +/* + * This file is part of the coreboot project. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +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}) +} + +Device (PXSX) +{ + Name (_ADR, 0x00000000) + + Method (_PRW, 0) + { + Return (Package() { 0x69, 4 }) + } +} + +Method (_DSW, 3) +{ + C2PM (Arg0, Arg1, Arg2, DCPM) + /* If entering Sx (Arg1 > 1), need to skip TCSS D3Cold & TBT RTD3/D3Cold. */ + \_SB.PCI0.TDM0.SD3C = Arg1 + \_SB.PCI0.TDM1.SD3C = Arg1 +} + +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 + + /* Wait for LA = 1 */ + Local0 = 0 + Local1 = LASX + While (Local1 == 0) { + If (Local0 > 20) { + Break + } + Sleep(5) + Local0++ + Local1 = LASX + } +} + +/* + * 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 */ + } + Sleep(100) /* Wait for 100ms before return to OS starts any DS activities. */ + If ((TUID == 0) || (TUID == 1)) { + If (\_SB.PCI0.TDM0.WACT == 1) { + /* + * Indicate other thread's _PS0 to wait the response. + */ + \_SB.PCI0.TDM0.WACT = 2 + \_SB.PCI0.TDM0.WFCC (10) /* Wait for command complete. */ + \_SB.PCI0.TDM0.WACT = 0 + } ElseIf (\_SB.PCI0.TDM0.WACT == 2) { + While (\_SB.PCI0.TDM0.WACT != 0) { + Sleep (5) + } + } + } Else { + If (\_SB.PCI0.TDM1.WACT == 1) { + /* + * Indicate other thread's _PS0 to wait the response. + */ + \_SB.PCI0.TDM1.WACT = 2 + \_SB.PCI0.TDM1.WFCC (10) /* Wait for command complete. */ + \_SB.PCI0.TDM1.WACT = 0 + } ElseIf (\_SB.PCI0.TDM1.WACT == 2) { + While (\_SB.PCI0.TDM1.WACT != 0) { + Sleep (5) + } + } + } +} + +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 (_DSD, 0) { + Return ( + Package () { + /* acpi_pci_bridge_d3 at ../drivers/pci/pci-acpi.c */ + ToUUID("6211E2C0-58A3-4AF3-90E1-927A4E0C55A4"), + Package () + { + Package (2) { "HotPlugSupportInD3", 1 }, + }, + + /* pci_acpi_set_untrusted at ../drivers/pci/pci-acpi.c */ + ToUUID("EFCC06CC-73AC-4BC3-BFF0-76143807C389"), + Package () { + Package (2) { "ExternalFacingPort", 1 }, /* TBT/CIO port */ + /* + * UID of the TBT RP on platform, range is: 0, 1 ..., + * (NumOfTBTRP - 1). + */ + Package (2) { "UID", TUID }, + } + } + ) +} + +Method (_S0W, 0x0, NotSerialized) +{ + Return (0x4) +} + +Method (_PR0) +{ + If ((TUID == 0) || (TUID == 1)) { + Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT0 }) + } Else { + Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT1 }) + } +} + +Method (_PR3) +{ + If ((TUID == 0) || (TUID == 1)) { + Return (Package() { \_SB.PCI0.D3C, \_SB.PCI0.TBT0 }) + } Else { + Return (Package() { \_SB.PCI0.D3C, \_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) +} diff --git a/src/soc/intel/tigerlake/acpi/tcss_xhci.asl b/src/soc/intel/tigerlake/acpi/tcss_xhci.asl new file mode 100644 index 0000000000..e78cc1d482 --- /dev/null +++ b/src/soc/intel/tigerlake/acpi/tcss_xhci.asl @@ -0,0 +1,138 @@ +/* + * This file is part of the coreboot project. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +OperationRegion (XPRT, SystemMemory, BASE(_ADR), 0x100) +Field (XPRT, ByteAcc, NoLock, Preserve) +{ + VDID, 32, + Offset(0x74), /* 0x74, XHCI CFG Power Control And Status */ + D0D3, 2, /* 0x74 BIT[1:0] */ + , 6, + PMEE, 1, /* PME Enable */ + , 6, + PMES, 1, /* PME Status */ +} + +Method (_PS0, 0, Serialized) +{ + If (\_SB.PCI0.TXHC.PMEE == 1) { + /* Clear PME_EN of CPU xHCI */ + \_SB.PCI0.TXHC.PMEE = 0 + } +} + +Method (_PS3, 0, Serialized) +{ + If (\_SB.PCI0.TXHC.PMEE == 0) { + /* Set PME_EN of CPU xHCI */ + \_SB.PCI0.TXHC.PMEE = 1 + } +} + +Method (_S0W, 0x0, NotSerialized) +{ + Return (0x4) +} + +/* + * Variable to skip TCSS/TBT D3 cold; 1+: Skip D3CE, 0 - Enable D3CE + * TCSS D3 Cold and TBT RTD3 is only available when system power state is in S0. + */ +Name (SD3C, 0) + +Method (_PR0) +{ + Return (Package () { \_SB.PCI0.D3C }) +} + +Method (_PR3) +{ + Return (Package () { \_SB.PCI0.D3C }) +} + +/* + * XHCI controller _DSM method + */ +Method (_DSM, 4, serialized) +{ + Return (Buffer() { 0 }) +} + +/* + * _SXD and _SXW methods + */ +Method (_S3D, 0, NotSerialized) +{ + Return (3) +} + +Method (_S4D, 0, NotSerialized) +{ + Return (3) +} + +Method (_S3W, 0, NotSerialized) +{ + Return (3) +} + +Method (_S4W, 0, NotSerialized) +{ + Return (3) +} + +/* + * Power resource for wake + */ +Method (_PRW, 0) +{ + Return (Package() { 0x6D, 4 }) +} + +/* + * Device sleep wake + */ +Method (_DSW, 3) +{ + C2PM (Arg0, Arg1, Arg2, DCPM) + /* If entering Sx (Arg1 > 1), need to skip TCSS D3Cold & TBT RTD3/D3Cold. */ + SD3C = Arg1 +} + +/* + * xHCI Root Hub Device + */ +Device (RHUB) +{ + Name (_ADR, Zero) + + /* High Speed Ports */ + Device (HS01) + { + Name (_ADR, 0x01) + } + + /* Super Speed Ports */ + Device (SS01) + { + Name (_ADR, 0x02) + } + + Device (SS02) + { + Name (_ADR, 0x03) + } + + Device (SS03) + { + Name (_ADR, 0x04) + } + + Device (SS04) + { + Name (_ADR, 0x05) + } +} |