| /** |
| * @file |
| * |
| * ALIB ASL library |
| * |
| * |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: GNB |
| * @e \$Revision: 31805 $ @e \$Date: 2010-05-21 17:58:16 -0700 (Fri, 21 May 2010) $ |
| * |
| */ |
| /* |
| ***************************************************************************** |
| * |
| * Copyright (c) 2011, Advanced Micro Devices, Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * * Neither the name of Advanced Micro Devices, Inc. nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| **************************************************************************** |
| * |
| */ |
| |
| External(\_SB.ALIC, MethodObj) |
| |
| Name (varStartPhyLane, 0) |
| Name (varEndPhyLane, 0) |
| Name (varStartCoreLane, 0) |
| Name (varEndCoreLane, 0) |
| Name (varWrapperId, 0) |
| Name (varPortId, 0) |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Set PCIe Bus Width |
| * |
| * Arg0 - Data Buffer |
| */ |
| Method (procPcieSetBusWidth, 1, NotSerialized) { |
| Store (Buffer (256) {}, Local7) |
| CreateWordField (Local7, 0x0, varReturnBufferLength) |
| CreateWordField (Local7, 0x2, varReturnBusWidth) |
| CreateByteField (Arg0, 0x2, varArgBusWidth) |
| //deternime correct lane bitmap (check for reversal) gate/ungate unused lanes |
| Store (3, varReturnBufferLength) |
| Store (varArgBusWidth, varReturnBusWidth) |
| return (Local7) |
| } |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * PCIe port hotplug |
| * |
| * Arg0 - Data Buffer |
| * Retval - Return buffer |
| */ |
| Method (procPciePortHotplug, 1, Serialized) { |
| Store ("PciePortHotplug Enter", Debug) |
| Store (DerefOf (Index (Arg0, 4)), varHotplugStateLocal0) |
| Store (DerefOf (Index (Arg0, 2)), varPortIndexLocal1) |
| |
| Subtract (ShiftRight (varPortBdfLocal1, 3), 2, varPortIndexLocal1) |
| if (LEqual(varHotplugStateLocal0, 1)) { |
| // Enable port |
| Store (DEF_TRAINING_STATE_RELEASE_TRAINING, Local2) |
| } else { |
| // Disable port |
| Store (DEF_TRAINING_STATE_NOT_PRESENT, Local2) |
| } |
| |
| Store (procPciePortTraining (varPortIndexLocal1, Local2), varHotplugStateLocal0) |
| |
| Store (Buffer (10) {}, Local7) |
| CreateWordField (Local7, 0x0, varReturnBufferLength) |
| CreateByteField (Local7, 0x2, varReturnStatus) |
| CreateByteField (Local7, 0x3, varReturnDeviceStatus) |
| Store (0x4, varReturnBufferLength) |
| Store (0x0, varReturnStatus) |
| Store (varHotplugStateLocal0, varReturnDeviceStatus) |
| Store ("PciePortHotplug Exit", Debug) |
| return (Local7) |
| } |
| |
| Name (varSpeedRequest, Buffer (10) {0,0,0,0,0,0,0,0,0,0}) |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Train PCIe port |
| * |
| * |
| * Arg0 - Port Index |
| * Arg1 - Initial state |
| */ |
| Method (procPciePortTraining, 2, Serialized) { |
| Store ("PciePortTraining Enter", Debug) |
| Store (DEF_HOTPLUG_STATUS_DEVICE_NOT_PRESENT, varResultLocal4) |
| Store (procPcieGetPortInfo (Arg0), Local7) |
| // Check if port supports basic hotplug |
| Store (DerefOf (Index (Local7, DEF_OFFSET_LINK_HOTPLUG)), varTempLocal1) |
| if (LNotEqual (varTempLocal1, DEF_BASIC_HOTPLUG)) { |
| Store (" No action.[Hotplug type]", Debug) |
| Store ("procPciePortTraining Exit", Debug) |
| return (varResultLocal4) |
| } |
| Store (Arg1, varStateLocal2) |
| while (LNotEqual (varStateLocal2, DEF_TRAINING_STATE_EXIT)) { |
| if (LEqual (varStateLocal2, DEF_TRAINING_STATE_RELEASE_TRAINING)) { |
| Store (" State: Release training", Debug) |
| // Remove link speed override |
| Store (0, Index (varOverrideLinkSpeed, Arg0)) |
| // Enable link width upconfigure |
| procPciePortIndirectRegisterRMW (Arg0, 0xA2, Not (0x2000), 0x0000) |
| // Request Max link speed for hotplug by going to AC state |
| Store (0, varPsppAcDcOverride) |
| procApplyPsppState () |
| // Power on/enable port lanes |
| procPcieLaneControl (Arg0, DEF_PCIE_LANE_POWERON) |
| // Release training |
| procPcieTrainingControl (Arg0, 0) |
| // Move to next state to check presence detection |
| Store (DEF_TRAINING_STATE_DETECT_PRESENCE, varStateLocal2) |
| // Initialize retry count |
| Store(0, varCountLocal3) |
| } |
| if (LEqual (varStateLocal2, DEF_TRAINING_STATE_DETECT_PRESENCE)) { |
| Store (" State: Detect presence", Debug) |
| And (procPciePortIndirectRegisterRead (Arg0, 0xa5), 0x3f, varTempLocal1) |
| if (LGreater (varTempLocal1, 0x4)) { |
| // device connection detected move to next state |
| Store (DEF_TRAINING_STATE_PRESENCE_DETECTED, varStateLocal2) |
| // reset retry counter |
| Store(0, varCountLocal3) |
| continue |
| } |
| if (LLess (varCountLocal3, 80)) { |
| Sleep (1) |
| Increment (varCountLocal3) |
| } else { |
| // detection time expired move to device not present state |
| Store (DEF_TRAINING_STATE_NOT_PRESENT, varStateLocal2) |
| } |
| } |
| if (LEqual (varStateLocal2, DEF_TRAINING_STATE_PRESENCE_DETECTED)) { |
| Store (" State: Device detected", Debug) |
| Store (procPciePortIndirectRegisterRead (Arg0, 0xa5), varTempLocal1) |
| And (varTempLocal1, 0x3f, varTempLocal1) |
| if (LEqual (varTempLocal1, 0x10)) { |
| Store (DEF_TRAINING_DEVICE_PRESENT, varStateLocal2) |
| continue |
| } |
| if (LLess (varCountLocal3, 80)) { |
| Sleep (1) |
| Increment (varCountLocal3) |
| continue |
| } |
| Store (DEF_TRAINING_STATE_NOT_PRESENT, varStateLocal2) |
| |
| if (LEqual (DeRefOf (Index (varOverrideLinkSpeed, Arg0)), DEF_LINK_SPEED_GEN1)) { |
| // GEN2 workaround already applied but device not trained successfully move device not present state |
| continue |
| } |
| |
| if (LEqual (procPcieCheckForGen2Workaround (Arg0), TRUE)) { |
| Store (" Request Gen2 workaround", Debug) |
| procPciePortIndirectRegisterRMW (Arg0, 0xA2, Not (0x2000), 0x2000) |
| Store (DEF_LINK_SPEED_GEN1, Index (varOverrideLinkSpeed, Arg0)) |
| procPcieSetLinkSpeed (Arg0, DEF_LINK_SPEED_GEN1) |
| Store (DEF_TRAINING_STATE_REQUEST_RESET, varStateLocal2) |
| } |
| } |
| if (LEqual (varStateLocal2, DEF_TRAINING_STATE_NOT_PRESENT)) { |
| Store (" State: Device not present", Debug) |
| procPcieTrainingControl (Arg0, 1) |
| procPcieLaneControl (Arg0, DEF_PCIE_LANE_POWEROFF) |
| // Exclude device from PSPP managment since it is not present |
| Store (DEF_LINK_SPEED_GEN1, Index (varOverrideLinkSpeed, Arg0)) |
| Store (DEF_TRAINING_STATE_COMPLETE, varStateLocal2) |
| } |
| if (LEqual (varStateLocal2, DEF_TRAINING_STATE_REQUEST_RESET)) { |
| Store (" State: Request Reset", Debug) |
| if (CondRefOf (\_SB.ALIC, Local6)) { |
| Store (" Call ALIC method", Debug) |
| //varTempLocal1 contain port BDF |
| Store(ShiftLeft (Add (Arg0, 2), 3), varTempLocal1) |
| \_SB.ALIC (varTempLocal1, 0) |
| Sleep (2) |
| \_SB.ALIC (varTempLocal1, 1) |
| Store (0, varCountLocal3) |
| Store (DEF_TRAINING_STATE_DETECT_PRESENCE, varStateLocal2) |
| continue |
| } |
| Store (DEF_TRAINING_STATE_NOT_PRESENT, varStateLocal2) |
| } |
| if (LEqual (varStateLocal2, DEF_TRAINING_DEVICE_PRESENT)) { |
| Store (" State: Device present", Debug) |
| Store (DEF_HOTPLUG_STATUS_DEVICE_PRESENT, varResultLocal4) |
| Store (DEF_TRAINING_STATE_COMPLETE, varStateLocal2) |
| procPcieLaneControl (Arg0, DEF_PCIE_LANE_POWEROFFUNUSED) |
| } |
| if (LEqual (varStateLocal2, DEF_TRAINING_STATE_COMPLETE)) { |
| |
| Store (1, varPsppAcDcOverride) |
| procApplyPsppState () |
| |
| Store (DEF_TRAINING_STATE_EXIT, varStateLocal2) |
| } |
| } |
| Store ("PciePortTraining Exit", Debug) |
| return (varResultLocal4) |
| } |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Lane control |
| * |
| * Arg0 - Port Index |
| * Arg1 - 0 - Power off all lanes / 1 - Power on all Lanes / 2 Power off unused lanes |
| */ |
| |
| Method (procPcieLaneControl, 2, Serialized) { |
| Store ("PcieLaneControl Enter", Debug) |
| Store (Concatenate (" Arg0 : ", ToHexString (Arg0), varStringBuffer), Debug) |
| Store (Concatenate (" Arg1 : ", ToHexString (Arg1), varStringBuffer), Debug) |
| Store (procPcieGetPortInfo (Arg0), Local7) |
| #ifdef PCIE_PHY_LANE_POWER_GATE_SUPPORT |
| Store (DerefOf (Index (Local7, DEF_OFFSET_START_PHY_LANE)), varStartPhyLane) |
| Store (DerefOf (Index (Local7, DEF_OFFSET_END_PHY_LANE)), varEndPhyLane) |
| #endif |
| Store (DerefOf (Index (Local7, DEF_OFFSET_START_CORE_LANE)), varStartCoreLane) |
| Store (DerefOf (Index (Local7, DEF_OFFSET_END_CORE_LANE)), varEndCoreLane) |
| |
| if (LEqual (Arg1, DEF_PCIE_LANE_POWEROFF)) { |
| procPcieLaneEnableControl (Arg0, varStartCoreLane, varEndCoreLane, 1) |
| #ifdef PCIE_PHY_LANE_POWER_GATE_SUPPORT |
| procPcieLanePowerControl (varStartPhyLane, varEndPhyLane, 1) |
| #endif |
| } |
| if (LEqual (Arg1, DEF_PCIE_LANE_POWERON)) { |
| #ifdef PCIE_PHY_LANE_POWER_GATE_SUPPORT |
| procPcieLanePowerControl (varStartPhyLane, varEndPhyLane, 0) |
| #endif |
| procPcieLaneEnableControl (Arg0, varStartCoreLane, varEndCoreLane, 0) |
| } |
| if (LNotEqual (Arg1, DEF_PCIE_LANE_POWEROFFUNUSED)) { |
| return (0) |
| } |
| Store (procPcieGetLinkWidth (Arg0, DEF_LINKWIDTH_ACTIVE), varActiveLinkWidthLocal2) |
| if (LLessEqual (procPcieGetLinkWidth (Arg0, DEF_LINKWIDTH_MAX_PHY), varActiveLinkWidthLocal2)) { |
| // Active link equal max link width, nothing needs to be done |
| return (0) |
| } |
| Store (procPcieIsPortReversed (Arg0), varIsReversedLocal1) |
| //There is unused lanes after device plugged |
| if (LEqual(varIsReversedLocal1, FALSE)) { |
| Store (" Port Not Reversed", Debug) |
| // Link not reversed |
| Add (varStartCoreLane, varActiveLinkWidthLocal2, Local3) |
| Store (varEndCoreLane, Local4) |
| } else { |
| // Link reversed |
| Store (" Port Reversed", Debug) |
| Subtract (varEndCoreLane, varActiveLinkWidthLocal2, Local4) |
| Store (varStartCoreLane, Local3) |
| } |
| procPcieLaneEnableControl (Arg0, Local3, Local4, 1) |
| #ifdef PCIE_PHY_LANE_POWER_GATE_SUPPORT |
| if (LGreater (varStartPhyLane, varEndPhyLane)) { |
| Store (varEndPhyLane, Local3) |
| Store (varStartPhyLane, Local4) |
| } else { |
| Store (varEndPhyLane, Local4) |
| Store (varStartPhyLane, Local3) |
| } |
| if (LEqual(varIsReversedLocal1, FALSE)) { |
| // Not reversed |
| Add (Local3, varActiveLinkWidthLocal2, Local3) |
| } else { |
| // Link reversed |
| Subtract (Local4, varActiveLinkWidthLocal2, Local4) |
| } |
| procPcieLanePowerControl (Local3, Local4, 1) |
| #endif |
| return (0) |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Check if GEN2 workaround applicable |
| * |
| * Arg0 - Port Index |
| * Retval - TRUE / FALSE |
| */ |
| |
| Method (procPcieCheckForGen2Workaround, 1, NotSerialized) { |
| Store (Buffer (16) {}, Local1) |
| Store (0x0, Local0) |
| while (LLessEqual (Local0, 0x3)) { |
| Store (procPciePortIndirectRegisterRead (Arg0, Add (Local0, 0xA5)), Local2) |
| Store (Local2, Index (Local1, Multiply (Local0, 4))) |
| Store (ShiftRight (Local2, 8), Index (Local1, Add (Multiply (Local0, 4), 1))) |
| Store (ShiftRight (Local2, 16), Index (Local1, Add (Multiply (Local0, 4), 2))) |
| Store (ShiftRight (Local2, 24), Index (Local1, Add (Multiply (Local0, 4), 3))) |
| Increment (Local0) |
| } |
| Store (0, Local0) |
| while (LLess (Local0, 15)) { |
| if (LAnd (LEqual (DeRefOf (Index (Local1, Local0)), 0x2a), LEqual (DeRefOf (Index (Local1, Add (Local0, 1))), 0x9))) { |
| return (TRUE) |
| } |
| Increment (Local0) |
| } |
| return (FALSE) |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Is port reversed |
| * |
| * Arg0 - Port Index |
| * Retval - 0 - Not reversed / !=0 - Reversed |
| */ |
| Method (procPcieIsPortReversed , 1, Serialized) { |
| Store (procPcieGetPortInfo (Arg0), Local7) |
| |
| Store (DerefOf (Index (Local7, DEF_OFFSET_START_PHY_LANE)), varStartPhyLane) |
| Store (DerefOf (Index (Local7, DEF_OFFSET_END_PHY_LANE)), varEndPhyLane) |
| Store (0, Local0) |
| if (LGreater (varStartPhyLane, varEndPhyLane)) { |
| Store (1, Local0) |
| } |
| And (procPciePortIndirectRegisterRead (Arg0, 0x50), 0x1, Local1) |
| return (And (Xor (Local0, Local1), 0x1)) |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Training Control |
| * |
| * Arg0 - Port Index |
| * Arg1 - Hold Training (1) / Release Training (0) |
| */ |
| Method (procPcieTrainingControl , 2, NotSerialized) { |
| Store ("PcieTrainingControl Enter", Debug) |
| Store (procPcieGetPortInfo (Arg0), Local7) |
| Store (DerefOf (Index (Local7, DEF_OFFSET_PORT_ID)), varPortId) |
| Store ( |
| Or (ShiftLeft (DerefOf (Index (Local7, Add (DEF_OFFSET_WRAPPER_ID, 1))), 8), DerefOf (Index (Local7, DEF_OFFSET_WRAPPER_ID))), |
| varWrapperId |
| ) |
| procIndirectRegisterRMW (0x0, 0xE0, Or (ShiftLeft (varWrapperId, 16), Add (0x800, Multiply (0x100, varPortId))), Not (0x1), Arg1); |
| Store ("PcieTrainingControl Exit", Debug) |
| } |
| |
| |
| Name (varLinkWidthBuffer, Buffer () {0, 1, 2, 4, 8, 12, 16}) |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Get actual negotiated/PHY or core link width |
| * |
| * Arg0 - Port Index |
| * Arg1 - 0/1 Negotiated/Phy |
| * Retval - Link Width |
| */ |
| Method (procPcieGetLinkWidth, 2, NotSerialized) { |
| Store ("PcieGetLinkWidth Enter", Debug) |
| Store (Concatenate (" Arg0 : ", ToHexString (Arg0), varStringBuffer), Debug) |
| Store (Concatenate (" Arg1 : ", ToHexString (Arg1), varStringBuffer), Debug) |
| |
| if (LEqual (Arg1, DEF_LINKWIDTH_ACTIVE)){ |
| //Get negotiated length |
| And (ShiftRight (procPciePortIndirectRegisterRead (Arg0, 0xA2), 4), 0x7, Local0) |
| Store (DeRefOf (Index (varLinkWidthBuffer, Local0)), Local1) |
| Store (Concatenate (" Active Link Width :", ToHexString (Local1), varStringBuffer), Debug) |
| } else { |
| //Get phy length |
| Store (procPcieGetPortInfo (Arg0), Local7) |
| Store (DerefOf (Index (Local7, DEF_OFFSET_START_PHY_LANE)), varStartPhyLane) |
| Store (DerefOf (Index (Local7, DEF_OFFSET_END_PHY_LANE)), varEndPhyLane) |
| if (LGreater (varStartPhyLane, varEndPhyLane)) { |
| Subtract (varStartPhyLane, varEndPhyLane, Local1) |
| } else { |
| Subtract (varEndPhyLane, varStartPhyLane, Local1) |
| } |
| Increment (Local1) |
| Store (Concatenate (" PHY Link Width :", ToHexString (Local1), varStringBuffer), Debug) |
| } |
| Store ("PcieGetLinkWidth Exit", Debug) |
| return (Local1) |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * PCIe lane mux lane enable control (hotplug support) |
| * |
| * Arg0 - Port Index |
| * Arg1 - Start Lane |
| * Arg2 - End Lane |
| * Arg3 - Enable(0) / Disable(1) |
| */ |
| Method (procPcieLaneEnableControl, 4, Serialized) { |
| Store ("PcieLaneEnableControl Enter", Debug) |
| Store (Concatenate (" Arg0 : ", ToHexString (Arg0), varStringBuffer), Debug) |
| Store (Concatenate (" Arg1 : ", ToHexString (Arg1), varStringBuffer), Debug) |
| Store (Concatenate (" Arg2 : ", ToHexString (Arg2), varStringBuffer), Debug) |
| Store (Concatenate (" Arg3 : ", ToHexString (Arg3), varStringBuffer), Debug) |
| Store (procPcieGetPortInfo (Arg0), Local7) |
| Store (Arg1, varStartCoreLane) |
| Store (Arg2, varEndCoreLane) |
| Store ( |
| Or (ShiftLeft (DerefOf (Index (Local7, Add (DEF_OFFSET_WRAPPER_ID, 1))), 8), DerefOf (Index (Local7, DEF_OFFSET_WRAPPER_ID))), |
| varWrapperId |
| ) |
| if (LGreater (varStartCoreLane, varEndCoreLane)) { |
| Subtract (varStartCoreLane, varEndCoreLane, Local1) |
| Store (varEndCoreLane, Local2) |
| } else { |
| Subtract (varEndCoreLane, varStartCoreLane, Local1) |
| Store (varStartCoreLane, Local2) |
| } |
| ShiftLeft (Subtract (ShiftLeft (1, Add (Local1, 1)), 1), Local2, varLaneBitmapOrMaskLocal3) |
| Store (Not (varLaneBitmapOrMaskLocal3), varLaneBitmapAndMaskLocal4) |
| Store (Concatenate ("Lane Bitmap : ", ToHexString (varLaneBitmapOrMaskLocal3), varStringBuffer), Debug) |
| if (Lequal (Arg3, 1)) { |
| Store (0, varLaneBitmapOrMaskLocal3) |
| } |
| procIndirectRegisterRMW (0x0, 0xE0, Or (ShiftLeft (varWrapperId, 16), 0x8023), varLaneBitmapAndMaskLocal4, varLaneBitmapOrMaskLocal3); |
| Stall (10) |
| Store ("PcieLaneEnableControl Exit", Debug) |
| } |
| |
| |