/** * @file * * ALIB ASL library * * * * @xrefitem bom "File Content Label" "Release Content" * @e project: AGESA * @e sub-project: GNB * @e \$Revision: 49874 $ @e \$Date: 2011-03-30 11:18:34 +0800 (Wed, 30 Mar 2011) $ * */ /* ***************************************************************************** * * 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) Name (varNormalizeLinkWidthBuffer, Buffer () {1, 2, 4, 4, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16}) /*----------------------------------------------------------------------------------------*/ /** * Set PCIe Bus Width * * Arg0 - Data Buffer */ Method (procPcieSetBusWidth, 1, NotSerialized) { Store ("procPcieSetBusWidth Enter", Debug) Name (varClientBus, 0) Name (varArgBusWidth, 0) Store (0, varPortIndex) Store (Buffer (10) {}, Local7) //ClientId: WORD //Bits 2-0: Function number. //Bits 7-3: Device number. //Bits 15-8: Bus number. Store (DerefOf (Index (Arg0, 0x3)), varClientBus) Store (DerefOf (Index (Arg0, 0x4)), varArgBusWidth) Store (Concatenate (" Client Bus : ", ToHexString (varClientBus), varStringBuffer), Debug) Store (Concatenate (" Arg Bus Width : ", ToHexString (varArgBusWidth), varStringBuffer), Debug) Store (3, Index (Local7, 0x0)) // Return Buffer Length Store (0, Index (Local7, 0x1)) // Return Buffer Length Store (varArgBusWidth, Index (Local7, 0x2)) // Return BusWidth //deternime correct lane bitmap (check for reversal) gate/ungate unused lanes // determine port index base on "Client ID" while (LLessEqual (varPortIndex, varMaxPortIndexNumber)) { if (LEqual (procChecPortAllocated (varPortIndex), DEF_PORT_ALLOCATED)) { Store (procPciDwordRead (ShiftLeft (Add( varPortIndex, 2), 3), 0x18), Local1) And (ShiftRight (Local1, 16), 0xff, varSubordinateBusLocal2) //Local2 Port Subordinate Bus number And (ShiftRight (Local1, 8), 0xff, varSecondaryBusLocal1) //Local1 Port Secondary Bus number if (LAnd (LGreaterEqual (varClientBus, Local1), LLessEqual(varClientBus, Local2))) { break } } Increment (varPortIndex) } if (LGreater (varPortIndex, varMaxPortIndexNumber)) { Store ("procPcieSetBusWidth Exit -- over max port index", Debug) return (Local7) } Store (Concatenate (" Pcie Set BusWidth for port index : ", ToHexString (varPortIndex), varStringBuffer), Debug) // Normalize link width (Num Lanes) to correct value x1, x2.x4,x8,x16, // make sure that number of lanes requested to be powered on less or equal mx port link width if (LLessEqual (procPcieGetLinkWidth (varPortIndex, DEF_LINKWIDTH_MAX_PHY), varArgBusWidth)) { // Active link equal max link width, nothing needs to be done Store ("procPcieSetBusWidth Exit -- over max lanes supported", Debug) return (Local7) } Store (DeRefOf (Index (varNormalizeLinkWidthBuffer, varArgBusWidth)), Local1) // call procPcieLaneControl to power on all lanes (Arg0 - port index , Arg1 - 1, Arg2 = 0) procPcieLaneControl (varPortIndex, DEF_PCIE_LANE_POWERON, 0) // call procPcieLaneControl power off unused lanes (Arg0 - port index, Arg1 - 1, Arg2 = Link width) procPcieLaneControl (varPortIndex, DEF_PCIE_LANE_POWEROFFUNUSED, Local1) #ifdef PHY_SPEED_REPORT_SUPPORT procReportPhySpeedCap () #endif Store (Local1, Index (Local7, 0x2)) // Return BusWidth Store ("procPcieSetBusWidth Exit", Debug) 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) #ifdef PHY_SPEED_REPORT_SUPPORT procReportPhySpeedCap () #endif 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, 0) // 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, 0) // 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) #ifdef PCIE_DISABLE_UNUSED_LANES_ON_ACTIVE_LINK procPcieLaneControl (Arg0, DEF_PCIE_LANE_POWEROFFUNUSED, 0) #endif } 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 * Arg2 - link width */ Method (procPcieLaneControl, 3, 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) } // Local2 should have link width (active lanes) // Local3 should have first non active lanes // Local4 should have last non active lanes if (LEqual(Arg2, 0)) { Store (procPcieGetLinkWidth (Arg0, DEF_LINKWIDTH_ACTIVE), varActiveLinkWidthLocal2) } else { Store ( Arg2 , varActiveLinkWidthLocal2) } // Let say Link width is x1 than local2 = 1, Local3 = 1 Local4 = 15 for non reversed case // while for reversed case should be Local2 = 1 Local3 = 0 and Local4 = 14 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) }