diff options
author | efdesign98 <efdesign98@gmail.com> | 2011-06-16 16:35:54 -0700 |
---|---|---|
committer | Marc Jones <marcj303@gmail.com> | 2011-06-21 22:37:51 +0200 |
commit | b0969d65e675f7c7a3004fc3f6fc154f22e73d44 (patch) | |
tree | 7e11f186e900ce6fc77603515b85c2a4154c6849 /src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/Tech/mrttsrc.c | |
parent | d1cb0eecd130cb4259ce9fedb32ebcd9ada0d4b7 (diff) |
Add AMD Family 12 cpu Agesa code
This is the addition of the AMD Family 12 cpu code.
Change-Id: I3febc81e192b4e86bbd3e8d6e1da62a28598fa8c
Signed-off-by: Frank Vibrans<frank.vibrans@amd.com>
Signed-off-by: efdesign98 <efdesign98@gmail.com>
Reviewed-on: http://review.coreboot.org/40
Tested-by: build bot (Jenkins)
Reviewed-by: Marc Jones <marcj303@gmail.com>
Diffstat (limited to 'src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/Tech/mrttsrc.c')
-rwxr-xr-x | src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/Tech/mrttsrc.c | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/Tech/mrttsrc.c b/src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/Tech/mrttsrc.c new file mode 100755 index 0000000000..6884b0591b --- /dev/null +++ b/src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/Tech/mrttsrc.c @@ -0,0 +1,436 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mrttsrc.c + * + * Technology Software based DQS receiver enable training Recovery + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Proc/Recovery/Mem) + * @e \$Revision: 48317 $ @e \$Date: 2011-03-08 01:38:14 +0800 (Tue, 08 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. +* *************************************************************************** +* +*/ + +/* + *---------------------------------------------------------------------------- + * MODULES USED + * + *---------------------------------------------------------------------------- + */ + + + +#include "AGESA.h" +#include "OptionMemory.h" +#include "amdlib.h" +#include "Ids.h" +#include "mm.h" +#include "mn.h" +#include "mru.h" +#include "mt.h" +#include "Filecode.h" +CODE_GROUP (G2_PEI) +RDATA_GROUP (G2_PEI) + +#define FILECODE PROC_RECOVERY_MEM_TECH_MRTTSRC_FILECODE +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ +#define MAX_BYTELANES 8 /* Max Bytelanes per channel */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + + +VOID +STATIC +MemRecTSetRcvrEnDly ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Receiver, + IN UINT16 RcvEnDly + ); + +VOID +STATIC +MemRecTLoadRcvrEnDly ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Receiver + ); + +BOOLEAN +STATIC +MemRecTSaveRcvrEnDly ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Receiver, + IN UINT16 RcvEnDly, + IN UINT8 CmpResult + ); + +UINT8 +STATIC +MemRecTCompare1ClPattern ( + IN UINT8 Buffer[], + IN UINT8 Pattern[], + IN OUT AMD_CONFIG_PARAMS *StdHeader + ); + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function executes receiver enable training for BSP + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +VOID +MemRecTTrainRcvrEnSw ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + _16BYTE_ALIGN UINT8 PatternBuffer[3 * 64]; + UINT8 TestBuffer[120]; + UINT8 *PatternBufPtr[2]; + UINT32 TestAddr[4]; + UINT8 TestResult; + UINT8 Receiver; + UINT8 i; + UINT8 j; + UINT16 RcvrEnDly; + + MEM_DATA_STRUCT *MemPtr; + DIE_STRUCT *MCTPtr; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + MemPtr = NBPtr->MemPtr; + MCTPtr = NBPtr->MCTPtr; + + AGESA_TESTPOINT (TpProcMemReceiverEnableTraining, &(MemPtr->StdHeader)); + + // Set environment settings before training + MemRecTBeginTraining (TechPtr); + + PatternBufPtr[0] = PatternBuffer; + MemRecUFillTrainPattern (TestPattern0, PatternBufPtr[0], 64, &(MemPtr->StdHeader)); + PatternBufPtr[1] = PatternBufPtr[0] + 128; + MemRecUFillTrainPattern (TestPattern1, PatternBufPtr[1], 64, &(MemPtr->StdHeader)); + + // Begin receiver enable training + MemRecTSetWrDatRdDqs (TechPtr, 0); + + // there are four receiver pairs, loosely associated with chipselects. + Receiver = NBPtr->DimmToBeUsed << 1; + TechPtr->DqsRcvEnSaved = 0; + + TestAddr[0] = NBPtr->GetSysAddrRec (NBPtr); + TestAddr[1] = TestAddr[0] + BIGPAGE_X8; + + IDS_HDT_CONSOLE (MEM_FLOW, "\tDct %d\n", NBPtr->Dct); + IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCS %d\n", Receiver); + IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tWrite to addresses: %04x0000\n", TestAddr[0]); + + // Sweep receiver enable delays + AGESA_TESTPOINT (TpProcMemRcvrStartSweep, &(MemPtr->StdHeader)); + for (RcvrEnDly = 0; RcvrEnDly < 0xFF; RcvrEnDly++) { + + TestResult = 0xFF; + for (i = 0; i < 2; i++) { + + // Set RcvrEn delay for all byte lanes + AGESA_TESTPOINT (TpProcMemRcvrSetDelay, &(MemPtr->StdHeader)); + MemRecTSetRcvrEnDly (TechPtr, Receiver, RcvrEnDly); + IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tDly %3x", RcvrEnDly); + + // Swap the test pointers such that even and odd steps alternate. + j = ((RcvrEnDly & 1) != 0) ? (i ^ 1) : i; + + // Write, read and compare the first beat of data + AGESA_TESTPOINT (TpProcMemRcvrWritePattern, &(MemPtr->StdHeader)); + MemRecUWrite1CL (TestAddr[j], PatternBufPtr[j]); + AGESA_TESTPOINT (TpProcMemRcvrReadPattern, &(MemPtr->StdHeader)); + MemRecURead1CL (TestBuffer, TestAddr[j]); + AGESA_TESTPOINT (TpProcMemRcvrTestPattern, &(MemPtr->StdHeader)); + TestResult &= MemRecTCompare1ClPattern (TestBuffer, PatternBufPtr[j], &(MemPtr->StdHeader)); + MemRecUProcIOClFlush (TestAddr[j], MemPtr); + } + + if (MemRecTSaveRcvrEnDly (TechPtr, Receiver, RcvrEnDly, TestResult)) { + // if all bytelanes pass + break; + } + } // End of delay sweep + + if (RcvrEnDly == 0xFF) { + // no passing window + // LibAmdEventLog (AGESA_ERROR, MEM_ERROR_RCVR_EN_NO_PASSING_WINDOW, 0, NBPtr->Dct, NBPtr->Channel, 0); //@attention commented out since it is not defined in recovery code + SetMemRecError (AGESA_ERROR, MCTPtr); + } + + // set final delays + MemRecTLoadRcvrEnDly (TechPtr, Receiver); + + // Clear training bit when done + NBPtr->SetBitField (NBPtr, BFDqsRcvEnTrain, 0); + + IDS_HDT_CONSOLE (MEM_FLOW, "\t\tMaxRcvrEnDly: %03x\n", RcvrEnDly + 0x20); + + // Set Max Latency for both channels + NBPtr->SetMaxLatency (NBPtr, RcvrEnDly + 0x20); + + // Restore environment settings after training + MemRecTEndTraining (TechPtr); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * If WrDatDly is 0, this function sets the DQS Positions in preparation + * for Receiver Enable Training. (Write Position is no delay, Read Position is 1.5 Memclock delay). + * Otherwise it will set WrDat and RdDqs to center of data eye. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] WrDatDly - either 0 or 0x0F + * + */ + +VOID +MemRecTSetWrDatRdDqs ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 WrDatDly + ) +{ + UINT8 ByteLane; + UINT8 Dimm; + UINT8 WrDqs; + UINT8 RdDqs; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + Dimm = NBPtr->DimmToBeUsed; + IDS_HDT_CONSOLE (MEM_FLOW, "\nWrDat RdDqs\n"); + for (ByteLane = 0; ByteLane < 8; ByteLane++) { + WrDqs = NBPtr->ChannelPtr->WrDqsDlys[(Dimm * MAX_BYTELANES) + ByteLane]; + NBPtr->SetTrainDly (NBPtr, AccessWrDatDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), WrDqs + WrDatDly); + RdDqs = (WrDatDly == 0) ? 0x2F : 0x012; + NBPtr->SetTrainDly (NBPtr, AccessRdDqsDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), RdDqs); + IDS_HDT_CONSOLE (MEM_FLOW, " %02x %02x\n\n", WrDqs + WrDatDly, RdDqs); + } +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function programs DqsRcvEnDly to additional index for DQS receiver enabled training + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Receiver - Current Chip select value + * @param[in] RcvEnDly - receiver enable delay to be saved + * + */ + +VOID +STATIC +MemRecTSetRcvrEnDly ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Receiver, + IN UINT16 RcvEnDly + ) +{ + UINT8 ByteLane; + + ASSERT (Receiver <= MAX_CS_PER_CHANNEL); + for (ByteLane = 0; ByteLane < 8; ByteLane++) { + TechPtr->NBPtr->SetTrainDly (TechPtr->NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (Receiver >> 1, ByteLane), RcvEnDly); + } +} + + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function compares test pattern with data in buffer and return a pass/fail bitmap + * for 8 Bytes + * + * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare + * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against + * @param[in,out] StdHeader - The Pointer of AGESA Header. + * + * @return PASS - Bit map of results of comparison + */ + +UINT8 +STATIC +MemRecTCompare1ClPattern ( + IN UINT8 Buffer[], + IN UINT8 Pattern[], + IN OUT AMD_CONFIG_PARAMS *StdHeader + ) +{ + UINT8 i; + UINT8 Pass; + + Pass = 0xFF; + IDS_HDT_CONSOLE (MEM_FLOW, " -"); + for (i = 0; i < 8; i++) { + if (Buffer[i] != Pattern[i]) { + // if bytelane n fails + Pass &= ~((UINT16) 1 << (i % 8)); // clear bit n + } + IDS_HDT_CONSOLE (MEM_FLOW, " %c", (Buffer[i] == Pattern[i]) ? 'P' : '.'); + } + + IDS_HDT_CONSOLE_DEBUG_CODE ( + IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t -"); + for (i = 0; i < 8; i++) { + IDS_HDT_CONSOLE (MEM_FLOW, " %02x", Buffer[i]); + } + IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t -"); + for (i = 0; i < 8; i++) { + IDS_HDT_CONSOLE (MEM_FLOW, " %02x", Pattern[i]); + } + IDS_HDT_CONSOLE (MEM_FLOW, "\n\n"); + ); + + return Pass; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function saves passing DqsRcvEnDly values to the stack + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Receiver - Current Chip select value + * @param[in] RcvEnDly - receiver enable delay to be saved + * @param[in] CmpResult - compare result for Rank 0 + * + * @return TRUE - All bytelanes pass + * @return FALSE - Some bytelanes fail + */ + +BOOLEAN +STATIC +MemRecTSaveRcvrEnDly ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Receiver, + IN UINT16 RcvEnDly, + IN UINT8 CmpResult + ) +{ + UINT8 i; + UINT8 Passed; + UINT8 Saved; + UINT8 Mask; + UINT8 Dimm; + + ASSERT (Receiver <= MAX_CS_PER_CHANNEL); + + Passed = CmpResult; + Saved = (UINT8) (TechPtr->DqsRcvEnSaved & Passed); //@todo - false passes filter (subject to be replaced with a better solution) + Dimm = Receiver >> 1; + Mask = 1; + for (i = 0; i < 8; i++) { + if ((Passed & Mask) != 0) { + if ((Saved & Mask) == 0) { + TechPtr->NBPtr->ChannelPtr->RcvEnDlys[Dimm * MAX_BYTELANES + i] = (UINT8) (RcvEnDly + 0x20); + IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tBL %d = %02x", i, RcvEnDly + 0x20); + } + Saved |= Mask; + } + Mask <<= 1; + } + TechPtr->DqsRcvEnSaved = Saved; + + if (Saved == 0xFF) { + return TRUE; + } else { + return FALSE; + } +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function loads the DqsRcvEnDly from saved data and program to additional index + * for DQS receiver enabled training + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Receiver - Current Chip select value + * + */ + +VOID +STATIC +MemRecTLoadRcvrEnDly ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Receiver + ) +{ + UINT8 i; + UINT8 Dimm; + UINT16 Saved; + CH_DEF_STRUCT *ChannelPtr; + + ASSERT (Receiver <= MAX_CS_PER_CHANNEL); + ChannelPtr = TechPtr->NBPtr->ChannelPtr; + + Dimm = Receiver >> 1; + Saved = TechPtr->DqsRcvEnSaved; + for (i = 0; i < 8; i++) { + if ((Saved & 1) != 0) { + TechPtr->NBPtr->SetTrainDly (TechPtr->NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (Receiver >> 1, i), + ChannelPtr->RcvEnDlys[Dimm * MAX_BYTELANES + i]); + } + Saved >>= 1; + } +} |