/* $NoKeywords:$ */
/**
 * @file
 *
 * Config Fch Gpp controller
 *
 * Init Gpp Controller features.
 *
 * @xrefitem bom "File Content Label" "Release Content"
 * @e project:     AGESA
 * @e sub-project: FCH
 * @e \$Revision: 49753 $   @e \$Date: 2011-03-29 04:51:46 +0800 (Tue, 29 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.
****************************************************************************
*/
#include "FchPlatform.h"
#include "Ids.h"
#include "Filecode.h"
#define FILECODE PROC_FCH_PCIE_GPPENV_FILECODE
//
// Declaration of local functions
//
VOID  FchGppRasInitialization (IN FCH_DATA_BLOCK* FchDataPtr);
VOID  FchGppAerInitialization (IN FCH_DATA_BLOCK* FchDataPtr);
VOID  PreInitGppLink (IN FCH_DATA_BLOCK* FchDataPtr);
UINT8 CheckGppLinkStatus (IN FCH_DATA_BLOCK* FchDataPtr);
VOID  AfterGppLinkInit (IN FCH_DATA_BLOCK* FchDataPtr);

//
//-----------------------------------------------------------------------------------
// Early GPP initialization sequence:
//
// 1) Set port enable bit fields by current GPP link configuration mode
// 2) Deassert GPP reset and pull EP out of reset - Clear GPP_RESET (abcfg:0xC0[8] = 0)
// 3) Loop polling for the link status of all ports
// 4) Misc operations after link training:
//      - (optional) Detect GFX device
//      - Hide empty GPP configuration spaces (Disable empty GPP ports)
//      - (optional) Power down unused GPP ports
//      - (optional) Configure PCIE_P2P_Int_Map (abcfg:0xC4[7:0])
// 5) GPP init completed
//
//
// *) Gen2 vs Gen1
//                                   Gen2 mode     Gen1 mode
//  ---------------------------------------------------------------
//    STRAP_PHY_PLL_CLKF[6:0]          7'h32         7'h19
//    STRAP_BIF_GEN2_EN                  1             0
//
//    PCIE_PHY_PLL clock locks @       5GHz
//
//

/**
 * FchInitEnvGpp - Config Gpp controller before PCI emulation
 *
 *  - GppEarlyInit
 *
 * @param[in] FchDataPtr Fch configuration structure pointer.
 *
 */
VOID
FchInitEnvGpp (
  IN  VOID     *FchDataPtr
  )
{
  //
  // GppEarlyInit
  //
  UINT8        FchGppMemWrImprove;
  UINT8        FchGppLaneReversal;
  UINT8        FchAlinkPhyPllPowerDown;
  UINT32       AbValue;
  FCH_DATA_BLOCK         *LocalCfgPtr;
  AMD_CONFIG_PARAMS      *StdHeader;

  LocalCfgPtr = (FCH_DATA_BLOCK *) FchDataPtr;
  StdHeader = LocalCfgPtr->StdHeader;

  FchGppMemWrImprove = LocalCfgPtr->Gpp.GppMemWrImprove;
  FchGppLaneReversal = (UINT8) LocalCfgPtr->Gpp.GppLaneReversal;
  FchAlinkPhyPllPowerDown = (UINT8) LocalCfgPtr->Ab.UmiPhyPllPowerDown;

  OutPort80 (0x90, StdHeader);

  //
  // Configure NB-FCH link PCIE PHY PLL power down for L1
  //
  if ( FchAlinkPhyPllPowerDown == TRUE ) {
    //
    // Set PCIE_P_CNTL in Alink PCIEIND space
    //
    WriteAlink (FCH_AX_INDXC_REG30 | (UINT32) (AXINDC << 29), 0x40, StdHeader);
    AbValue = ReadAlink (FCH_AX_DATAC_REG34 | (UINT32) (AXINDC << 29), StdHeader);
    AbValue |= BIT12 + BIT3 + BIT0;
    AbValue &= ~(BIT9 + BIT4);
    WriteAlink (FCH_AX_DATAC_REG34 | (UINT32) (AXINDC << 29), AbValue, StdHeader);
    RwAlink (FCH_AX_INDXC_REG02 | (UINT32) (AXINDC << 29), ~(BIT8), (BIT8), StdHeader);
    RwAlink (FCH_AX_INDXC_REG02 | (UINT32) (AXINDC << 29), ~(BIT3), (BIT3), StdHeader);
  }

  //
  // AXINDC_Reg 0xA4[18] = 0x1
  //
  WriteAlink (FCH_AX_INDXP_REG38 | (UINT32) (AXINDP << 29), 0xA4, StdHeader);
  AbValue = ReadAlink (FCH_AX_DATAP_REG3C | (UINT32) (AXINDP << 29), StdHeader);
  AbValue |= BIT18;
  WriteAlink (FCH_AX_DATAP_REG3C | (UINT32) (AXINDP << 29), AbValue, StdHeader);

  //
  // Set ABCFG 0x031C[0] = 1 to enable lane reversal
  //
  AbValue = ReadAlink (FCH_ABCFG_REG31C | (UINT32) (ABCFG << 29), StdHeader);
  if ( FchGppLaneReversal ) {
    WriteAlink (FCH_ABCFG_REG31C | (UINT32) (ABCFG << 29), AbValue | BIT0, StdHeader);
  } else {
    WriteAlink (FCH_ABCFG_REG31C | (UINT32) (ABCFG << 29), AbValue | 0x00, StdHeader);
  }

  //
  // Set abcfg:0x90[20] = 1 to enable GPP bridge multi-function
  //
  AbValue = ReadAlink (FCH_ABCFG_REG90 | (UINT32) (ABCFG << 29), StdHeader);
  WriteAlink (FCH_ABCFG_REG90 | (UINT32) (ABCFG << 29), AbValue | BIT20, StdHeader);

  //
  // Initialize and configure GPP
  //
  if (LocalCfgPtr->Gpp.GppFunctionEnable) {
    ProgramGppTogglePcieReset (LocalCfgPtr->Gpp.GppToggleReset, StdHeader);
    FchGppAerInitialization (LocalCfgPtr);
    FchGppRasInitialization (LocalCfgPtr);

    //
    // PreInit - Enable GPP link training
    //
    PreInitGppLink (LocalCfgPtr);

    //
    // GPP Upstream Memory Write Arbitration Enhancement ABCFG 0x54[26] = 1
    // GPP Memory Write Max Payload Improvement RCINDC_Reg 0x10[12:10] = 0x4
    //
    if ( FchGppMemWrImprove == TRUE ) {
      RwAlink (FCH_ABCFG_REG54 | (UINT32) (ABCFG << 29), ~BIT26, (BIT26), StdHeader);
      RwAlink (FCH_RCINDXC_REG10 | (UINT32) (RCINDXC << 29), ~(BIT12 + BIT11 + BIT10), (BIT12), StdHeader);
    }

    if (CheckGppLinkStatus (LocalCfgPtr) && !LocalCfgPtr->Misc.S3Resume) {
      //
      // Toggle GPP reset (Note this affects all Hudson-2 GPP ports)
      //
      ProgramGppTogglePcieReset (LocalCfgPtr->Gpp.GppToggleReset, StdHeader);
    }

    //
    // Misc operations after link training
    //
    AfterGppLinkInit (LocalCfgPtr);
  }
  FchGppDynamicPowerSaving (LocalCfgPtr);

  OutPort80 (0x9F, StdHeader);
}

/**
 * FchGppAerInitialization - Initializing AER
 *
 *
 * @param[in] FchDataPtr
 *
 */
VOID
FchGppAerInitialization (
  IN  FCH_DATA_BLOCK     *FchDataPtr
  )
{
  AMD_CONFIG_PARAMS     *StdHeader;

  StdHeader = FchDataPtr->StdHeader;

  if (FchDataPtr->Gpp.PcieAer) {
    //
    // GPP strap configuration
    //
    RwAlink (FCH_ABCFG_REG310 | (UINT32) (ABCFG << 29), ~(BIT7 + BIT4), BIT28 + BIT27 + BIT26 + BIT1, StdHeader);
    RwAlink (FCH_ABCFG_REG314 | (UINT32) (ABCFG << 29), ~(UINT32) (0xfff << 15), 0, StdHeader);

    //
    // AB strap configuration
    //
    RwAlink (FCH_ABCFG_REGF0 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT15 + BIT14, StdHeader);
    RwAlink (FCH_ABCFG_REGF4 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT3, StdHeader);
  } else {
    //
    // Hard System Hang running MeatGrinder Test on multiple blocks
    // GPP Error Reporting Configuration
    RwAlink (FCH_ABCFG_REGF0 | (UINT32) (ABCFG << 29), ~(BIT1), 0, StdHeader);
  }

}

/**
 * FchGppRasInitialization - Initializing RAS
 *
 *
 * @param[in] FchDataPtr
 *
 */
VOID
FchGppRasInitialization (
  IN  FCH_DATA_BLOCK     *FchDataPtr
  )
{
  if (FchDataPtr->Gpp.PcieRas) {
    RwAlink (FCH_ABCFG_REGF4 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT0, FchDataPtr->StdHeader);
  }
}

/**
 * PreInitGppLink - Enable GPP link training.
 *
 *
 *
 * @param[in] FchDataPtr Fch configuration structure pointer.
 *
 */
VOID
PreInitGppLink (
  IN  FCH_DATA_BLOCK     *FchDataPtr
  )
{
  GPP_LINKMODE        CfgMode;
  UINT8               PortId;
  UINT32              GppPortCfg;
  UINT16              Tmp16Value;
  FCH_GPP_PORT_CONFIG  *PortCfg;
  AMD_CONFIG_PARAMS     *StdHeader;

  UINT8               PortMask[5] = {
    0x01,
    0x00,
    0x03,
    0x07,
    0x0F
  };

  //
  //  PCIE_GPP_ENABLE (abcfg:0xC0):
  //
  //     GPP_LINK_CONFIG ([3:0])  PortA   PortB   PortC   PortD    Description
  //    ----------------------------------------------------------------------------------
  //                       0000    0-3                             x4 Config
  //                       0001                                    N/A
  //                       0010    0-1     2-3      0              2:2 Config
  //                       0011    0-1      2       3              2:1:1 Config
  //                       0100     0       1       2       3      1:1:1:1 Config
  //
  //  For A12 and above:
  //                  ABCFG:0xC0[12] - Port A hold training (default 1)
  //                  ABCFG:0xC0[13] - Port B hold training (default 1)
  //                  ABCFG:0xC0[14] - Port C hold training (default 1)
  //                  ABCFG:0xC0[15] - Port D hold training (default 1)
  //
  //
  //
  // Set port enable bit fields based on current GPP link configuration mode
  //
  CfgMode = FchDataPtr->Gpp.GppLinkConfig;
  StdHeader = FchDataPtr->StdHeader;

  ASSERT (CfgMode == PortA4 || CfgMode == PortA2B2 || CfgMode == PortA2B1C1 || CfgMode == PortA1B1C1D1);

  GppPortCfg = (UINT32) PortMask[CfgMode];

  //
  // Mask out non-applicable ports according to the target link configuration mode
  //
  for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) {
    FchDataPtr->Gpp.PortCfg[PortId].PortPresent &= (UINT8 ) (GppPortCfg >> PortId) & BIT0;
  }

  //
  // Deassert GPP reset and pull EP out of reset - Clear GPP_RESET (abcfg:0xC0[8] = 0)
  //
  Tmp16Value = (UINT16) (~GppPortCfg << 12);
  GppPortCfg = (UINT32) (Tmp16Value + (GppPortCfg << 4) + CfgMode);
  WriteAlink (FCH_ABCFG_REGC0 | (UINT32) (ABCFG << 29), GppPortCfg, StdHeader);

  GppPortCfg = ReadAlink (0xC0 | (UINT32) (RCINDXC << 29), StdHeader);
  WriteAlink (0xC0 | (UINT32) (RCINDXC << 29), GppPortCfg | 0x400, StdHeader);                 /// Set STRAP_F0_MSI_EN

  //
  // A-Link L1 Entry Delay Shortening
  // AXINDP_Reg 0xA0[7:4] = 0x3
  // KR Does not need this portion of code.
  RwAlink (FCH_AX_INDXP_REGA0, 0xFFFFFF0F, 0x30, StdHeader);
  RwAlink (FCH_AX_INDXP_REGB1, 0xFFFFFFFF, BIT19, StdHeader);
  RwAlink (FCH_AX_INDXP_REGB1, 0xFFFFFFFF, BIT28, StdHeader);

  //
  // GPP L1 Entry Delay Shortening
  // RCINDP_Reg 0xA0[7:4] = 0x1 Enter L1 sooner after ACK'ing PM request.
  // This is done to reduce number of NAK received with L1 enabled.
  //
  for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) {
    RwAlink (FCH_RCINDXP_REGA0 | PortId << 24, 0xFFFFFF0F, 0x10, StdHeader);
    // Hard System Hang running MeatGrinder Test on multiple blocks
    // GPP Error Reporting Configuration
    RwAlink (FCH_RCINDXP_REG6A | PortId << 24, ~(BIT1), 0, StdHeader);
  }

  if (FchDataPtr->Misc.S3Resume) {
    for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) {
      PortCfg = &FchDataPtr->Gpp.PortCfg[PortId];
      if (PortCfg->PortHotPlug == TRUE) {
        PortCfg->PortDetected = FALSE;
      } else {
        if (PortCfg->PortIsGen2 == 1) {
          FchGppForceGen1 (FchDataPtr, (UINT8) (1 << PortId));
        } else {
          FchGppForceGen2 (FchDataPtr, (UINT8) (1 << PortId));
        }
      }
    }
  }

  //
  // Obtain original Gen2 strap value (LC_GEN2_EN_STRAP)
  //
  FchDataPtr->Gpp.GppGen2Strap = (UINT8) (ReadAlink (FCH_RCINDXP_REGA4 | 0 << 24, StdHeader) & BIT0);
}

/**
 * CheckGppLinkStatus - loop polling the link status for each GPP port
 *
 *
 * Return:     ToggleStatus[3:0] = Port bitmap for those need to clear De-emphasis
 *
 * @param[in] FchDataPtr Fch configuration structure pointer.
 *
 */
UINT8
CheckGppLinkStatus (
  IN  FCH_DATA_BLOCK     *FchDataPtr
  )
{
  UINT32              PortId;
  UINT8               PortScanMap;
  UINT8               GppHwDowngrade;
  FCH_GPP_PORT_CONFIG  *PortCfg;
  UINT8               FailedPorts;


  PortScanMap = 0;
  FailedPorts = 0;

  //
  // Obtain a list of ports to be checked
  //
  for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) {
    PortCfg = &FchDataPtr->Gpp.PortCfg[PortId];
    if ( PortCfg->PortPresent == TRUE && PortCfg->PortDetected == FALSE ) {
      PortScanMap |= 1 << PortId;
    }
  }

  GppHwDowngrade = (UINT8)FchDataPtr->Gpp.GppHardwareDownGrade;
  if (GppHwDowngrade != 0) {
    //
    // Skip polling and always assume this port to be present
    //
    PortScanMap &= ~(1 << (GppHwDowngrade - 1));
  }

  //
  //GPP Gen2 Speed Change
  // if ((GPP Gen2 == enabled) and (RCINDP_Reg 0xA4[0] == 0x1)) {
  //   PCIe_Cfg 0x88[3:0]  = 0x2
  //   RCINDP_Reg 0xA2[13] = 0x0
  //   RCINDP_Reg 0xC0[15] = 0x0
  //   RCINDP_Reg 0xA4[29] = 0x1
  // } else {
  //   PCIe_Cfg 0x88[3:0]  = 0x1
  //   RCINDP_Reg 0xA4[0]  = 0x0
  //   RCINDP_Reg 0xA2[13] = 0x1
  //   RCINDP_Reg 0xC0[15] = 0x0
  //   RCINDP_Reg 0xA4[29] = 0x1
  // }
  //
  FchStall (5000, FchDataPtr->StdHeader);
  if (FchDataPtr->Gpp.GppGen2 && FchDataPtr->Gpp.GppGen2Strap) {
    FchGppForceGen2 (FchDataPtr, PortScanMap);
    FailedPorts = GppPortPollingLtssm (FchDataPtr, PortScanMap, TRUE);

    if (FailedPorts) {
      FchGppForceGen1 (FchDataPtr, FailedPorts);
      FailedPorts = GppPortPollingLtssm (FchDataPtr, FailedPorts, FALSE);
    }
  } else {
    FchGppForceGen1 (FchDataPtr, PortScanMap);
    FailedPorts = GppPortPollingLtssm (FchDataPtr, PortScanMap, FALSE);
  }
  return FailedPorts;
}

/**
 * AfterGppLinkInit
 *       - Search for display device behind each GPP port
 *       - If the port is empty AND not hotplug-capable:
 *           * Turn off link training
 *           * (optional) Power down the port
 *           * Hide the configuration space (Turn off the port)
 *
 * @param[in] FchDataPtr Fch configuration structure pointer.
 *
 */
VOID
AfterGppLinkInit (
  IN  FCH_DATA_BLOCK     *FchDataPtr
  )
{
  UINT32              PortId;
  FCH_GPP_PORT_CONFIG  *PortCfg;
  UINT32              RegBusNumber;
  UINT32              AbValue;
  UINT32              AbIndex;
  UINT8               Value;
  UINT8               FchGppGen2;
  AMD_CONFIG_PARAMS     *StdHeader;

  StdHeader = FchDataPtr->StdHeader;
  FchGppGen2 = FchDataPtr->Gpp.GppGen2;

  FchDataPtr->Gpp.GppFoundGfxDev = 0;
  AbValue = ReadAlink (FCH_ABCFG_REGC0 | (UINT32) (ABCFG << 29), StdHeader);
  //
  // Link Bandwidth Notification Capability Enable
  //RCINDC:0xC1[0] = 1
  //
  RwAlink (FCH_RCINDXC_REGC1, 0xFFFFFFFF, BIT0, StdHeader);

  for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) {
    //
    // Program requester ID for every port
    //
    AbIndex = FCH_RCINDXP_REG21 | (UINT32) (RCINDXP << 29) | (PortId << 24);
    WriteAlink (AbIndex, (FCH_GPP_DEV << 3) + PortId, StdHeader);
    //
    // Link Bandwidth Notification Capability Enable
    //PCIe Cfg 0x68[10] = 0
    //PCIe Cfg 0x68[11] = 0
    //
    RwPci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x68), AccessWidth16, ~(BIT10 + BIT11), 0, StdHeader);

    PortCfg = &FchDataPtr->Gpp.PortCfg[PortId];
    //
    // Check if there is GFX device behind each GPP port
    //
    if ( PortCfg->PortDetected == TRUE ) {
      RegBusNumber = (SBTEMP_BUS << 16) + (SBTEMP_BUS << 8);
      WritePci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x18), AccessWidth32, &RegBusNumber, StdHeader);
      ReadPci (PCI_ADDRESS (SBTEMP_BUS, 0, 0, 0x0B), AccessWidth8, &Value, StdHeader);
      if ( Value == 3 ) {
        FchDataPtr->Gpp.GppFoundGfxDev |= (1 << PortId);
      }

      RegBusNumber = 0;
      WritePci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x18), AccessWidth32, &RegBusNumber, StdHeader);
    } else if ( PortCfg->PortPresent == FALSE || PortCfg->PortHotPlug == FALSE ) {
      //
      // Mask off non-applicable ports
      //
      AbValue &= ~(1 << (PortId + 4));
    }

    if ( PortCfg->PortHotPlug == TRUE ) {
      //
      // Hot Plug: PCIe Native Support
      // RCINDP_Reg 0x10[3] = 0x1
      // PCIe_Cfg 0x5A[8] = 0x1
      // PCIe_Cfg 0x6C[6] = 0x1
      // RCINDP_Reg 0x20[19] = 0x0
      //
      RwAlink ((FCH_RCINDXP_REG10 | (UINT32) (RCINDXP << 29) | (PortId << 24)), 0xFFFFFFFF, BIT3, StdHeader);
      RwPci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x5b), AccessWidth8, 0xff, BIT0, StdHeader);
      RwPci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x6c), AccessWidth8, 0xff, BIT6, StdHeader);
      RwAlink ((FCH_RCINDXP_REG20 | (UINT32) (RCINDXP << 29) | (PortId << 24)), ~BIT19, 0, StdHeader);
    }
  }

  if ( FchDataPtr->Gpp.GppUnhidePorts == FALSE ) {
    if ((AbValue & 0xF0) == 0) {
      AbValue = BIT8;                                                               /// if all ports are empty set GPP_RESET
    } else if ((AbValue & 0xE0) != 0 && (AbValue & 0x10) == 0) {
      AbValue |= BIT4;                                                              /// PortA should always be visible whenever other ports are exist
    }

    //
    // Update GPP_Portx_Enable (abcfg:0xC0[7:5])
    //
    WriteAlink (FCH_ABCFG_REGC0 | (UINT32) (ABCFG << 29), AbValue, StdHeader);
  }

  //
  // Common initialization for open GPP ports
  //
  for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) {
    ReadPci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x80), AccessWidth8, &Value, StdHeader);
    if (Value != 0xff) {
      //
      // Set pciCfg:PCIE_DEVICE_CNTL2[3:0] = 4'h6 (0x80[3:0])
      //
      Value &= 0xf0;
      Value |= 0x06;
      WritePci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x80), AccessWidth8, &Value, StdHeader);

      //
      // Set PCIEIND_P:PCIE_RX_CNTL[RX_RCB_CPL_TIMEOUT_MODE] (0x70:[19]) = 1
      //
      AbIndex = FCH_RCINDXP_REG70 | (UINT32) (RCINDXP << 29) | (PortId << 24);
      AbValue = ReadAlink (AbIndex, StdHeader) | BIT19;
      WriteAlink (AbIndex, AbValue, StdHeader);

      //
      // Set PCIEIND_P:PCIE_TX_CNTL[TX_FLUSH_TLP_DIS] (0x20:[19]) = 0
      //
      AbIndex = FCH_RCINDXP_REG20 | (UINT32) (RCINDXP << 29) | (PortId << 24);
      AbValue = ReadAlink (AbIndex, StdHeader) & ~BIT19;
      WriteAlink (AbIndex, AbValue, StdHeader);

    }
  }
}

