From e32da955b3a4e9674c6c5012e895c79c2696032e Mon Sep 17 00:00:00 2001 From: Duncan Laurie Date: Thu, 27 Aug 2015 17:09:02 -0700 Subject: [PATCH] skylake: ACPI: Clean up and fix XHCI ACPI Device - Remove the old workarounds for XHCI from broadwell - Add PMC device to expose bits needed for XHCI workarounds - Implement the new workarounds for XHCI, the first will set a bit in the XHCI MMIO and the second will send a message to the PMC if a bit is set indicating the workaround is available. - Clean up the HS/SS port defines and remove unnecessary methods to determine the port count since we only support SPT-LP. BUG=chrome-os-partner:44622,chrome-os-partner:44518 BRANCH=none TEST=build and boot on glados, verify that D0 and D3 can be made to work (by disabling unused USB and the misbehaving camera) Change-Id: I535c9d22308c45a3b9bf7e4045c3d01481acc19c Signed-off-by: Patrick Georgi Original-Commit-Id: a945f8bc2976d57373be2305c5da40a5691f1e88 Original-Change-Id: I7a57051c0a5c4f5408c2d6ff0aecf660100a1aec Original-Signed-off-by: Duncan Laurie Original-Reviewed-on: https://chromium-review.googlesource.com/295950 Original-Reviewed-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/11537 Tested-by: build bot (Jenkins) Reviewed-by: Alexandru Gagniuc Reviewed-by: Aaron Durbin --- src/soc/intel/skylake/acpi/pch.asl | 3 + src/soc/intel/skylake/acpi/pmc.asl | 45 ++++ src/soc/intel/skylake/acpi/xhci.asl | 387 +++++++++------------------- 3 files changed, 174 insertions(+), 261 deletions(-) create mode 100644 src/soc/intel/skylake/acpi/pmc.asl diff --git a/src/soc/intel/skylake/acpi/pch.asl b/src/soc/intel/skylake/acpi/pch.asl index f2c1a16d04..951b97a77d 100644 --- a/src/soc/intel/skylake/acpi/pch.asl +++ b/src/soc/intel/skylake/acpi/pch.asl @@ -40,6 +40,9 @@ /* PCR Access */ #include "pcr.asl" +/* PMC 0:1f.2 */ +#include "pmc.asl" + /* Serial IO */ #include "serialio.asl" diff --git a/src/soc/intel/skylake/acpi/pmc.asl b/src/soc/intel/skylake/acpi/pmc.asl new file mode 100644 index 0000000000..2d826f6883 --- /dev/null +++ b/src/soc/intel/skylake/acpi/pmc.asl @@ -0,0 +1,45 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +Device (PMC) +{ + Name (_ADR, 0x001f0002) + Name (_DDN, "Power Management Controller") + + OperationRegion (PMCP, PCI_Config, 0x00, 0x100) + Field (PMCP, AnyAcc, NoLock, Preserve) + { + Offset (0x48), + , 12, + PWRM, 20, /* PWRMBASE */ + } + + OperationRegion (PMCM, SystemMemory, ShiftLeft (PWRM, 12), 0x3f) + Field (PMCM, DWordAcc, NoLock, Preserve) + { + Offset (0x1c), /* PCH_PM_STS */ + , 24, + PMFS, 1, /* PMC_MSG_FULL_STS */ + Offset (0x20), + MPMC, 32, /* MTPMC */ + Offset (0x24), /* PCH_PM_STS2 */ + , 20, + UWAB, 1, /* USB2 Workaround Available */ + } +} diff --git a/src/soc/intel/skylake/acpi/xhci.asl b/src/soc/intel/skylake/acpi/xhci.asl index f0ee414b52..5e4908780b 100644 --- a/src/soc/intel/skylake/acpi/xhci.asl +++ b/src/soc/intel/skylake/acpi/xhci.asl @@ -2,7 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007-2009 coresystems GmbH - * Copyright (C) 2014 Google Inc. + * Copyright (C) 2015 Google Inc. * Copyright (C) 2015 Intel Corporation. * * This program is free software; you can redistribute it and/or modify @@ -25,297 +25,162 @@ Device (XHCI) { Name (_ADR, 0x00140000) - Name (PLSD, 5) /* Port Link State - RxDetect */ - Name (PLSP, 7) /* Port Link State - Polling */ + Name (_PRW, Package () { GPE0_PME_B0, 3 }) + + Method (_DSW, 3) + { + Store (Arg0, PMEE) + } + + Name (_S3D, 3) /* D3 supported in S3 */ + Name (_S4D, 3) /* D3 supported in S4 */ + Name (_S0W, 3) /* D3 can wake device in S0 */ + Name (_S3W, 3) /* D3 can wake system from S3 */ + Name (_S4W, 3) /* D3 can wake system from S4 */ OperationRegion (XPRT, PCI_Config, 0x00, 0x100) Field (XPRT, AnyAcc, NoLock, Preserve) { Offset (0x0), - DVID, 16, + DVID, 16, /* VENDORID */ Offset (0x10), , 16, XMEM, 16, /* MEM_BASE */ Offset (0x74), - D0D3, 2, + D0D3, 2, /* POWERSTATE */ , 6, PMEE, 1, /* PME_EN */ , 6, PMES, 1, /* PME_STS */ - Offset (0xA8), - , 13, - MW13, 1, - MW14, 1, - , 17, - Offset (0xb0), - , 13, - MB13, 1, - MB14, 1, - , 17, - Offset (0xd0), - PR2, 32, /* USB2PR */ - PR2M, 32, /* USB2PRM */ - PR3, 32, /* USB3PR */ - PR3M, 32, /* USB3PRM */ } - Method (USRA,0){ - Return(11) - } - - Method (SSPA,0){ - Return (13) - } - - /* Clear status bits */ - Method (LPCL, 0, Serialized) + OperationRegion (XREG, SystemMemory, + Add (ShiftLeft (XMEM, 16), 0x8000), 0x200) + Field (XREG, DWordAcc, Lock, Preserve) { - OperationRegion (XREG, SystemMemory, - ShiftLeft (^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, ShiftLeft (1, 1)) - - /* Change Status (Bits 23:17)*/ - Name (CHST, ShiftLeft (0x7f, 17)) - - /* Port 0 */ - And (PSC0, Not (PEDB), Local0) - Or (Local0, CHST, PSC0) - - /* Port 1 */ - And (PSC1, Not (PEDB), Local0) - Or (Local0, CHST, PSC1) - - /* Port 2 */ - And (PSC2, Not (PEDB), Local0) - Or (Local0, CHST, PSC2) - - /* Port 3 */ - And (PSC3, Not (PEDB), Local0) - Or (Local0, CHST, PSC3) + Offset (0x1c4), /* USB2PMCTRL */ + , 2, + UPSW, 2, /* U2PSUSPGP */ } - Method (LPS0, 0, Serialized) - { - OperationRegion (XREG, SystemMemory, - ShiftLeft (^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*/ - Store (10, Local0) - While (LOr (LOr (LAnd (LEqual (PPR1, 1), LEqual (PLS1, PLSP)), - LAnd (LEqual (PPR2, 1), LEqual (PLS2, PLSP))), - LOr (LAnd (LEqual (PPR3, 1), LEqual (PLS3, PLSP)), - LAnd (LEqual (PPR4, 1), LEqual (PLS4, PLSP))))) - { - If (LEqual (Local0, 0)) { - Break - } - Decrement (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*/ - Store (0, Local1) - Store (0, Local2) - Store (0, Local3) - Store (0, Local4) - - If (LAnd (LEqual (PLS1, PLSD), - LAnd (LEqual (CSC1, 0), LEqual (PPR1, 1)))) { - Store (1, WPR1) /* Issue warm reset*/ - Store (1, Local1) - } - If (LAnd (LEqual (PLS2, PLSD), - LAnd (LEqual (CSC2, 0), LEqual (PPR2, 1)))) { - Store (1, WPR2) /* Issue warm reset*/ - Store (1, Local2) - } - If (LAnd (LEqual (PLS3, PLSD), - LAnd (LEqual (CSC3, 0), LEqual (PPR3, 1)))) { - Store (1, WPR3) /* Issue warm reset*/ - Store (1, Local3) - } - If (LAnd (LEqual (PLS4, PLSD), - LAnd (LEqual (CSC4, 0), LEqual (PPR4, 1)))) { - Store (1, WPR4) /* Issue warm reset*/ - Store (1, Local4) - } - - /* Poll for warm reset complete on all ports that were reset*/ - Store (10, Local0) - While (LOr (LOr (LAnd (LEqual (Local1, 1), LEqual (WRC1, 0)), - LAnd (LEqual (Local2, 1), LEqual (WRC2, 0))), - LOr (LAnd (LEqual (Local3, 1), LEqual (WRC3, 0)), - LAnd (LEqual (Local4, 1), LEqual (WRC4, 0))))) - { - If (LEqual (Local0, 0)) { - Break - } - Decrement (Local0) - Stall (10) - } - - /* Clear status bits in all ports */ - LPCL () - } - - Method (_PSC, 0, NotSerialized) + Method (_PSC, 0, Serialized) { Return (^D0D3) } Method (_PS0, 0, Serialized) { + If (LEqual (^DVID, 0xFFFF)) { + Return + } + If (LOr (LEqual (^XMEM, 0xFFFF), LEqual (^XMEM, 0x0000))) { + Return + } + + /* If device is in D3, set back to D0 */ + If (LEqual (^D0D3, 3)) { + Store (Zero, ^D0D3) + Store (^D0D3, Local0) + } + + /* Disable USB2 PHY SUS Well Power Gating */ + Store (Zero, ^UPSW) + + /* + * Apply USB2 PHPY Power Gating workaround if needed. + */ + If (^^PMC.UWAB) { + /* Write to MTPMC to have PMC disable power gating */ + Store (1, ^^PMC.MPMC) + + /* Wait for PCH_PM_STS.MSG_FULL_STS to be 0 */ + Store (10, Local0) + While (^^PMC.PMFS) { + If (LNot (Local0)) { + Break + } + Decrement (Local0) + Sleep (10) + } + } } + Method (_PS3, 0, Serialized) { + If (LEqual (^DVID, 0xFFFF)) { + Return + } + If (LOr (LEqual (^XMEM, 0xFFFF), LEqual (^XMEM, 0x0000))) { + Return + } + + /* Clear PME Status */ + Store (1, ^PMES) + + /* Enable PME */ + Store (1, ^PMEE) + + /* If device is in D3, set back to D0 */ + If (LEqual (^D0D3, 3)) { + Store (Zero, ^D0D3) + Store (^D0D3, Local0) + } + + /* Enable USB2 PHY SUS Well Power Gating in D0/D0i2/D0i3/D3 */ + Store (3, ^UPSW) + + /* Now put device in D3 */ + Store (3, ^D0D3) + Store (^D0D3, Local0) + + /* + * Apply USB2 PHPY Power Gating workaround if needed. + * This code assumes XDCI is disabled, if it is enabled + * then this must also check if it is in D3 state too. + */ + If (^^PMC.UWAB) { + /* Write to MTPMC to have PMC enable power gating */ + Store (3, ^^PMC.MPMC) + + /* Wait for PCH_PM_STS.MSG_FULL_STS to be 0 */ + Store (10, Local0) + While (^^PMC.PMFS) { + If (LNot (Local0)) { + Break + } + Decrement (Local0) + Sleep (10) + } + } } - Name (_PRW, Package(){ 0x6d, 3 }) + /* Root Hub for Skylake-LP PCH */ + Device (RHUB) + { + Name (_ADR, Zero) - /* Leave USB ports on for to allow Wake from USB */ + /* USB2 */ + Device (HS01) { Name (_ADR, 1) } + Device (HS02) { Name (_ADR, 2) } + Device (HS03) { Name (_ADR, 3) } + Device (HS04) { Name (_ADR, 4) } + Device (HS05) { Name (_ADR, 5) } + Device (HS06) { Name (_ADR, 6) } + Device (HS07) { Name (_ADR, 7) } + Device (HS08) { Name (_ADR, 8) } + Device (HS09) { Name (_ADR, 9) } + Device (HS10) { Name (_ADR, 10) } - Method (_S3D,0) /* Highest D State in S3 State*/ - { - Return (3) - } + /* USBr */ + Device (USR1) { Name (_ADR, 11) } + Device (USR2) { Name (_ADR, 12) } - Method (_S4D,0) /* Highest D State in S4 State*/ - { - Return (3) - } - Device (HS01) - { - Name(_ADR, 0x01) - } - Device (HS02) - { - Name(_ADR, 0x02) - } - Device (HS03) - { - Name(_ADR, 0x03) - } - Device (HS04) - { - Name(_ADR, 0x04) - } - Device (HS05) - { - Name(_ADR, 0x05) - } - Device (HS06) - { - Name(_ADR, 0x06) - } - Device (HS07) - { - Name(_ADR, 0x07) - } - Device (HS08) - { - Name(_ADR, 0x08) - } - Device (HS09) - { - Name(_ADR, 0x09) - } - Device (HS10) - { - Name(_ADR, 0x10) - } - Device (USR1) - { - Method(_ADR) { Return (Add(USRA(),0)) } - } - Device (USR2) - { - Method(_ADR) { Return (Add(USRA(),1)) } - } - Device (SS01) - { - Method(_ADR) { Return (Add(SSPA(),0)) } - } - Device (SS02) - { - Method(_ADR) { Return (Add(SSPA(),1)) } - } - Device (SS03) - { - Method(_ADR) { Return (Add(SSPA(),2)) } - } - Device (SS04) - { - Method(_ADR) { Return (Add(SSPA(),3)) } - } - Device (SS05) - { - Method(_ADR) { Return (Add(SSPA(),4)) } - } - Device (SS06) - { - Method(_ADR) { Return (Add(SSPA(),5)) } + /* USB3 */ + Device (SS01) { Name (_ADR, 13) } + Device (SS02) { Name (_ADR, 14) } + Device (SS03) { Name (_ADR, 15) } + Device (SS04) { Name (_ADR, 16) } + Device (SS05) { Name (_ADR, 17) } + Device (SS06) { Name (_ADR, 18) } } } -