summaryrefslogtreecommitdiff
path: root/src/southbridge/intel/lynxpoint/acpi/xhci.asl
diff options
context:
space:
mode:
Diffstat (limited to 'src/southbridge/intel/lynxpoint/acpi/xhci.asl')
-rw-r--r--src/southbridge/intel/lynxpoint/acpi/xhci.asl344
1 files changed, 344 insertions, 0 deletions
diff --git a/src/southbridge/intel/lynxpoint/acpi/xhci.asl b/src/southbridge/intel/lynxpoint/acpi/xhci.asl
new file mode 100644
index 0000000000..65f1869e10
--- /dev/null
+++ b/src/southbridge/intel/lynxpoint/acpi/xhci.asl
@@ -0,0 +1,344 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+// XHCI Controller 0:14.0
+
+Device (XHCI)
+{
+ Name (_ADR, 0x00140000)
+
+ Name (PLSD, 5) // Port Link State - RxDetect
+ Name (PLSP, 7) // Port Link State - Polling
+
+ OperationRegion (XPRT, PCI_Config, 0, 0x100)
+ Field (XPRT, AnyAcc, NoLock, Preserve)
+ {
+ Offset (0x0),
+ DVID, 16,
+ Offset (0x10),
+ , 16,
+ XMEM, 16, // MEM_BASE
+ Offset (0x74),
+ D0D3, 2,
+ , 6,
+ PMEE, 1, // PME_EN
+ , 6,
+ PMES, 1, // PME_STS
+ Offset (0xb0),
+ , 13,
+ MB13, 1,
+ MB14, 1,
+ Offset (0xd0),
+ PR2R, 32, // USB2PR
+ PR2M, 32, // USB2PRM
+ PR3R, 32, // USB3PR
+ PR3M, 32, // USB3PRM
+ }
+
+ // Clear status bits
+ Method (LPCL, 0, Serialized)
+ {
+ OperationRegion (XREG, SystemMemory, ^XMEM << 16, 0x600)
+ Field (XREG, DWordAcc, Lock, Preserve)
+ {
+ Offset (0x510), // PORTSCNUSB3[0]
+ PSC0, 32,
+ Offset (0x520), // PORTSCNUSB3[1]
+ PSC1, 32,
+ Offset (0x530), // PORTSCNUSB3[2]
+ PSC2, 32,
+ Offset (0x540), // PORTSCNUSB3[3]
+ PSC3, 32,
+ }
+
+ // Port Enabled/Disabled (Bit 1)
+ Name (PEDB, 1 << 1)
+
+ // Change Status (Bits 23:17)
+ Name (CHST, 0x7f << 17)
+
+ // Port 0
+ Local0 = PSC0 & ~PEDB
+ PSC0 = Local0 | CHST
+
+ // Port 1
+ Local0 = PSC1 & ~PEDB
+ PSC1 = Local0 | CHST
+
+ // Port 2
+ Local0 = PSC2 & ~PEDB
+ PSC2 = Local0 | CHST
+
+ // Port 3
+ Local0 = PSC3 & ~PEDB
+ PSC3 = Local0 | CHST
+ }
+
+ Method (LPS0, 0, Serialized)
+ {
+ OperationRegion (XREG, SystemMemory, ^XMEM << 16, 0x600)
+ Field (XREG, DWordAcc, Lock, Preserve)
+ {
+ Offset (0x510), // PORTSCNUSB3
+ , 5,
+ PLS1, 4, // [8:5] Port Link State
+ PPR1, 1, // [9] Port Power
+ , 7,
+ CSC1, 1, // [17] Connect Status Change
+ , 1,
+ WRC1, 1, // [19] Warm Port Reset Change
+ , 11,
+ WPR1, 1, // [31] Warm Port Reset
+ Offset (0x520), // PORTSCNUSB3
+ , 5,
+ PLS2, 4, // [8:5] Port Link State
+ PPR2, 1, // [9] Port Power
+ , 7,
+ CSC2, 1, // [17] Connect Status Change
+ , 1,
+ WRC2, 1, // [19] Warm Port Reset Change
+ , 11,
+ WPR2, 1, // [31] Warm Port Reset
+ Offset (0x530), // PORTSCNUSB3
+ , 5,
+ PLS3, 4, // [8:5] Port Link State
+ PPR3, 1, // [9] Port Power
+ , 7,
+ CSC3, 1, // [17] Connect Status Change
+ , 1,
+ WRC3, 1, // [19] Warm Port Reset Change
+ , 11,
+ WPR3, 1, // [31] Warm Port Reset
+ Offset (0x540), // PORTSCNUSB3
+ , 5,
+ PLS4, 4, // [8:5] Port Link State
+ PPR4, 1, // [9] Port Power
+ , 7,
+ CSC4, 1, // [17] Connect Status Change
+ , 1,
+ WRC4, 1, // [19] Warm Port Reset Change
+ , 11,
+ WPR4, 1, // [31] Warm Port Reset
+ }
+
+ // Wait for all powered ports to finish polling
+ Local0 = 10
+ While ((PPR1 == 1 && PLS1 == PLSP || PPR2 == 1 && PLS2 == PLSP) ||
+ (PPR3 == 1 && PLS3 == PLSP || PPR4 == 1 && PLS4 == PLSP))
+ {
+ If (Local0 == 0) {
+ Break
+ }
+ Local0--
+ Stall (10)
+ }
+
+ // For each USB3 Port:
+ // If port is disconnected (PLS=5 PP=1 CSC=0)
+ // 1) Issue warm reset (WPR=1)
+ // 2) Poll for warm reset complete (WRC=0)
+ // 3) Write 1 to port status to clear
+
+ // Local# indicate if port is reset
+ Local1 = 0
+ Local2 = 0
+ Local3 = 0
+ Local4 = 0
+
+ If (PLS1 == PLSD && (CSC1 == 0 && PPR1 == 1)) {
+ WPR1 = 1 // Issue warm reset
+ Local1 = 1
+ }
+ If (PLS2 == PLSD && (CSC2 == 0 && PPR2 == 1)) {
+ WPR2 = 1 // Issue warm reset
+ Local2 = 1
+ }
+ If (PLS3 == PLSD && (CSC3 == 0 && PPR3 == 1)) {
+ WPR3 = 1 // Issue warm reset
+ Local3 = 1
+ }
+ If (PLS4 == PLSD && (CSC4 == 0 && PPR4 == 1)) {
+ WPR4 = 1 // Issue warm reset
+ Local4 = 1
+ }
+
+ // Poll for warm reset complete on all ports that were reset
+ Local0 = 10
+ While ((Local1 == 1 && WRC1 == 0 || Local2 == 1 && WRC2 == 0) ||
+ (Local3 == 1 && WRC3 == 0 || Local4 == 1 && WRC4 == 0))
+ {
+ If (Local0 == 0) {
+ Break
+ }
+ Local0--
+ Stall (10)
+ }
+
+ // Clear status bits in all ports
+ LPCL ()
+ }
+
+ Method (_PSC, 0, NotSerialized)
+ {
+ Return (^D0D3)
+ }
+
+ Method (_PS0, 0, Serialized)
+ {
+ If (^DVID == 0xFFFF) {
+ Return ()
+ }
+ If (^XMEM == 0xFFFF || ^XMEM == 0) {
+ Return ()
+ }
+
+ OperationRegion (XREG, SystemMemory, (^XMEM << 16) + 0x8000, 0x200)
+ Field (XREG, DWordAcc, Lock, Preserve)
+ {
+ Offset (0x0e0), // AUX Reset Control 1
+ , 15,
+ AX15, 1,
+ Offset (0x154), // AUX Domain PM Control Register 2
+ , 31,
+ CLK2, 1,
+ Offset (0x16c), // AUX Clock Control
+ , 2,
+ CLK0, 1,
+ , 11,
+ CLK1, 1, // USB3 Port Aux/Core Clock Gating Enable
+ }
+
+ // If device is in D3, set back to D0
+ Local0 = ^D0D3
+ if (Local0 == 3) {
+ ^D0D3 = 0
+ }
+
+ If (\ISLP ()) {
+ // Clear PCI 0xB0[14:13]
+ ^MB13 = 0
+ ^MB14 = 0
+
+ // Clear MMIO 0x816C[14,2]
+ CLK0 = 0
+ CLK1 = 0
+ }
+
+ // Set MMIO 0x8154[31]
+ CLK2 = 1
+
+ If (\ISLP ()) {
+ // Handle per-port reset if needed
+ LPS0 ()
+
+ // Set MMIO 0x80e0[15]
+ AX15 = 1
+ }
+
+ Return ()
+ }
+
+ Method (_PS3, 0, Serialized)
+ {
+ If (^DVID == 0xFFFF) {
+ Return ()
+ }
+ If (^XMEM == 0xFFFF || ^XMEM == 0) {
+ Return ()
+ }
+
+ OperationRegion (XREG, SystemMemory, (^XMEM << 16) + 0x8000, 0x200)
+ Field (XREG, DWordAcc, Lock, Preserve)
+ {
+ Offset (0x0e0), // AUX Reset Control 1
+ , 15,
+ AX15, 1,
+ Offset (0x154), // AUX Domain PM Control Register 2
+ , 31,
+ CLK2, 1,
+ Offset (0x16c), // AUX Clock Control
+ , 2,
+ CLK0, 1,
+ , 11,
+ CLK1, 1, // USB3 Port Aux/Core Clock Gating Enable
+ }
+
+ ^PMES = 1 // Clear PME Status
+ ^PMEE = 1 // Enable PME
+
+ // If device is in D3, set back to D0
+ Local0 = ^D0D3
+ if (Local0 == 3) {
+ ^D0D3 = 0
+ }
+
+ If (\ISLP ()) {
+ // Set PCI 0xB0[14:13]
+ ^MB13 = 1
+ ^MB14 = 1
+
+ // Set MMIO 0x816C[14,2]
+ CLK0 = 1
+ CLK1 = 1
+ }
+
+ // Clear MMIO 0x8154[31]
+ CLK2 = 0
+
+ If (\ISLP ()) {
+ // Clear MMIO 0x80e0[15]
+ AX15 = 0
+ }
+
+ // Put device in D3
+ ^D0D3 = 3
+
+ Return ()
+ }
+
+ Name (_PRW, Package () { DEFAULT_PRW_VALUE, 3 })
+
+ // Leave USB ports on for to allow Wake from USB
+
+ Method (_S3D, 0) // Highest D State in S3 State
+ {
+ Return (3)
+ }
+
+ Method (_S4D, 0) // Highest D State in S4 State
+ {
+ Return (3)
+ }
+
+ Device (HUB7)
+ {
+ Name (_ADR, 0)
+
+ // GPLD: Generate Port Location Data (PLD)
+ Method (GPLD, 1, Serialized) {
+ Name (PCKG, Package () {
+ Buffer (0x10) {}
+ })
+
+ // REV: Revision 2 for ACPI 5.0
+ CreateField (DerefOf (PCKG [0]), 0, 7, REV)
+ REV = 2
+
+ // VISI: Port visibility to user per port
+ CreateField (DerefOf (PCKG [0]), 0x40, 1, VISI)
+ VISI = Arg0
+ Return (PCKG)
+ }
+
+ Device (PRT1) { Name (_ADR, 1) } // USB Port 0
+ Device (PRT2) { Name (_ADR, 2) } // USB Port 1
+ Device (PRT3) { Name (_ADR, 3) } // USB Port 2
+ Device (PRT4) { Name (_ADR, 4) } // USB Port 3
+ Device (PRT5) { Name (_ADR, 5) } // USB Port 4
+ Device (PRT6) { Name (_ADR, 6) } // USB Port 5
+ Device (PRT7) { Name (_ADR, 7) } // USB Port 6
+ Device (SSP1) { Name (_ADR, 10) } // USB Port 10
+ Device (SSP2) { Name (_ADR, 11) } // USB Port 11
+ Device (SSP3) { Name (_ADR, 12) } // USB Port 12
+ Device (SSP4) { Name (_ADR, 13) } // USB Port 13
+ }
+}