/**@file
|
|
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
|
External(\_SB.PCI0.LPCB.H_EC.XDAT, MethodObj)
|
|
Scope(\_SB.PCI0)
|
{
|
Device(XDCI)
|
{
|
Name (_ADR, 0x00140001) // _ADR: Address
|
|
OperationRegion (OTGD, PCI_Config, 0x0, 0x100)
|
Field (OTGD, DWordAcc, NoLock, Preserve)
|
{
|
Offset(0x0),
|
DVID, 16,
|
Offset(0x10),
|
XDCB, 64
|
}
|
//
|
// Byte access for PMCS field to avoid race condition on device D-state
|
//
|
Field (OTGD, ByteAcc, NoLock, Preserve)
|
{
|
Offset(R_PCH_XDCI_PMCSR), // 0x84, PM_CS - Power Management Control/Status
|
D0I3, 2, // PM_CS[1:0] PowerState
|
, 6,
|
PMEE, 1, // bit 8, PME Enable
|
, 6,
|
PMES, 1 // bit 15, PME Status
|
}
|
|
Method(XDBA, 0)
|
{
|
Return(And(^XDCB, 0xFFFFFFFFFFFFFF00))
|
}
|
|
//
|
// Arg0: UUID = {732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511}
|
// Arg1: Revision ID = 1
|
// Arg2: Function Index
|
// Arg3: Argument
|
//
|
Method(_DSM,4,Serialized)
|
{
|
If(PCIC(Arg0)) { Return(PCID(Arg0,Arg1,Arg2,Arg3)) }
|
|
If(LEqual(Arg0, ToUUID("732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"))){
|
If(Lequal(Arg1, 1)){
|
//
|
// Set PMU Power State
|
// Arg0: 0x00 PMU should enter the D0 power state.
|
// 0x03 PMU should enter the D3 power state.
|
// Arg1: 0x03 Enable PMU PME
|
// 0x00 Clear PMU PME
|
//
|
Method (SPPS,2,Serialized) {
|
OperationRegion(XDBW, SystemMemory, XDBA(), 0x110000)
|
Field(XDBW, WordAcc, NoLock, Preserve)
|
{
|
Offset(R_PCH_XDCI_APBFC_U3PMU_CFG2), // 0x10F810
|
, 8,
|
U2CP, 2, // USB2 core power state
|
U3CP, 2, // USB3 core power state
|
Offset(R_PCH_XDCI_APBFC_U3PMU_CFG4), // 0x10F818
|
PUPS, 2, // PMU power state
|
, 1,
|
PURC, 1, // Reset PMU core
|
, 12,
|
Offset(R_PCH_XDCI_APBFC_U3PMU_CFG5), // 0x10F81C
|
, 3,
|
UXPE, 2, // U2 PME EN / U3 PME EN
|
, 11,
|
}
|
|
// Local 1 is power state D0 or D3
|
Store(Arg0, Local1)
|
// Local 2 is Enable/Clear PMU PME
|
Store(Arg1, Local2)
|
|
If(LEqual(Local1, 0)){
|
// Clear PMU PME
|
// 0x10F81C BIT3: USB3 PME
|
// 0x10F81C BIT4: USB2 PME
|
Store(0, UXPE)
|
// Wait for at least 100us, currently configured to 1000us
|
Store(0, Local0)
|
While(LLess(Local0, 10)){
|
Stall(100)
|
Increment(Local0)
|
}
|
// Set PMU to D0 by writing 0 to 0x10f818 Bit 1:0
|
Store(0, PUPS)
|
// Wait 200ms for PMU to enter D0
|
// Confirm PMU being in D0 by checking 0x10f810 Bit 11:8 to be clear
|
// 0x10f810 Bit 11:10 - Current power state of USB3 core
|
// 0x10f810 Bit 9:8 - Current power state of USB2 core
|
// both should be clear
|
Store(0,Local0)
|
While(LLess(Local0,2000)){
|
Stall(100)
|
If(LAnd(LEqual(U2CP,0),LEqual(U3CP,0))){
|
break
|
}
|
Increment(Local0)
|
}
|
If(LNotEqual(U2CP, 0)){
|
// Show warning message
|
}
|
If(LNotEqual(U3CP, 0)){
|
// Show warning message
|
}
|
Return(0)
|
}
|
|
If(LEqual(Local1, 3)){
|
// PMU should be in D0 at this point
|
// 0x10f810 Bit 11:10 - current power state of USB3 core
|
// 0x10f810 Bit 9:8 - current power state of USB2 core
|
// both should be clear
|
If(LNotEqual(U2CP, 0)){
|
// Show warning message
|
}
|
If(LNotEqual(U3CP, 0)){
|
// Show warning message
|
}
|
// Set PMU to D3 by writing 3 to 0x10f818 bit 1:0
|
Store(3, PUPS)
|
// Wait 200ms for PMU to enter D3
|
// Confirm PMU being in D3 by checking 0x10f810 Bit 11:8 to be set
|
// 0x10f810 Bit 11:10 - Current power state of USB3 core
|
// 0x10f810 Bit 9:8 - Current power state of USB2 core
|
// both should be set
|
Store(0,Local0)
|
While(LLess(Local0,2000)){
|
Stall(100)
|
If(LAnd(LEqual(U2CP,3),LEqual(U3CP,3))){
|
break
|
}
|
Increment(Local0)
|
}
|
If(LNotEqual(U2CP, 3)){
|
// Show warning message
|
}
|
If(LNotEqual(U3CP, 3)){
|
// Show warning message
|
}
|
// Set/Clear PMU PME
|
// 0x10F81C BIT3: USB3 PME
|
// 0x10F81C BIT4: USB2 PME
|
Store(Local2, UXPE)
|
Return(0)
|
}
|
Return(0)
|
}
|
|
Switch(ToInteger(Arg2)) {
|
Case(0){
|
// Function 0: return Bit map to indicate Function 0,1,4,5,6,7 supported
|
Return(Buffer(){0xF3})
|
}
|
Case(1){
|
// Function 1: Attach/Detach and Port Detection Properties Method
|
// This method is called by the USB function stack to set the power state of the PMU.
|
// Bit 0 as 1: to indicate Platform support for Attach/detach notify
|
// Bit 1 as 0:HW based charging indication
|
Return(0x1)
|
}
|
Case(4){
|
// Function 4: Set PMU Power State Method, clear PMU PME
|
// Arg3: A package consisting of 1 ULONG value
|
// 0x00 PMU should enter the D0 power state.
|
// 0x03 PMU should enter the D3 power state.
|
|
// Local 1 is power state D0 or D3
|
Store(DerefOf(Index(Arg3,0)), Local1)
|
|
// Set PMU to Dx state and clear PMU PME
|
SPPS(Local1, 0)
|
}
|
Case(5){
|
// Function 5: Attach Notification Enabled Method
|
// This method is called by the USB function stack to indicate that it has enabled ACPI attach detach notifications.
|
// In response the platform may issue an notification indicating the current attach/detach state of the controller.
|
|
// If device is attached, notify XDCI with 0x80
|
// If device is detached, notify XDCI with 0x81
|
|
|
If(CondRefOf(\_SB.PCI0.LPCB.H_EC.XDAT)){
|
If(LEqual(\_SB.PCI0.LPCB.H_EC.XDAT(), 1)){
|
Notify(\_SB.PCI0.XDCI,0x80)
|
}Else{
|
Notify(\_SB.PCI0.XDCI,0x81)
|
}
|
}
|
|
Return(0)
|
}
|
Case(6){
|
// Function 6: XDCI Soft Reset Workaround
|
// Return value indicate to OS softreset should be done by OS or not
|
// Return value == 1: OS does softreset
|
// Return value == 0: platform does softreset
|
|
|
OperationRegion(XDBD, SystemMemory, XDBA(), 0x110000)
|
Field(XDBD, DwordAcc, NoLock, Preserve)
|
{
|
Offset(0xC704),
|
, 30,
|
CSFR, 1,
|
, 1,
|
}
|
OperationRegion(XDW2, SystemMemory, XDBA(), 0x110000)
|
Field(XDW2, WordAcc, NoLock, Preserve)
|
{
|
Offset(R_PCH_XDCI_APBFC_U3PMU_CFG6), // 0x10F820
|
, 13,
|
OTHC, 1, // OTG switched to host complete
|
}
|
|
If(LEqual(OTHC, 0)){
|
Store(1, CSFR)
|
// timeout is 100ms
|
Store(0, Local0)
|
While(LLess(Local0, 100)){
|
If(LEqual(CSFR, 0)){
|
Break
|
}
|
Sleep(1)
|
}
|
}
|
Return(0)
|
}
|
Case(7){
|
// Function 7: Get PMU Power State Method
|
// Return:
|
// 0: PMU is in D0 state
|
// 3: PMU is in D3 state
|
|
|
OperationRegion(XD22, SystemMemory, XDBA(), 0x110000)
|
Field(XD22, WordAcc, NoLock, Preserve)
|
{
|
Offset(R_PCH_XDCI_APBFC_U3PMU_CFG4), // 0x10F818
|
P2PS, 2, // PMU power state
|
, 14,
|
}
|
Store(P2PS, Local0)
|
Return(Local0)
|
}
|
}
|
}
|
}
|
Return(Buffer() {0})
|
}
|
|
Name (_DDN, "SPT XHCI controller") // _DDN: DOS Device Name
|
Name (_STR, Unicode ("SPT XHCI controller")) // _STR: Description String
|
|
Method(_S0W, 0)
|
{ // PMEs can be generated from D3(hot)
|
Return(3)
|
}
|
|
Method (_STA, 0x0, NotSerialized)
|
{
|
If(LNotEqual(DVID, 0xFFFFFFFF)) { // device not disabled
|
Return (0xF)
|
} Else{
|
Return (0x0)
|
}
|
}
|
|
// XDCI Wake Support
|
Method(_PRW, 0)
|
{
|
Return(GPRW(0x6D,4)) // can wakeup from S4 state
|
}
|
|
Method(_DSW, 3)
|
{
|
Store(Arg0, PMEE)
|
}
|
|
Method(GPEH, 0, NotSerialized)
|
{
|
If(LEqual(DVID,0xFFFF)){
|
Return()
|
}
|
Store(PMES, Local0)
|
Store(1, PMES) // Clear PME Status
|
If(LAnd(PMEE, Local0)){
|
Notify(XDCI, 0x02)
|
}
|
}
|
|
}
|
}
|