/** @file ACPI PD SSDT table for the platform has EC-less PD @copyright INTEL CONFIDENTIAL Copyright 2020 Intel Corporation. The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material may contain trade secrets and proprietary and confidential information of Intel Corporation and its suppliers and licensors, and is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel's prior express written permission. No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing. Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way. This file contains a 'Sample Driver' and is licensed as such under the terms of your license agreement with Intel or your vendor. This file may be modified by the user, subject to the additional terms of the license agreement. @par Specification Reference: **/ // @details // Code in this file uses following rules: // - Print debug message in the beginning and end of each function method with "[USBC] xxx Start" and "[USBC] xxx End" // - All local variables and parameters must be dumped at the beginning and right before exit the call // - All dumps should give full messages instead of simple ACPI name // - All timeout must be specified with interval in comment and print // GPRV is a PS_ON control method implemented in ACPI RTD3 SSDT table // for veto : GPRV (2, 1) // for allowing PD PS_ON : GPRV (2, 0) // the first parameter (2) is an interface index for all commands from USBC PD // the second parameter (either 1 or 0) is for disabling or enabling PS_ON External (\GPRV, MethodObj) // PS_ON control method // PCH lib imports External (\PSOS, MethodObj) // PS_ON status method External (\PSON, IntObj) // Indicates if PS_ON is enabled External (\_SB.SGOV, MethodObj) External (\_SB.GGOV, MethodObj) External (\_SB.GGIV, MethodObj) // External declarations for optional objects. // Defined by board specific code or in BIOS settings. External (UCMS, IntObj) External (PPOE, IntObj) External (POVP, IntObj) External (PSG1, IntObj) External (PSG2, IntObj) #define PSG1_ACTIVATE 1 // Active high #define PSG1_DEACTIVATE 0 Name (PDLV, 0) // PD Level // 0 - PD is not in PS_ON mode // 1 - PD request not entering PS_ON mode // 2 - PD is in PS_ON mode Name (PDLK, 0) // PD Lock // 0 - platform allows to exit PD PS_ON mode // 1 - platform locks PD PS_ON mode state (power gating). //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // Debug Methods // // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PDDP PD PS_ON Mode Debug Method for EC-less Design Method (PDDP, 0, Serialized) { } // PDBG PD_PSON Debug Method Method (PDBG, 0, Serialized) { PDDP () } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // PD PS_ON Mode Methods // // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Method (PDOF, 0, Serialized) { // ECless USBC Sx workaround PDDP () // The feature is only available with EC-less PD design, hence UCMCx for PD must be enabled. If (LEqual (UCMS, 2)) { // Check if S0IX_EN_TRY_REQ is high, // if not then pull high to push PD entering PS_ON state If (LNotEqual (\_SB.GGOV (PSG1), PSG1_ACTIVATE)) { // Pull PLX_SX_ENTRY_G1_PCH_N GPIO down to notify PD controller \_SB.SGOV (PSG1, PSG1_ACTIVATE) Store (0, Local0) While (LLess (Local0, 100)) {// Timeout is 1 second Sleep (10) // In ms // Wait for S0IX_EN_TRY_ACK to high until timeout If (LEqual (\_SB.GGIV (PSG2), PSG1_ACTIVATE)) { Break } Else { Increment (Local0) } } } else { } } PDDP () } Method (PDON) { // ECless USBC Sx workaround PDDP () // The feature is only available with EC-less PD design, hence UCMCx for PD must be enabled. If (LEqual (UCMS, 2)) { // Check if S0IX_EN_TRY_REQ is high, // if yes then notify PD to exit PS_ON state If (LEqual (\_SB.GGOV (PSG1), PSG1_ACTIVATE)) { // Pull S0IX_EN_TRY_REQ GPIO to low to notify PD controller \_SB.SGOV (PSG1, PSG1_DEACTIVATE) Store (0, Local0) While (LLess (Local0, 100)) { // Timeout is 1 second Sleep (10) // Wait for PD_SX_ACK_G2_FP_PCH to low until timeout If (LEqual (\_SB.GGIV (PSG2), PSG1_DEACTIVATE)) { Break } Else { // Time out in 1 sec Increment (Local0) } } } else { } } PDDP () } // In some platforms BIOS to PD handshake was limited to only Sx flows and handled during OSPM call to _PTS control method. // In order to support PS_ON# during S0ix and still have legacy support for Sx, changes had to be made to the BIOS flow. // The following section highlights the changes: // - BIOS will configure USB controller and PCIe root port to which TBT controller is connected as a shared power resource package to OSPM. // - The new method is invoked when USB controller is in D3 hot and PCIe downstream ports are in D3 cold state. // - The high-level flow for entry and exit is described as below: // Entry of the shared power resource package - // - The entry of shared power resource package is only invoked by OSPM after USB host controller is in D3 hot and TBT downstream ports // are in D3 cold, or OSPM invokes low power S0 idle entry indication as a strong hint. // - In order to support better user experience, BIOS may allow PS_ON override check when the devices are in D3 and system is in S0 // yet to low power S0 idle. // And when the devices are in D3 state and OSPM signaled low power S0 idle entry as well, BIOS can disable PS_ON override, proceed PD // low power transition in case they don't want to support wake for bus powered devices. // // // Handshaking is locked when PPEN is invoked back to back. // Handshaking will be unblocked when S0ix exit is invoked. // // // Power Sequence RTD3 Entry RTD3 Exit // // USBC_PSON_OVERRIDE_N // (by PD, 0 means override enabled) 0 0 // // Level - Before 0 1 // // PS_ON State Veto No change // // Level - After 1 0 // // Lock False False // // PLX_SX_ENTRY_G1_PCH // (by BIOS, 1 means to request PD 0 0 // to PS_ON mode) // // // Power Sequence RTD3 Entry MS Fun#5 RTD3 Exit RTD3 Entry MS Fun#6 RTD3 Exit (?? What if no??) // // USBC_PSON_OVERRIDE_N // (by PD, 0 means override enabled) 0 0 0 0 0 0 // // Level - Before 0 1 2 2 2 1 // // PS_ON State Veto Restore No change No change No change No change // // Level - After 1 2 2 2 1 0 // // Lock False True True True False False // // PLX_SX_ENTRY_G1_PCH // (by BIOS, 1 means to request PD 0 1 1 1 1 0 // to PS_ON mode) // // // // Power Sequence MS Fun#5 RTD3 Entry MS Fun#6 RTD3 Exit RTD3 entry // // USBC_PSON_OVERRIDE_N // (by PD, 0 means override enabled) 0 0 0 0 0 // // Level - Before 0 1 2 1 0 // // PS_ON State Veto Restore No change No change Veto // // Level - After 1 2 1 0 1 // // Lock False True False False False // // PLX_SX_ENTRY_G1_PCH // (by BIOS, 1 means to request PD 0 1 1 0 0 // to PS_ON mode) // // // // Power Sequence MS Fun#5 RTD3 Entry MS Fun#6 MS Fun#5 // // USBC_PSON_OVERRIDE_N // (by PD, 0 means override enabled) 0 0 0 0 // // Level - Before 0 1 2 1 // // PS_ON State Veto Restore No change No change // // Level - After 1 2 1 2 // // Lock False True False True // // PLX_SX_ENTRY_G1_PCH // (by BIOS, 1 means to request PD 0 1 1 1 // to PS_ON mode) // // // // Power Sequence RTD3 Entry RTD3 Exit // // USBC_PSON_OVERRIDE_N // (by PD, 0 means override enabled) 1 1 // // Level - Before 0 1 // // PS_ON State No change No change // // Level - After 1 0 // // Lock False False // // PLX_SX_ENTRY_G1_PCH // (by BIOS, 1 means to request PD 1 0 // to PS_ON mode) // // // // Power Sequence RTD3 Entry MS Fun#5 RTD3 Exit RTD3 Entry MS Fun#6 RTD3 Exit (?? What if no??) // // USBC_PSON_OVERRIDE_N // (by PD, 0 means override enabled) 1 1 1 1 1 1 // // Level - Before 0 1 2 2 2 1 // // PS_ON State No change No change No change No change No change No change // // Level - After 1 2 2 2 1 0 // // Lock False True True True False False // // PLX_SX_ENTRY_G1_PCH // (by BIOS, 1 means to request PD 1 1 1 1 1 0 // to PS_ON mode) // // // Power Sequence MS Fun#5 RTD3 Entry MS Fun#6 RTD3 Exit RTD3 entry // // USBC_PSON_OVERRIDE_N // (by PD, 0 means override enabled) 1 1 1 1 1 // // Level - Before 0 1 2 1 0 // // PS_ON State No change No change No change No change No change // // Level - After 1 2 1 0 1 // // Lock False True False False False // // PLX_SX_ENTRY_G1_PCH // (by BIOS, 1 means to request PD 1 1 1 0 1 // to PS_ON mode) // // // Power Sequence MS Fun#5 RTD3 Entry MS Fun#6 MS Fun#5 // // USBC_PSON_OVERRIDE_N // (by PD, 0 means override enabled) 1 1 1 1 // // Level - Before 0 1 2 1 // // PS_ON State No change No change No change No change // // Level - After 1 2 1 2 // // Lock False True False True // // PLX_SX_ENTRY_G1_PCH // (by BIOS, 1 means to request PD 1 1 1 1 // to PS_ON mode) // // NCS1 Method Method (NCS1, 0, Serialized) { If (LEqual (PSON, 1)) { PDOF () } else { } GPRV (2, 0) // Allow PS_ON# (restore) } // XCS1 Method Method (XCS1, 0, Serialized) { PDON () } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // PD PS ON Override Methods // // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PPEN PD PSON Entry Method // When ENABLE_OVERRIDE (BIOS option) is enabled by platform, BIOS checks if USBC_PSON_OVERRIDE_N is asserted by PD to override PS_ON. // - If USBC_PSON_OVERRIDE_N (PD signal) is asserted, which means "PD PS_ON override" is requested by PD, then BIOS override(veto) PS_ON#. // - If USBC_PSON_OVERRIDE_N (PD signal) is deasserted, then continue with PD handshake to request PD transit to PS_ON state. // # Assert PLX_SX_ENTRY_G1_PCH_N to high // # Wait for PD_SX_ACK_G2_PCH being pulled high by PD or until timeout // // Moreover, in order to support better user experience, BIOS may allow PS_ON override check when (1) the devices are in D3 and system is in S0 // yet to low power S0 idle or (2) the devices are still in D0 while OSPM gives low power S0 idle entry notification. // And when the devices are in D3 state and OSPM signaled low power S0 idle entry as well, BIOS can disable PS_ON override, proceed PD // PS_ON transition in case they don't want to support wake for bus powered devices. Each one condition upgrade one level // (starting from 0). Once both conditions are satisfied, enforce PD to PS_ON state to support PS_ON unless platform disables // PD PS_ON support. Method (PPEN, 0, Serialized) { PDBG () Switch (ToInteger(PDLV)) { Case (0) { // This is new cycle of PD PS_ON flow Increment (PDLV) // Level++ // POVP is the GPIO pin for USBC_PSON_OVERRIDE_N // PPOE is the BIOS setting for PD PS_ON Enable // PPOE = 0 : PD PS_ON disable // PPOE = 1 : PD PS_ON enable // PPOE = 2 : PD PS_ON enable with override enable If (LAnd (LEqual (PPOE, 2), LEqual (\_SB.GGIV (POVP), 0))) { // PD requests to override(veto) PS_ON GPRV (2, 1) // Veto PS_ON# Break } else { // PD doesn't request to override(veto) PS_ON // Continue to PD PS_ON enable NCS1 () Break } } Case (1) { NCS1 () Increment (PDLV) // Level++ Store (1, PDLK) // Lock the PD PS_ON override for this group Break } Default { If (LEqual (PDLK, 0)) { } } } PDBG () Return (PDLV) } // PPEX PD PSON Exit Method // When ENABLE_OVERRIDE (BIOS option) is enabled by platform, BIOS checks if PLX_SX_ENTRY_G1_PCH_N (PD signal) is low. If it is, which means // "PD PS_ON" was entered, then BIOS notify PD to exit PS_ON mode as following // - BIOS pulls PLX_SX_ENTRY_G1_PCH_N to high. // - BIOS wait for PD_SX_ACK_G2_PCH being pulled to low by PD or until timeout. // // Moreover, in order to support better user experience, BIOS may wait for PD response in USB and PCIe RP _PS0 while PD delay introduce // responsiveness impact. Method (PPEX, 0, Serialized) { PDBG () If (LEqual (PDLK, 1)) { Return (PDLV) } Switch (ToInteger (PDLV)) { Case (0) { // This is new cycle of PD PS_ON flow Break } Case (1) { XCS1 () // remove this when the "break" issue will be fixed Decrement (PDLV) Break } Case (2) { Decrement (PDLV) Break } Default { If (LEqual (PDLK, 0)) { } } } PDBG () Return (PDLV) } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // PD PS_ON Low Power S0 idle Method // // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PSLI PD PS_ON Low Power S0 idle Method // Invoke the method by Low Power S0 idle Entry Notification // // Input: Arg0 -> Low Power S0 idle function# // If Arg0 = 5, execute low power S0 idle entry notification // If Arg0 = 6, execute low power S0 idle exit notification Method (PSLI, 1, Serialized) { Switch (ToInteger (Arg0)) { Case (5) { If (LLess (PDLV, 1)) { Store (1, PDLV) } PPEN () } Case (6) { Store (0, PDLK) // Unlock the PD PS_ON override for this group Store (1, PDLV) PPEX () } Default { } } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // PD PS_ON Sleep Method // // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PSLP PD PS_ON Sleep Method // Invoke the method by Sleep Entry Notification // // Input: Arg0 -> Sleep type, not used now; placeholder Method (PSLP, 1, Serialized) { Store (1, PDLV) PPEN () // Reset this group for next Sx exit Store (0, PDLV) Store (0, PDLK) } // A group includes a PCIe RP where the TBT controller connected to, and a set of USB2/3 port or xHCI // Each group has unique variable to manage the PD PS_ON flow Name (PDSA, 0x1) // PD State; variable to save power state // 0 - PD PS_ON request sent, PD is in PS_ON mode // 1 - PD PS_ON request cleared PowerResource (PDPG, 0, 0) // Turn on second, turn off second to last { Method (_STA, 0) { Return (PDSA) } Method (_ON) { PPEX () if (LEqual (PDLV, 0)) { Store (1, PDSA) // PD is not in PS_ON mode } } Method (_OFF) { PPEN () if (LEqual (PDLV, 2)) { Store (0, PDSA) // PD is in PS_ON mode } } } // End PowerResource (PDPG)