diff options
Diffstat (limited to 'src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3')
14 files changed, 5835 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mt3.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mt3.c new file mode 100644 index 0000000000..eb06c8425c --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mt3.c @@ -0,0 +1,262 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mt3.c + * + * Common Technology functions for DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** +* +* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. +* +* AMD is granting you permission to use this software (the Materials) +* pursuant to the terms and conditions of your Software License Agreement +* with AMD. This header does *NOT* give you permission to use the Materials +* or any rights under AMD's intellectual property. Your use of any portion +* of these Materials shall constitute your acceptance of those terms and +* conditions. If you do not agree to the terms and conditions of the Software +* License Agreement, please do not use any portion of these Materials. +* +* CONFIDENTIALITY: The Materials and all other information, identified as +* confidential and provided to you by AMD shall be kept confidential in +* accordance with the terms and conditions of the Software License Agreement. +* +* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION +* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED +* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, +* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. +* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER +* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS +* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, +* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER +* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE +* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, +* THE ABOVE LIMITATION MAY NOT APPLY TO YOU. +* +* AMD does not assume any responsibility for any errors which may appear in +* the Materials or any other related information provided to you by AMD, or +* result from use of the Materials or any related information. +* +* You agree that you will not reverse engineer or decompile the Materials. +* +* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any +* further information, software, technical information, know-how, or show-how +* available to you. Additionally, AMD retains the right to modify the +* Materials at any time, without notice, and is not obligated to provide such +* modified Materials to you. +* +* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with +* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is +* subject to the restrictions as set forth in FAR 52.227-14 and +* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the +* Government constitutes acknowledgement of AMD's proprietary rights in them. +* +* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any +* direct product thereof will be exported directly or indirectly, into any +* country prohibited by the United States Export Administration Act and the +* regulations thereunder, without the required authorization from the U.S. +* government nor will be used for any purpose prohibited by the same. +* *************************************************************************** +* +*/ + +/* + *---------------------------------------------------------------------------- + * MODULES USED + * + *---------------------------------------------------------------------------- + */ + + + +#include "AGESA.h" +#include "Ids.h" +#include "mm.h" +#include "mn.h" +#include "mu.h" +#include "mt.h" +#include "mt3.h" +#include "mtspd3.h" +#include "mtot3.h" +#include "OptionMemory.h" +#include "PlatformMemoryConfiguration.h" +#include "Filecode.h" +CODE_GROUP (G1_PEICC) +RDATA_GROUP (G1_PEICC) + +/* features */ +#define FILECODE PROC_MEM_TECH_DDR3_MT3_FILECODE +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ +/* -----------------------------------------------------------------------------*/ +/** + * + * This function Constructs the technology block + * + * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +BOOLEAN +MemConstructTechBlock3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT MEM_NB_BLOCK *NBPtr + ) +{ + TECHNOLOGY_TYPE *TechTypePtr; + UINT8 Dct; + UINT8 Channel; + UINT8 i; + DIE_STRUCT *MCTPtr; + DCT_STRUCT *DCTPtr; + CH_DEF_STRUCT *ChannelPtr; + UINT8 DimmSlots; + + + TechTypePtr = (TECHNOLOGY_TYPE *) FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MEM_TECH, NBPtr->MCTPtr->SocketId, 0, 0, NULL, NULL); + if (TechTypePtr != NULL) { + // Ensure the platform override value is valid + ASSERT ((*TechTypePtr == DDR3_TECHNOLOGY) || (*TechTypePtr == DDR2_TECHNOLOGY)); + if (*TechTypePtr != DDR3_TECHNOLOGY) { + return FALSE; + } + } + + TechPtr->NBPtr = NBPtr; + TechPtr->RefPtr = NBPtr->RefPtr; + MCTPtr = NBPtr->MCTPtr; + + TechPtr->SendAllMRCmds = MemTSendAllMRCmds3; + TechPtr->FreqChgCtrlWrd = FreqChgCtrlWrd3; + TechPtr->SetDramMode = MemTSetDramMode3; + TechPtr->DimmPresence = MemTDIMMPresence3; + TechPtr->SpdCalcWidth = MemTSPDCalcWidth3; + TechPtr->SpdGetTargetSpeed = MemTSPDGetTargetSpeed3; + TechPtr->AutoCycTiming = MemTAutoCycTiming3; + TechPtr->SpdSetBanks = MemTSPDSetBanks3; + TechPtr->SetDqsEccTmgs = MemTSetDQSEccTmgs; + TechPtr->GetCSIntLvAddr = MemTGetCSIntLvAddr3; + TechPtr->AdjustTwrwr = MemTAdjustTwrwr3; + TechPtr->AdjustTwrrd = MemTAdjustTwrrd3; + TechPtr->GetDimmSpdBuffer = MemTGetDimmSpdBuffer3; + TechPtr->GetLD = MemTGetLD3; + TechPtr->MaxFilterDly = 0; + + // + // Map the Logical Dimms on this channel to the SPD that should be used for that logical DIMM. + // The pointers to the DIMM SPD information is as follows (2 Dimm/Ch and 3 Dimm/Ch examples). + // + // DIMM Spd Buffer Current Channel DimmSpdPtr[MAX_DIMMS_PER_CHANNEL] array + // (Number of dimms varies by platform) (Array size is determined in AGESA.H) Dimm operations loop + // on this array only) + // 2 DIMMS PER CHANNEL + // + // Socket N Channel N Dimm 0 SR/DR DIMM <--------------DimmSpdPtr[0] + // Dimm 1 SR/DR DIMM <--------------DimmSpdPtr[1] + // DimmSpdPtr[2]------->NULL + // DimmSpdPtr[3]------->NULL + // + // Socket N Channel N Dimm 0 SR/DR DIMM <--------------DimmSpdPtr[0] + // Dimm 1 QR DIMM <---------+----DimmSpdPtr[1] + // | DimmSpdPtr[2]------->NULL + // +----DimmSpdPtr[3] + // + // Socket N Channel N Dimm 0 QR DIMM <-----+--------DimmSpdPtr[0] + // Dimm 1 QR DIMM <-----|---+----DimmSpdPtr[1] + // +-- | ---DimmSpdPtr[2] + // +----DimmSpdPtr[3] + // + // 3 DIMMS PER CHANNEL + // + // Socket N Channel N Dimm 0 SR/DR DIMM <--------------DimmSpdPtr[0] + // Dimm 1 SR/DR DIMM <--------------DimmSpdPtr[1] + // Dimm 3 SR/DR DIMM <--------------DimmSpdPtr[2] + // DimmSpdPtr[3]------->NULL + // + // Socket N Channel N Dimm 0 SR/DR DIMM <--------------DimmSpdPtr[0] + // Dimm 1 QR DIMM <---------+----DimmSpdPtr[1] + // Dimm 3 SR/DR DIMM <-------- | ---DimmSpdPtr[2] + // +----DimmSpdPtr[3] + // + // + // FOR LRDIMMS + // + // This code will assign SPD pointers on the basis of Physical ranks, even though + // an LRDIMM may only use one or two logical ranks, that determination will have to + // be made from downstream code. An LRDIMM with greater than 2 Physical ranks will have + // its DimmSpdPtr[] mapped as if it were a QR in the above diagrams. + + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + NBPtr->SwitchDCT (NBPtr, Dct); + DCTPtr = NBPtr->DCTPtr; + for (Channel = 0; Channel < NBPtr->ChannelCount; Channel++) { + NBPtr->SwitchChannel (NBPtr, Channel); + ChannelPtr = NBPtr->ChannelPtr; + ChannelPtr->TechType = DDR3_TECHNOLOGY; + ChannelPtr->MCTPtr = MCTPtr; + ChannelPtr->DCTPtr = DCTPtr; + + DimmSlots = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, + MCTPtr->SocketId, + NBPtr->GetSocketRelativeChannel (NBPtr, Dct, Channel) + ); + // + // Initialize the SPD pointers for each Dimm + // + for (i = 0 ; i < (sizeof (ChannelPtr->DimmSpdPtr) / sizeof (ChannelPtr->DimmSpdPtr[0])) ; i++) { + ChannelPtr->DimmSpdPtr[i] = NULL; + } + for (i = 0 ; i < DimmSlots; i++) { + ChannelPtr->DimmSpdPtr[i] = &(ChannelPtr->SpdPtr[i]); + if ( (i + 2) < (sizeof (ChannelPtr->DimmSpdPtr) / sizeof (ChannelPtr->DimmSpdPtr[0]))) { + if (ChannelPtr->DimmSpdPtr[i]->DimmPresent) { + if ((((ChannelPtr->DimmSpdPtr[i]->Data[SPD_RANKS] >> 3) & 0x07) + 1) > 2) { + ChannelPtr->DimmSpdPtr[i + 2] = &(ChannelPtr->SpdPtr[i]); + } + } + } + } + } + } + // Initialize Common technology functions + MemTCommonTechInit (TechPtr); + + return TRUE; +} + +/*---------------------------------------------------------------------------- + * LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mt3.h b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mt3.h new file mode 100644 index 0000000000..9cf712b902 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mt3.h @@ -0,0 +1,161 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mt3.h + * + * Common Technology + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** + * + * Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. + * + * AMD is granting you permission to use this software (the Materials) + * pursuant to the terms and conditions of your Software License Agreement + * with AMD. This header does *NOT* give you permission to use the Materials + * or any rights under AMD's intellectual property. Your use of any portion + * of these Materials shall constitute your acceptance of those terms and + * conditions. If you do not agree to the terms and conditions of the Software + * License Agreement, please do not use any portion of these Materials. + * + * CONFIDENTIALITY: The Materials and all other information, identified as + * confidential and provided to you by AMD shall be kept confidential in + * accordance with the terms and conditions of the Software License Agreement. + * + * LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION + * PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, + * OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. + * IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER + * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS + * INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, + * GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER + * RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE + * EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, + * THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + * + * AMD does not assume any responsibility for any errors which may appear in + * the Materials or any other related information provided to you by AMD, or + * result from use of the Materials or any related information. + * + * You agree that you will not reverse engineer or decompile the Materials. + * + * NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + * further information, software, technical information, know-how, or show-how + * available to you. Additionally, AMD retains the right to modify the + * Materials at any time, without notice, and is not obligated to provide such + * modified Materials to you. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with + * "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is + * subject to the restrictions as set forth in FAR 52.227-14 and + * DFAR252.227-7013, et seq., or its successor. Use of the Materials by the + * Government constitutes acknowledgement of AMD's proprietary rights in them. + * + * EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any + * direct product thereof will be exported directly or indirectly, into any + * country prohibited by the United States Export Administration Act and the + * regulations thereunder, without the required authorization from the U.S. + * government nor will be used for any purpose prohibited by the same. + * *************************************************************************** + * + */ + +#ifndef _MT3_H_ +#define _MT3_H_ + +/*---------------------------------------------------------------------------- + * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS) + * + *---------------------------------------------------------------------------- + */ + +/*----------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *----------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS, STRUCTURES, ENUMS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * FUNCTIONS PROTOTYPE + * + *---------------------------------------------------------------------------- + */ + +BOOLEAN +MemConstructTechBlock3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT MEM_NB_BLOCK *NBPtr + ); +BOOLEAN +MemTSetDramMode3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +BOOLEAN +MemTDIMMPresence3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +BOOLEAN +MemTSPDCalcWidth3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +BOOLEAN +MemTSPDGetTargetSpeed3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +BOOLEAN +MemTAutoCycTiming3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +BOOLEAN +MemTSPDSetBanks3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +VOID +MemTGetCSIntLvAddr3 ( + IN UINT8 BankEnc, + OUT UINT8 *LowBit, + OUT UINT8 *HiBit + ); + +VOID +MemTSendAllMRCmds3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 ChipSel + ); + +VOID +FreqChgCtrlWrd3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + + +BOOLEAN +MemTGetDimmSpdBuffer3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT UINT8 **SpdBuffer, + IN UINT8 Dimm + ); +#endif /* _MT3_H_ */ + + diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtlrdimm3.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtlrdimm3.c new file mode 100644 index 0000000000..6ecef377f3 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtlrdimm3.c @@ -0,0 +1,1474 @@ +/** + * @file + * + * mtlrdimm3.c + * + * Technology initialization and control workd support for DDR3 LRDIMMS + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** +* +* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. +* +* AMD is granting you permission to use this software (the Materials) +* pursuant to the terms and conditions of your Software License Agreement +* with AMD. This header does *NOT* give you permission to use the Materials +* or any rights under AMD's intellectual property. Your use of any portion +* of these Materials shall constitute your acceptance of those terms and +* conditions. If you do not agree to the terms and conditions of the Software +* License Agreement, please do not use any portion of these Materials. +* +* CONFIDENTIALITY: The Materials and all other information, identified as +* confidential and provided to you by AMD shall be kept confidential in +* accordance with the terms and conditions of the Software License Agreement. +* +* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION +* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED +* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, +* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. +* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER +* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS +* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, +* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER +* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE +* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, +* THE ABOVE LIMITATION MAY NOT APPLY TO YOU. +* +* AMD does not assume any responsibility for any errors which may appear in +* the Materials or any other related information provided to you by AMD, or +* result from use of the Materials or any related information. +* +* You agree that you will not reverse engineer or decompile the Materials. +* +* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any +* further information, software, technical information, know-how, or show-how +* available to you. Additionally, AMD retains the right to modify the +* Materials at any time, without notice, and is not obligated to provide such +* modified Materials to you. +* +* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with +* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is +* subject to the restrictions as set forth in FAR 52.227-14 and +* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the +* Government constitutes acknowledgement of AMD's proprietary rights in them. +* +* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any +* direct product thereof will be exported directly or indirectly, into any +* country prohibited by the United States Export Administration Act and the +* regulations thereunder, without the required authorization from the U.S. +* government nor will be used for any purpose prohibited by the same. +* *************************************************************************** +* +*/ + +/* + *---------------------------------------------------------------------------- + * MODULES USED + * + *---------------------------------------------------------------------------- + */ + + + +#include "AGESA.h" +#include "amdlib.h" +#include "Ids.h" +#include "mm.h" +#include "mn.h" +#include "mu.h" +#include "mt.h" +#include "mt3.h" +#include "mtspd3.h" +#include "mtrci3.h" +#include "mtsdi3.h" +#include "mtlrdimm3.h" +#include "merrhdl.h" +#include "GeneralServices.h" +#include "Filecode.h" +CODE_GROUP (G1_PEICC) +RDATA_GROUP (G1_PEICC) +#define FILECODE PROC_MEM_TECH_DDR3_MTLRDIMM3_FILECODE +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +VOID +STATIC +MemTSendMBCtlWord3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Fn, + IN UINT8 Rcw, + IN UINT8 Value + ); + +VOID +STATIC +MemTSendExtMBCtlWord3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT16 Addr, + IN UINT16 Data, + IN UINT8 Len + ); + +UINT8 +STATIC +MemTGetSpecialMBCtlWord3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Dimm, + IN UINT8 Fn, + IN UINT8 Rc + ); + +BOOLEAN +STATIC +MemTLrDimmControlRegInit3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *OptParam + ); + +BOOLEAN +STATIC +MemTLrDimmFreqChgCtrlWrd3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *OptParam + ); + +BOOLEAN +STATIC +MemTWLPrepareLrdimm3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *Wl + ); + +BOOLEAN +STATIC +MemTSendAllMRCmdsLR3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *CsPtr + ); + +VOID +STATIC +MemTEMRS1Lr3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 ChipSel, + IN UINT8 PhyRank + ); + +VOID +STATIC +MemTEMRS2Lr3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 ChipSel + ); + + +BOOLEAN +STATIC +MemTLrdimmRankMultiplication ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *DimmID + ); + +BOOLEAN +STATIC +MemTLrdimmBuf2DramTrain3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *OptParam + ); + +BOOLEAN +STATIC +MemTLrdimmSyncTrainedDlys ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *OptParam + ); + +BOOLEAN +STATIC +MemTLrdimmPresence ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *DimmID + ); + +UINT32 +STATIC +MemTLrDimmGetBufferID ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Dimm + ); + +VOID +STATIC +MemTLrdimmInitHook ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN LRDIMM_HOOK_ENTRYPOINT Entrypoint, + IN UINT8 Dimm, + IN OUT VOID *OptParam + ); + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function initializes LRDIMM functions. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +BOOLEAN +MemTLrdimmConstructor3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + TechPtr->TechnologySpecificHook[LrdimmSendAllMRCmds] = MemTSendAllMRCmdsLR3; + TechPtr->TechnologySpecificHook[LrdimmControlRegInit] = MemTLrDimmControlRegInit3; + TechPtr->TechnologySpecificHook[LrdimmFreqChgCtrlWrd] = MemTLrDimmFreqChgCtrlWrd3; + TechPtr->TechnologySpecificHook[WlTrainingPrepareLrdimm] = MemTWLPrepareLrdimm3; + TechPtr->TechnologySpecificHook[LrdimmRankMultiplication] = MemTLrdimmRankMultiplication; + TechPtr->TechnologySpecificHook[LrdimmBuf2DramTrain] = MemTLrdimmBuf2DramTrain3; + TechPtr->TechnologySpecificHook[LrdimmSyncTrainedDlys] = MemTLrdimmSyncTrainedDlys; + TechPtr->TechnologySpecificHook[LrdimmPresence] = MemTLrdimmPresence; + return TRUE; +} + +/*---------------------------------------------------------------------------- + * LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function sends a Control word command to an LRDIMM Memory Buffer + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Fn - control word function + * @param[in] Rcw - control word number + * @param[in] Value - value to send + * + */ + +VOID +STATIC +MemTSendMBCtlWord3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Fn, + IN UINT8 Rcw, + IN UINT8 Value + ) +{ + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + ASSERT (Rcw != RCW_FN_SELECT); // RC7 can only be used for function select + IDS_HDT_CONSOLE (MEM_FLOW, "\t\tF%dRC%d = %x\n", Fn, Rcw, Value); + // + // Select the MB Function by sending the Fn number + // to the Function Select Control Word + // + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, RCW_FN_SELECT, Fn); + // + // Send the value to the control word + // + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, Rcw, Value); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function sends a an Extended Control word command to an LRDIMM Memory Buffer + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Addr - Extended Control Word Address + * Addr[15:12] Extended Control Workd Function Select + * Addr[11:0] Extended Control Word CSR Address + * @param[in] Data - value to send + * @param[in] Len - Length of data. 1 or 2 bytes + * + */ + +VOID +STATIC +MemTSendExtMBCtlWord3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT16 Addr, + IN UINT16 Data, + IN UINT8 Len + ) +{ + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + ASSERT ((Len == 1) || (Len == 2)); + if (Len == 2 ) { + IDS_HDT_CONSOLE (MEM_FLOW, "\t\tExtRC_x%04x = %04x\n", Addr, Data); + } else { + IDS_HDT_CONSOLE (MEM_FLOW, "\t\tExtRC_x%04x = %02x\n", Addr, (UINT8) (Data & 0xFF) ); + } + // + // Select the MB Function by sending the Fn number + // to the Function Select Control Word + // + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, RCW_FN_SELECT, 13); + // + // Send address via control words + // + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, 9, (UINT8) (Addr >> 12)); + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, 10, (UINT8) (Addr & 0xF)); + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, 11, (UINT8) ((Addr >> 4) & 0x0F)); + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, 12, (UINT8) ((Addr >> 8) & 0x0F)); + // + // Send the Lower Byte of Data + // + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, 14, (UINT8) (Data & 0xF)); + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, 15, (UINT8) ((Data >> 4) & 0x0F)); + // + // Send the Upper Byte of Data + // + if (Len == 2) { + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, 10, (UINT8) ((Addr & 0xF) + 1)); + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, 14, (UINT8) ((Data >> 8) & 0xF)); + MemUWait10ns (800, NBPtr->MemPtr); + MemTSendCtlWord3 (TechPtr, 15, (UINT8) ((Data >> 12) & 0xF)); + } +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function gets the value of special RCW + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Dimm - Physical LR DIMM number + * @param[in] Fn - control word function + * @param[in] Rc - control word number + * + * @return Special RCW value + * + */ + +UINT8 +STATIC +MemTGetSpecialMBCtlWord3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Dimm, + IN UINT8 Fn, + IN UINT8 Rc + ) +{ + CONST UINT8 F0RC13PhyRankTab[] = {3, 2, 0, 1, 0}; + UINT8 PhyRanks; + UINT8 LogRanks; + UINT8 DramCap; + UINT8 Value8; + UINT8 *SpdBufferPtr; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, Dimm); + + Value8 = 0; + switch (Fn) { + case 0: + switch (Rc) { + case 8: + // F0RC8 + Value8 = NBPtr->PsPtr->F0RC8; + break; + case 10: + // F0RC10 + // 2:0 OperatingSpeed: operating speed. BIOS: Table 88. + if (NBPtr->DCTPtr->Timings.Speed == DDR667_FREQUENCY) { + Value8 = 0; + } else { + Value8 = (UINT8) (NBPtr->DCTPtr->Timings.Speed / 133) - 3; + } + break; + case 11: + // F0RC11 + // 3:2 ParityCalculation: partiy calculation. BIOS: Table. + // 1:0 OperatingVoltage: operating voltage. BIOS: IF(VDDIO == 1.5) THEN 00b ELSEIF (VDDIO == + // 1.35) THEN 01b ELSE 10b ENDIF. + DramCap = SpdBufferPtr[SPD_DENSITY] & 0xF; + if (NBPtr->PsPtr->LrdimmRowAddrBits[Dimm] > 16) { + Value8 = 8; + } else { + Value8 = 4; + } + Value8 |= CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage); + break; + case 13: + // F0RC13 + // 3:2 NumLogicalRanks: partiy calculation. BIOS: Table 90. + // 1:0 NumPhysicalRanks: operating voltage. BIOS: Table 89. + LogRanks = NBPtr->ChannelPtr->LrDimmLogicalRanks[Dimm] >> 1; + PhyRanks = F0RC13PhyRankTab[(SpdBufferPtr[SPD_RANKS] >> 3) & 7]; + Value8 = (LogRanks << 2) | PhyRanks; + break; + case 14: + // F0RC14 + // 3 DramBusWidth: DRAM bus width. BIOS: IF (DeviceWidth==0) THEN 0 ELSE 1 ENDIF. + // 2 MRSCommandControl: MRS command control. BIOS: IF (F0RC15[RankMultiplicationControl] + // > 0) THEN 1 ELSE 0 ENDIF. + // 1 RefreshPrechargeCommandControl: refresh and precharge command control. BIOS: IF + // (F0RC15[RankMultiplicationControl] > 0) THEN D18F2xA8_dct[1:0][LrDimmEnhRefEn] ELSE 0 ENDIF. + // 0 AddressMirror: address mirror. BIOS: RankMap. See D18F2x[5C:40]_dct[1:0][OnDimmMirror]. + if ((SpdBufferPtr[SPD_DEV_WIDTH] & 7) != 0) { + Value8 |= 8; + } + if (NBPtr->ChannelPtr->LrDimmRankMult[Dimm] > 1) { + Value8 |= 4; + if (NBPtr->GetBitField (NBPtr, BFLrDimmEnhRefEn) == 1) { + Value8 |= 2; + } + } + if ((SpdBufferPtr[SPD_ADDRMAP] & 1) != 0) { + Value8 |= 1; + } + break; + case 15: + // F0RC15 + // 3:0 RankMultiplicationControl: rank multiplication control. BIOS: Table 91. + DramCap = SpdBufferPtr[SPD_DENSITY] & 0xF; + ASSERT ((DramCap >= 2) && (DramCap <= 4)); // BKDG only lists 1Gb, 2Gb, and 4Gb + switch (NBPtr->ChannelPtr->LrDimmRankMult[Dimm]) { + case 1: + Value8 = 0; + break; + case 2: + Value8 = DramCap - 1; + break; + case 4: + Value8 = DramCap + 3; + break; + default: + ASSERT (FALSE); + } + break; + default: + ASSERT (FALSE); + } + break; + case 1: + switch (Rc) { + case 0: + // F1RC0 + Value8 = NBPtr->PsPtr->F1RC0; + Value8 |= (UINT8) NBPtr->GetBitField (NBPtr, BFCSTimingMux67) << 3; + break; + case 1: + // F1RC1 + Value8 = NBPtr->PsPtr->F1RC1; + break; + case 2: + // F1RC2 + Value8 = NBPtr->PsPtr->F1RC2; + break; + case 9: + // F1RC9 + if (NBPtr->GetBitField (NBPtr, BFLrDimmEnhRefEn) == 0) { + Value8 = 1; + } + break; + default: + ASSERT (FALSE); + } + break; + case 3: + switch (Rc) { + case 0: + // F3RC0 + // 3 TDQSControl: TDQS control. BIOS: 0. + // 2:0 RttNom: RttNom. BIOS: Table 57, Table 60 + Value8 = NBPtr->PsPtr->RttNom[Dimm << 1]; + break; + case 1: + // F3RC1 + // 3 Vref: Vref. BIOS: 0. + // 2:0 RttWr: RttWr. BIOS: Table 57, Table 60. + Value8 = NBPtr->PsPtr->RttWr[Dimm << 1]; + break; + case 6: + // F3RC6 + // IF (D18F2x90_dct[1:0][X4Dimm] == 0) THEN 1 ELSE 0 + if (NBPtr->GetBitField (NBPtr, BFX4Dimm) == 0) { + Value8 = 8; + } + break; + default: + ASSERT (FALSE); + } + break; + default: + ASSERT (FALSE); + } + + return Value8; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function sends LRDIMM Control Words to all LRDIMMS + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in,out] OptParam - Optional parameter + * + * @return TRUE + */ + +BOOLEAN +STATIC +MemTLrDimmControlRegInit3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *OptParam + ) +{ + CONST UINT8 RCWInitTable[] = { + // RCW, Mask, SPD + F0, RC0, 0x00, SPD_NONE, + F0, RC1, 0x00, SPD_NONE, + F0, RC2, 0x03, SPD_67, + F0, RC10, 0x00, SPECIAL_CASE, + F0, RC11, 0x00, SPECIAL_CASE, + + F1, RC8, 0x0F, SPD_69, + F1, RC11, 0xF0, SPD_69, + F1, RC12, 0x0F, SPD_70, + F1, RC13, 0xF0, SPD_70, + F1, RC14, 0x0F, SPD_71, + F1, RC15, 0xF0, SPD_71, + + WAIT_6US, 0, 0, 0, + + F0, RC3, 0xF0, SPD_67, + F0, RC4, 0x0F, SPD_68, + F0, RC5, 0xF0, SPD_68, + + F0, RC6, 0x00, SPD_NONE, + F0, RC8, 0x00, SPECIAL_CASE, + F0, RC9, 0x0C, SPD_NONE, + F0, RC13, 0x00, SPECIAL_CASE, + F0, RC14, 0x00, SPECIAL_CASE, + F0, RC15, 0x00, SPECIAL_CASE, + + F1, RC0, 0x00, SPECIAL_CASE, + F1, RC1, 0x00, SPECIAL_CASE, + F1, RC2, 0x00, SPECIAL_CASE, + F1, RC3, 0x00, SPD_NONE, + F1, RC9, 0x00, SPECIAL_CASE, + F1, RC10, 0x00, SPD_NONE, + + F2, RC0, 0x00, SPD_NONE, + F2, RC1, 0x00, SPD_NONE, + F2, RC2, 0x0F, SPD_NONE, + F2, RC3, 0x00, SPD_NONE, + + F3, RC0, 0x00, SPECIAL_CASE, + F3, RC1, 0x00, SPECIAL_CASE, + F3, RC2, 0x01, SPD_NONE, + F3, RC6, 0x00, SPECIAL_CASE + // + // F3 RC[8,9] are programmed in MDQ RC loop + // + // F[10:3] RC[11,10] are programmed in QxODT RC loop + // + // F[15,14] RC[15:0] are programmed in personality RC loop + }; + + UINT8 Dimm; + UINT16 i; + UINT16 DimmMask; + UINT8 Fn; + UINT8 Rc; + UINT8 Mask; + UINT8 Spd; + UINT8 *SpdBufferPtr; + UINT8 FreqDiffOffset; + UINT8 Value8; + UINT32 Temp32; + MEM_DATA_STRUCT *MemPtr; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + MemPtr = NBPtr->MemPtr; + + if (NBPtr->MCTPtr->Status[SbLrdimms]) { + for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) { + DimmMask = (UINT16)1 << Dimm; + if ((NBPtr->ChannelPtr->LrDimmPresent & DimmMask) != 0) { + // + // Select the Target Chipselects + // + NBPtr->SetBitField (NBPtr, BFMrsChipSel, (Dimm << 1)); + NBPtr->SetBitField (NBPtr, BFCtrlWordCS, 3 << (Dimm << 1)); + + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, Dimm); + + IDS_HDT_CONSOLE (MEM_FLOW, "\t\tSending LRDIMM Control Words: Dimm %02x\n", Dimm); + + for (i = 0; i < sizeof (RCWInitTable) ; i += 4) { + Fn = RCWInitTable[i]; + Rc = RCWInitTable[i + 1]; + Mask = RCWInitTable[i + 2]; + Spd = RCWInitTable[i + 3]; + + if (Fn == WAIT_6US) { + MemUWait10ns (600, MemPtr); // wait 6us for TSTAB + } else { + if (Spd == SPD_NONE) { + Value8 = Mask; + } else if (Spd == SPECIAL_CASE) { + Value8 = MemTGetSpecialMBCtlWord3 (TechPtr, Dimm, Fn, Rc); + } else { + Value8 = (Mask > 0x0F) ? ((SpdBufferPtr[Spd] & Mask) >> 4) : (SpdBufferPtr[Spd] & Mask); + } + MemTSendMBCtlWord3 (TechPtr, Fn, Rc, Value8); + } + } + + FreqDiffOffset = (UINT8) (SPD_FREQ_DIFF_OFFSET * (((NBPtr->DCTPtr->Timings.Speed / 133) - 3) / 2)); + // + // Send RCW to program MDQ termination and drive strength + // + for (Rc = 8; Rc <= 9; Rc++) { + Value8 = SpdBufferPtr[SPD_MDQ_800_1066 + FreqDiffOffset]; + Value8 = (Rc == 9) ? (Value8 >> 4) : Value8; + MemTSendMBCtlWord3 (TechPtr, 3, Rc, Value8 & 0x07); + } + // + // Send RCW to program QxODT + // + for (Fn = 3; Fn <= 10; Fn ++) { + for (Rc = 10; Rc <= 11; Rc++) { + Value8 = SpdBufferPtr[SPD_QXODT_800_1066 + FreqDiffOffset + ((Fn - 3) >> 1)]; + Value8 = (Rc == 11) ? (Value8 >> 4) : (Value8 & 0x0F); + Value8 = ((Fn & 1) == 0) ? (Value8 >> 2) : (Value8 & 0x03); + MemTSendMBCtlWord3 (TechPtr, Fn, Rc, Value8); + } + } + + MemTLrdimmInitHook (TechPtr, AFTER_TSTAB, Dimm, 0); + // + // Send Personality bytes from SPD + // + for (i = 0; i < 15; i ++) { + Value8 = SpdBufferPtr[SPD_PERSONALITY_BYTE + i]; + Fn = (UINT8) (14 + (i >> 3)); + Rc = (UINT8) ((i << 1) & 0x0F); + if ( i == 0) { + Value8 |= 0x01; + } else if ( i > 10) { + Rc += 2; + } + MemTSendMBCtlWord3 (TechPtr, Fn, Rc, (Value8 & 0x0F)); + if (i == 3) { + Fn++; + } else { + Rc++; + } + MemTSendMBCtlWord3 (TechPtr, Fn, Rc, (Value8 >> 4)); + } + // + // Send Extended Control Words to Buffer + // + // ExtRC_xAC + // + MemTSendExtMBCtlWord3 (TechPtr, 0x00AC, 0, 1); + // + // ExtRC_xB8-BF + // + Value8 = SpdBufferPtr[SPD_MR1_MR2_800_1066 + FreqDiffOffset]; + for (i = 0x00B8; i < 0x00C0; i++) { + MemTSendExtMBCtlWord3 (TechPtr, i, Value8, 1); + if (i == 0xB9) { + // + // Phys ranks > 1, Rtt_nom = 0 + // + Value8 &= 0xE3; + } + } + // ExtRC_xC8 + Value8 = (UINT8) (NBPtr->MemNGetMR0CL (NBPtr) & 0x000000FF); + Value8 = ((Value8 & 0xE0) | ((Value8 & 0x04) << 1)); + Value8 |= 1 << 2; // RBT + Value8 |= NBPtr->GetBitField (NBPtr, BFBurstCtrl); // BL + MemTSendExtMBCtlWord3 (TechPtr, 0x00C8 , Value8, 1); + // ExtRC_xC9 + // PPD + Value8 = (UINT8) (NBPtr->GetBitField (NBPtr, BFPchgPDModeSel) & 0x000000FF); + NBPtr->FamilySpecificHook[MR0_PPD] (NBPtr, &Value8); + IDS_OPTION_HOOK (IDS_MEM_MR0, &Value8, &TechPtr->NBPtr->MemPtr->StdHeader); + Value8 <<= 4; + // WR + Temp32 = NBPtr->MemNGetMR0WR (NBPtr); + Value8 |= (UINT8) ((Temp32 >> 8) & 0x000000FF); + MemTSendExtMBCtlWord3 (TechPtr, 0x00C9 , Value8, 1); + // ExtRC_xCA + MemTSendExtMBCtlWord3 (TechPtr, 0x00CA , 0, 1); + // ExtRC_xCB + MemTSendExtMBCtlWord3 (TechPtr, 0x00CB , 0, 1); + // ExtRC_xCC + // CWL + Value8 = (UINT8) (NBPtr->MemNGetMR2CWL (NBPtr) & 0x000000FF); + // SRT|ASR + Value8 |= 0x40; + MemTSendExtMBCtlWord3 (TechPtr, 0x00CC , Value8, 1); + // ExtRC_xCD + MemTSendExtMBCtlWord3 (TechPtr, 0x00CD , 0, 1); + // ExtRC_xCE + MemTSendExtMBCtlWord3 (TechPtr, 0x00CE , 0, 1); + // ExtRC_xCF + MemTSendExtMBCtlWord3 (TechPtr, 0x00CF , 0, 1); + } + } + } + return TRUE; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function sends LRDIMM Control Words to all LRDIMMS + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in,out] OptParam - Optional parameter + * + * @return FALSE - The current channel does not have LRDIMM populated + * TRUE - The current channel has LRDIMM populated + */ +BOOLEAN +STATIC +MemTLrDimmFreqChgCtrlWrd3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *OptParam + ) +{ + UINT8 Dct; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + if (NBPtr->MCTPtr->Status[SbLrdimms]) { + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + MemNSwitchDCTNb (NBPtr, Dct); + if (NBPtr->DCTPtr->Timings.DctMemSize != 0) { + MemTLrDimmControlRegInit3 (TechPtr, NULL); + } + } + return TRUE; + } + return FALSE; +} + +/*----------------------------------------------------------------------------- + * + * + * This function prepares LRDIMMs for WL training. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in,out] *Wl - Indicates if WL mode should be enabled + * + * @return TRUE - LRDIMMs present + * ---------------------------------------------------------------------------- + */ +BOOLEAN +STATIC +MemTWLPrepareLrdimm3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *Wl + ) +{ + UINT8 Dimm; + UINT8 Value8; + UINT16 MrsAddress; + MEM_NB_BLOCK *NBPtr; + NBPtr = TechPtr->NBPtr; + MrsAddress = 0; + if (NBPtr->MCTPtr->Status[SbLrdimms]) { + for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) { + if (*(BOOLEAN *) Wl == TRUE) { + // Program WrLvOdt + NBPtr->SetBitField (NBPtr, BFWrLvOdt, NBPtr->ChannelPtr->PhyWLODT[Dimm]); + } + if ((NBPtr->ChannelPtr->LrDimmPresent & ((UINT8) 1 << Dimm)) != 0) { + if (Dimm == TechPtr->TargetDIMM) { + if (*(BOOLEAN *) Wl == TRUE) { + // + // Select the Target Chipselects + // + NBPtr->SetBitField (NBPtr, BFMrsChipSel, (Dimm << 1)); + NBPtr->SetBitField (NBPtr, BFCtrlWordCS, 3 << (Dimm << 1)); + // Program F0RC12 to 1h + MemTSendMBCtlWord3 (TechPtr, F0, RC12, 0x01); + if (NBPtr->ChannelPtr->Dimms >= 2) { + // For two or more LRDIMMs per channel program the buffer RttNom to the + // corresponding specifed RttWr termination + Value8 = NBPtr->MemNGetDynDramTerm (NBPtr, Dimm << 2); + } else { + // Program RttNom as normal + Value8 = NBPtr->MemNGetDramTerm (NBPtr, Dimm << 2); + } + if ((Value8 & ((UINT8) 1 << 2)) != 0) { + MrsAddress |= ((UINT16) 1 << 9); + } + if ((Value8 & ((UINT8) 1 << 1)) != 0) { + MrsAddress |= ((UINT16) 1 << 6); + } + if ((Value8 & ((UINT8) 1 << 0)) != 0) { + MrsAddress |= ((UINT16) 1 << 2); + } + NBPtr->SetBitField (NBPtr, BFMrsAddress, MrsAddress); + } else { + // Program F0RC12 to 0h + MemTSendMBCtlWord3 (TechPtr, F0, RC12, 0x00); + } + } + } + } + return TRUE; + } else { + return FALSE; + } +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This send all MR commands to all physical ranks of an LRDIMM + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] *CsPtr - Target Chip Select + * + * @return FALSE - The current channel does not have LRDIMM populated + * TRUE - The current channel has LRDIMM populated + */ +BOOLEAN +STATIC +MemTSendAllMRCmdsLR3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *CsPtr + ) +{ + UINT8 *SpdBufferPtr; + UINT8 Rank; + UINT8 PhyRank; + UINT8 ChipSel; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + ChipSel = *((UINT8 *) CsPtr); + + if (NBPtr->MCTPtr->Status[SbLrdimms]) { + // + // For LRDIMMs, MR0, MR2, and MR3 can be broadcast to any physicall ranks behind + // each logical rank(CS) by setting MRSAddress[13]. MR1[Rtt_Nom] needs to be programmed + // differently per physical rank, so it must target a physical rank using MrsAddress[17:14]. + // The actual bits used to index the physical rank are determined by the DRAM Capacity. + // + // This function will be called once for each CS where CSPresent is set, so each time + // it only needs to handle the Physical ranks behind each CS. If a Dimm is not using some + // CS due to Rank Mux, those CSPresent bits will have been already cleared. + // + + // + // Select target chip select + // + NBPtr->SetBitField (NBPtr, BFMrsChipSel, ChipSel); + // + // 13.Send EMRS(2) + // + MemTEMRS2Lr3 (TechPtr, ChipSel); + NBPtr->SetBitField (NBPtr, BFMrsAddressHi, 1); // Set Address bit 13 to broadcast + NBPtr->SendMrsCmd (NBPtr); + // + // 14.Send EMRS(3). Ordinarily at this time, MrsAddress[2:0]=000b + // + MemTEMRS33 (TechPtr); + NBPtr->SetBitField (NBPtr, BFMrsAddressHi, 1); // Set Address bit 13 to broadcast + NBPtr->SendMrsCmd (NBPtr); + // + // 15.Send EMRS(1). Send to each physical rank. + // + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, ChipSel >> 1); + // + // Determine first physical rank relative to the LRDIMM for this CS + // + PhyRank = ((((ChipSel & NBPtr->ChannelPtr->LrDimmLogicalRanks[ChipSel >> 1]) >> 1) & 2) | (ChipSel & 1)); + for (Rank = 0; Rank < NBPtr->ChannelPtr->LrDimmRankMult[ChipSel >> 1]; Rank++) { + MemTEMRS1Lr3 (TechPtr, ChipSel, PhyRank); + // + // Set Address bit 14, 15, 16, or 17 to select physical rank, relative to the CS, according to the device size + // + NBPtr->SetBitField (NBPtr, BFMrsAddressHi, Rank << ((SpdBufferPtr[SPD_DENSITY] & 0xF) - 1 ) ); + NBPtr->SendMrsCmd (NBPtr); + // + // Index to the next physical rank + // + PhyRank = PhyRank + NBPtr->ChannelPtr->LrDimmLogicalRanks[ChipSel >> 1]; + } + // + // 16.Send MRS with MrsAddress[8]=1(reset the DLL) + // + MemTMRS3 (TechPtr); + NBPtr->SetBitField (NBPtr, BFMrsAddressHi, 1); // Set Address bit 13 to broadcast + NBPtr->SendMrsCmd (NBPtr); + // + // If LRDIMM, return TRUE to skip sending regular MR commands. + // + return TRUE; + } + // + // If not LRDIMM, send regular MR commands. + // + return FALSE; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function calculates the EMRS1 value for an LRDIMM + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] ChipSel - Chip select number + * @param[in] PhyRank - Physical rank number + */ + +VOID +STATIC +MemTEMRS1Lr3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 ChipSel, + IN UINT8 PhyRank + ) +{ + UINT16 MrsAddress; + UINT8 Value8; + UINT8 *SpdBufferPtr; + UINT8 FreqDiffOffset; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, ChipSel >> 1); + FreqDiffOffset = (UINT8) (SPD_FREQ_DIFF_OFFSET * (((NBPtr->DCTPtr->Timings.Speed / 133) - 3) / 2)); + + // BA2=0,BA1=0,BA0=1 + NBPtr->SetBitField (NBPtr, BFMrsBank, 1); + + MrsAddress = 0; + + // program MrsAddress[5,1]=output driver impedance control (DIC): 01b + MrsAddress |= ((UINT16) 1 << 1); + + // program MrsAddress[5,1]=output driver impedance control (DIC): + // DIC is read from SPD byte 77, 83, or 89 depending on DDR speed + Value8 = SpdBufferPtr[SPD_MR1_MR2_800_1066 + FreqDiffOffset] & 3; + if ((Value8 & ((UINT8) 1 << 1)) != 0) { + MrsAddress |= ((UINT16) 1 << 5); + } + if ((Value8 & ((UINT8) 1 << 0)) != 0) { + MrsAddress |= ((UINT16) 1 << 1); + } + + // program MrsAddress[9,6,2]=nominal termination resistance of ODT (RTT): + // RttNom is read from SPD byte 77, 83, or 89 depending on DDR speed + if (PhyRank <= 1) { + Value8 = (SpdBufferPtr[SPD_MR1_MR2_800_1066 + FreqDiffOffset] >> 2) & 7; + if ((Value8 & ((UINT8) 1 << 2)) != 0) { + MrsAddress |= ((UINT16) 1 << 9); + } + if ((Value8 & ((UINT8) 1 << 1)) != 0) { + MrsAddress |= ((UINT16) 1 << 6); + } + if ((Value8 & ((UINT8) 1 << 0)) != 0) { + MrsAddress |= ((UINT16) 1 << 2); + } + } + + NBPtr->SetBitField (NBPtr, BFMrsAddress, MrsAddress); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function calculates the EMRS2 value for an LRDIMM + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] ChipSel - Chip select number + */ + +VOID +STATIC +MemTEMRS2Lr3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 ChipSel + ) +{ + UINT8 RttWr; + UINT8 *SpdBufferPtr; + UINT8 FreqDiffOffset; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + // Save default RttWr + RttWr = NBPtr->PsPtr->RttWr[ChipSel]; + + // Override RttWr with the value read from SPD byte 77, 83, or 89 depending on DDR speed + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, ChipSel >> 1); + FreqDiffOffset = (UINT8) (SPD_FREQ_DIFF_OFFSET * (((NBPtr->DCTPtr->Timings.Speed / 133) - 3) / 2)); + NBPtr->PsPtr->RttWr[ChipSel] = SpdBufferPtr[SPD_MR1_MR2_800_1066 + FreqDiffOffset] >> 6; + + // Call EMRS2 calculation + MemTEMRS23 (TechPtr); + + // Restore RttWr + NBPtr->PsPtr->RttWr[ChipSel] = RttWr; +} + +/*----------------------------------------------------------------------------- + * + * + * This function to determine the Rank Multiplication to use for an LRDIMM + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in,out] *DimmID - Dimm ID + * + * @return TRUE - LRDIMM Support is installed and LRDIMMs are present + * ---------------------------------------------------------------------------- + */ +BOOLEAN +STATIC +MemTLrdimmRankMultiplication ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *DimmID + ) +{ + BOOLEAN RetVal; + UINT8 *SpdBufferPtr; + UINT8 Dimm; + UINT8 NumDimmslots; + UINT8 DramCapacity; + UINT8 Ranks; + UINT8 Rows; + UINT8 RankMult; + MEM_NB_BLOCK *NBPtr; + CH_DEF_STRUCT *ChannelPtr; + + ASSERT (TechPtr != NULL); + ASSERT (DimmID != NULL); + + Dimm = *(UINT8*)DimmID; + ASSERT (Dimm < MAX_DIMMS_PER_CHANNEL); + + NBPtr = TechPtr->NBPtr; + ChannelPtr = NBPtr->ChannelPtr; + RetVal = FALSE; + RankMult = 0; + + if (!MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, Dimm)) { + ASSERT (FALSE); + } + + NumDimmslots = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, + NBPtr->MCTPtr->SocketId, + ChannelPtr->ChannelID); + + if (NBPtr->MCTPtr->Status[SbLrdimms]) { + RetVal = TRUE; + // + // Determine LRDIMM Rank Multiplication + // + Ranks = ((SpdBufferPtr[SPD_RANKS] >> 3) & 0x07) + 1; + if (Ranks == 5) { + Ranks = 8; + } + DramCapacity = (SpdBufferPtr[SPD_DENSITY] & 0x0F); + Rows = 12 + ((SpdBufferPtr[SPD_ROW_SZ] >> 3) & 0x7); + + if (Ranks < 4) { + RankMult = 1; + } else if (Ranks == 4) { + RankMult = (NumDimmslots < 3) ? 1 : 2; + } else if (Ranks == 8) { + RankMult = ((NumDimmslots < 3) && (DramCapacity < 4)) ? 2 : 4; + } + // + // Save Rank Information + // + ChannelPtr->LrDimmRankMult[Dimm] = RankMult; + ChannelPtr->LrDimmLogicalRanks[Dimm] = Ranks / RankMult; + NBPtr->PsPtr->LrdimmRowAddrBits[Dimm] = Rows + (RankMult >> 1); + // + // Program RankDef + // + NBPtr->SetBitField (NBPtr, BFRankDef0 + Dimm, (RankMult == 4) ? 3 : RankMult); + // + // If LrdimmRowAddressBits > 16, then we must be using some CS signals for rank + // multiplication. If this is the case, then we want to clear the CSPresent bits + // that correspond to those chipselects. + // If there are 3 DIMMs per channel, then it will always be CS67, if there are + // 2DPCH, then DIMM0 will use CS45, and DIMM1 will use CS67. + // + if ((ChannelPtr->LrDimmLogicalRanks[Dimm] < 4) && (Dimm >= NumDimmslots)) { + NBPtr->DCTPtr->Timings.CsPresent &= ~(0x3 << (Dimm << 1)); + ChannelPtr->LrDimmRankMult[Dimm] = 0; + ChannelPtr->LrDimmLogicalRanks[Dimm] = 0; + NBPtr->PsPtr->LrdimmRowAddrBits[Dimm] = 0; + } else { + IDS_HDT_CONSOLE_DEBUG_CODE ( + if (Dimm < NumDimmslots) { + IDS_HDT_CONSOLE (MEM_FLOW,"\tDimm %d: Log. Ranks:%d Phys. Ranks:%d RowAddrBits:%d RankMult:%d\n", + Dimm, + ChannelPtr->LrDimmLogicalRanks[Dimm], + ChannelPtr->LrdimmPhysicalRanks[Dimm], + NBPtr->PsPtr->LrdimmRowAddrBits[Dimm], + RankMult + ); + } + ); + } + } + return RetVal; +} + +/* ----------------------------------------------------------------------------- + * + * This function performs buffer to DRAM training for LRDIMMs + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in,out] OptParam - Optional parameter + * + * @return TRUE + */ + +BOOLEAN +STATIC +MemTLrdimmBuf2DramTrain3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *OptParam + ) +{ + MEM_DATA_STRUCT *MemPtr; + MEM_NB_BLOCK *NBPtr; + UINT8 Dct; + UINT8 Dimm; + UINT8 ChipSel; + UINT16 DimmMask; + UINT8 i; + + NBPtr = TechPtr->NBPtr; + MemPtr = NBPtr->MemPtr; + + if (NBPtr->MCTPtr->Status[SbLrdimms]) { + IDS_HDT_CONSOLE (MEM_FLOW, "\nStart Buffer to DRAM training\n"); + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct); + NBPtr->SwitchDCT (NBPtr, Dct); + // + // ODM needs to be set after Dram Init + // + if (NBPtr->StartupSpeed == NBPtr->DCTPtr->Timings.Speed) { + for (ChipSel = 1; ChipSel < MAX_CS_PER_CHANNEL; ChipSel += 2) { + if ((NBPtr->DCTPtr->Timings.CsPresent & ((UINT16)1 << ChipSel)) != 0) { + if ((NBPtr->DCTPtr->Timings.DimmMirrorPresent & (1 << (ChipSel >> 1))) != 0) { + NBPtr->SetBitField (NBPtr, BFCSBaseAddr0Reg + ChipSel, ((NBPtr->GetBitField (NBPtr, BFCSBaseAddr0Reg + ChipSel)) | ((UINT32)1 << BFOnDimmMirror ))); + } + } + } + } + // + // Buffer to DRAM training + // + for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) { + DimmMask = (UINT16)1 << Dimm; + if ((NBPtr->ChannelPtr->LrDimmPresent & DimmMask) != 0) { + IDS_HDT_CONSOLE (MEM_STATUS, "\t\nDimm %d\n", Dimm); + // + // Select the Target Chipselects + // + NBPtr->SetBitField (NBPtr, BFMrsChipSel, (Dimm << 1)); + NBPtr->SetBitField (NBPtr, BFCtrlWordCS, 3 << (Dimm << 1)); + + NBPtr->SetBitField (NBPtr, BFLrDimmErrOutMonEn, 1); + MemTSendMBCtlWord3 (TechPtr, F2, RC3, 8); + // Send F0RC12 with data = 0010b. + MemTSendMBCtlWord3 (TechPtr, F0, RC12, 2); + // + // Wait until D18F2xA0_dct[1:0][RcvParErr]=0 or tCAL * the number of physical ranks expires. + // + IDS_HDT_CONSOLE (MEM_FLOW, "\t\tWaiting %d ms...\n", 10 * NBPtr->ChannelPtr->LrdimmPhysicalRanks[Dimm]); + for (i = 0; i < (NBPtr->ChannelPtr->LrdimmPhysicalRanks[Dimm] * 10); i++) { + MemUWait10ns (1000000, MemPtr); + // + // @todo: Provide option for polling RcvParErr to optimize DRAM bus timing. + // + } + IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tRcvParErr = %02x\n", NBPtr->GetBitField (NBPtr, BFRcvParErr)); + NBPtr->SetBitField (NBPtr, BFLrDimmErrOutMonEn, 0); + MemTSendMBCtlWord3 (TechPtr, F2, RC3, 0); + // Configure for normal operation: Send F0RC12 with data = 0000b. + MemTSendMBCtlWord3 (TechPtr, F0, RC12, 0); + } + } + } + IDS_HDT_CONSOLE (MEM_FLOW, "\nEnd Buffer to DRAM training\n"); + } + return TRUE; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function copies trained delays of the first rank of a QR LRDIMM to the third rank + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in,out] OptParam - Optional parameter + * + * @return TRUE + */ + +BOOLEAN +STATIC +MemTLrdimmSyncTrainedDlys ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *OptParam + ) +{ + UINT8 i; + UINT8 Dimm; + UINT8 Dct; + MEM_NB_BLOCK *NBPtr; + CH_DEF_STRUCT *ChannelPtr; + UINT16 WrDqsDly; + UINT16 RcvEnDly; + UINT16 RdDqsDly; + UINT16 WrDatDly; + UINT8 RdDqs2dDly; + NBPtr = TechPtr->NBPtr; + + if (NBPtr->MCTPtr->Status[SbLrdimms]) { + IDS_HDT_CONSOLE (MEM_STATUS, "\tSync LRDIMM Delays to remaining ranks.\n"); + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct); + NBPtr->SwitchDCT (NBPtr, Dct); + ChannelPtr = NBPtr->ChannelPtr; + for (Dimm = 0; Dimm < 2; Dimm++) { + if (ChannelPtr->LrDimmLogicalRanks[Dimm] > 2) { + // If logical QR LRDIMM, copy trained delays from first rank to third rank + IDS_HDT_CONSOLE (MEM_FLOW, "\t\tDimm %d -> Dimm %d\n",Dimm, Dimm + 2); + for (i = 0; i < TechPtr->DlyTableWidth (); i++) { + WrDqsDly = ChannelPtr->WrDqsDlys[Dimm * TechPtr->DlyTableWidth () + i]; + NBPtr->SetTrainDly (NBPtr, AccessWrDqsDly, DIMM_BYTE_ACCESS (Dimm + 2, i), WrDqsDly); + ChannelPtr->WrDqsDlys[(Dimm + 2) * TechPtr->DlyTableWidth () + i] = (UINT8)WrDqsDly; + + RcvEnDly = ChannelPtr->RcvEnDlys[Dimm * TechPtr->DlyTableWidth () + i]; + NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (Dimm + 2, i), RcvEnDly); + ChannelPtr->RcvEnDlys[(Dimm + 2) * TechPtr->DlyTableWidth () + i] = RcvEnDly; + + RdDqsDly = ChannelPtr->RdDqsDlys[Dimm * TechPtr->DlyTableWidth () + i]; + NBPtr->SetTrainDly (NBPtr, AccessRdDqsDly, DIMM_BYTE_ACCESS (Dimm + 2, i), RdDqsDly); + ChannelPtr->RdDqsDlys[(Dimm + 2) * TechPtr->DlyTableWidth () + i] = (UINT8)RdDqsDly; + + WrDatDly = ChannelPtr->WrDatDlys[Dimm * TechPtr->DlyTableWidth () + i]; + NBPtr->SetTrainDly (NBPtr, AccessWrDatDly, DIMM_BYTE_ACCESS (Dimm + 2, i), WrDatDly); + ChannelPtr->WrDatDlys[(Dimm + 2) * TechPtr->DlyTableWidth () + i] = (UINT8)WrDatDly; + } + if ((ChannelPtr->DimmNibbleAccess & (1 << Dimm)) != 0) { + // + // If 2D x4 (Not Currently POR for LRDIMMs) + // + for (i = 0; i < MAX_NUMBER_LANES; i++) { + if (ChannelPtr->LrDimmLogicalRanks[Dimm] > 2) { + // If logical QR LRDIMM, copy trained delays from first rank to third rank + RdDqs2dDly = ChannelPtr->RdDqs2dDlys[Dimm * MAX_NUMBER_LANES + i]; + NBPtr->SetTrainDly (NBPtr, excel845 , DIMM_NBBL_ACCESS (Dimm + 2, i), + ChannelPtr->RdDqs2dDlys[Dimm * MAX_NUMBER_LANES + i]); + ChannelPtr->RdDqs2dDlys[(Dimm + 2) * MAX_NUMBER_LANES + i] = (UINT8)RdDqs2dDly; + } + } + } + } + } + } + return TRUE; + } else { + return FALSE; + } +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function performs LRDIMM specific tasks during Dimm Presence detection + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in,out] *DimmID - Dimm ID + * + * @return TRUE + * + */ + +BOOLEAN +STATIC +MemTLrdimmPresence ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT VOID *DimmID + ) +{ + MEM_NB_BLOCK *NBPtr; + UINT32 BufferID; + UINT8 Dimm; + NBPtr = TechPtr->NBPtr; + Dimm = *(UINT8*) DimmID; + + BufferID = MemTLrDimmGetBufferID (TechPtr, Dimm); + if ((BufferID == 0x0020B304) || (BufferID == 0x0020B380)) { + IDS_HDT_CONSOLE (MEM_FLOW, "\tDimm %d: Unsupported LRDIMM Buffer Revision\n", Dimm); + PutEventLog (AGESA_WARNING, MEM_WARNING_UNSUPPORTED_LRDIMM, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, Dimm, &NBPtr->MemPtr->StdHeader); + NBPtr->DCTPtr->Timings.CsTestFail |= (UINT16)0x3 << (Dimm << 1); + } + return TRUE; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function returns LRDIMM Buffer ID Info from the SPD + * + * + * @param[in,out] *TechPtr - Pointer to the Technology Block + * @param[in] Dimm - Dimm number + * + * @return Buffer ID Information + * + */ + +UINT32 +STATIC +MemTLrDimmGetBufferID ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Dimm + ) +{ + UINT8 *SpdBufferPtr; + UINT32 BufferID; + + BufferID = 0; + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, Dimm); + BufferID = (SpdBufferPtr[64] << 16) | (SpdBufferPtr[66] << 8) | (SpdBufferPtr[65]); + return BufferID; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function implements special case Initialization hooks for LRDIMMs + * + * @param[in] TechPtr - Tech Block Pointer + * @param[in] Entrypoint - Entrypoint to indicate when this hook is called + * @param[in] Dimm - Dimm being configured when hook is called + * @param[in] OptParam - Not Used + */ + +VOID +STATIC +MemTLrdimmInitHook ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN LRDIMM_HOOK_ENTRYPOINT Entrypoint, + IN UINT8 Dimm, + IN OUT VOID *OptParam + ) +{ + MEM_NB_BLOCK *NBPtr; + UINT8 i; + CONST UINT16 AfterTstabRcwTable[] = { + 0x0270, 0x0000, + 0x0122, 0x0074, + 0x0124, 0x009B, + 0x0126, 0x00C2, + 0x0128, 0x00E8, + 0x01D2, 0x5942, + 0x01D4, 0x836D, + 0x01CE, 0x5942, + 0x01D0, 0x836D, + 0x01D6, 0x017F, + 0x01D8, 0x0000, + 0x01F0, 0x008E, + 0x01F2, 0x00BA, + 0x01F4, 0x00E8, + 0x01F6, 0x0114, + 0x0B40, 0x7054, + 0x0B42, 0xA48A, + 0x0B3C, 0x7054, + 0x0B3E, 0xA48A, + 0x0B38, 0x0100, + 0x0B3A, 0x0000, + + 0x0274, 0x55AA, + 0x3012, 0x0080, + 0x3018, 0x6B80 + }; + if (MemTLrDimmGetBufferID (TechPtr, Dimm) != 0x0021B304) { + return; + } + NBPtr = TechPtr->NBPtr; + switch (Entrypoint) { + case AFTER_TSTAB: + MemTSendMBCtlWord3 (TechPtr, F14, RC0, 0xB); + for ( i = 0 ; i < (sizeof (AfterTstabRcwTable) / sizeof (UINT16)); i += 2 ) { + MemTSendExtMBCtlWord3 (TechPtr, AfterTstabRcwTable[i], AfterTstabRcwTable[i + 1], 2); + } + break; + default: + // + // If a hook entrypoint is called, it should have a case for it. + // + ASSERT (FALSE); + break; + } +}
\ No newline at end of file diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtlrdimm3.h b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtlrdimm3.h new file mode 100644 index 0000000000..be553114fe --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtlrdimm3.h @@ -0,0 +1,159 @@ +/** + * @file + * + * mtlrdimm3.h + * + * Definitions and declarations for DDR3 LRDIMM support + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** + * + * Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. + * + * AMD is granting you permission to use this software (the Materials) + * pursuant to the terms and conditions of your Software License Agreement + * with AMD. This header does *NOT* give you permission to use the Materials + * or any rights under AMD's intellectual property. Your use of any portion + * of these Materials shall constitute your acceptance of those terms and + * conditions. If you do not agree to the terms and conditions of the Software + * License Agreement, please do not use any portion of these Materials. + * + * CONFIDENTIALITY: The Materials and all other information, identified as + * confidential and provided to you by AMD shall be kept confidential in + * accordance with the terms and conditions of the Software License Agreement. + * + * LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION + * PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, + * OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. + * IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER + * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS + * INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, + * GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER + * RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE + * EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, + * THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + * + * AMD does not assume any responsibility for any errors which may appear in + * the Materials or any other related information provided to you by AMD, or + * result from use of the Materials or any related information. + * + * You agree that you will not reverse engineer or decompile the Materials. + * + * NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + * further information, software, technical information, know-how, or show-how + * available to you. Additionally, AMD retains the right to modify the + * Materials at any time, without notice, and is not obligated to provide such + * modified Materials to you. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with + * "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is + * subject to the restrictions as set forth in FAR 52.227-14 and + * DFAR252.227-7013, et seq., or its successor. Use of the Materials by the + * Government constitutes acknowledgement of AMD's proprietary rights in them. + * + * EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any + * direct product thereof will be exported directly or indirectly, into any + * country prohibited by the United States Export Administration Act and the + * regulations thereunder, without the required authorization from the U.S. + * government nor will be used for any purpose prohibited by the same. + * *************************************************************************** + * + */ + +#ifndef _MTLRDIMM3_H_ +#define _MTLRDIMM3_H_ + +/*---------------------------------------------------------------------------- + * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS) + * + *---------------------------------------------------------------------------- + */ + +/*----------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *----------------------------------------------------------------------------- + */ +#define RCW_FN_SELECT 7 + +#define F0 0 +#define F1 1 +#define F2 2 +#define F3 3 +#define F4 4 +#define F5 5 +#define F6 6 +#define F7 7 +#define F8 8 +#define F9 9 +#define F10 10 +#define F11 11 +#define F12 12 +#define F13 13 +#define F14 14 +#define F15 15 + +#define RC0 0 +#define RC1 1 +#define RC2 2 +#define RC3 3 +#define RC4 4 +#define RC5 5 +#define RC6 6 +#define RC7 7 +#define RC8 8 +#define RC9 9 +#define RC10 10 +#define RC11 11 +#define RC12 12 +#define RC13 13 +#define RC14 14 +#define RC15 15 + +#define SPD_NONE 0 +#define SPD_67 67 +#define SPD_68 68 +#define SPD_69 69 +#define SPD_70 70 +#define SPD_71 71 + +#define SPD_MDQ_800_1066 72 +#define SPD_QXODT_800_1066 73 +#define SPD_MR1_MR2_800_1066 77 +#define SPD_PERSONALITY_BYTE 102 +#define SPD_FREQ_DIFF_OFFSET 6 + +#define SPECIAL_CASE 0xFF +#define WAIT_6US 0xF6 + +/*---------------------------------------------------------------------------- + * TYPEDEFS, STRUCTURES, ENUMS + * + *---------------------------------------------------------------------------- + */ + +/// LRDIMM SPECIALIZED HOOK ENTRY POINTS +typedef enum { + AFTER_TSTAB, ///< Time point after tStab + AFTER_RCW, ///< Time point after LrDimm Rcw commands are sent + BEFORE_BUFFERTRN, ///< Time point just before Buffer training + AFTER_BUFFERTRN, ///< Time point just after Buffer training + BEFORE_HOST_WL, ///< Time point before host WL + AFTER_HOST_WL ///< Time point after host WL +} LRDIMM_HOOK_ENTRYPOINT; + +/*---------------------------------------------------------------------------- + * FUNCTIONS PROTOTYPE + * + *---------------------------------------------------------------------------- + */ + +#endif /* _MTLRDIMM3_H_ */ diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtot3.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtot3.c new file mode 100644 index 0000000000..a90c5c2aa6 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtot3.c @@ -0,0 +1,194 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mtot3.c + * + * Technology Non-SPD Timings for DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** +* +* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. +* +* AMD is granting you permission to use this software (the Materials) +* pursuant to the terms and conditions of your Software License Agreement +* with AMD. This header does *NOT* give you permission to use the Materials +* or any rights under AMD's intellectual property. Your use of any portion +* of these Materials shall constitute your acceptance of those terms and +* conditions. If you do not agree to the terms and conditions of the Software +* License Agreement, please do not use any portion of these Materials. +* +* CONFIDENTIALITY: The Materials and all other information, identified as +* confidential and provided to you by AMD shall be kept confidential in +* accordance with the terms and conditions of the Software License Agreement. +* +* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION +* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED +* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, +* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. +* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER +* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS +* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, +* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER +* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE +* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, +* THE ABOVE LIMITATION MAY NOT APPLY TO YOU. +* +* AMD does not assume any responsibility for any errors which may appear in +* the Materials or any other related information provided to you by AMD, or +* result from use of the Materials or any related information. +* +* You agree that you will not reverse engineer or decompile the Materials. +* +* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any +* further information, software, technical information, know-how, or show-how +* available to you. Additionally, AMD retains the right to modify the +* Materials at any time, without notice, and is not obligated to provide such +* modified Materials to you. +* +* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with +* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is +* subject to the restrictions as set forth in FAR 52.227-14 and +* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the +* Government constitutes acknowledgement of AMD's proprietary rights in them. +* +* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any +* direct product thereof will be exported directly or indirectly, into any +* country prohibited by the United States Export Administration Act and the +* regulations thereunder, without the required authorization from the U.S. +* government nor will be used for any purpose prohibited by the same. +* *************************************************************************** +* +*/ + +/* + *---------------------------------------------------------------------------- + * MODULES USED + * + *---------------------------------------------------------------------------- + */ + + + +#include "AGESA.h" +#include "Ids.h" +#include "mm.h" +#include "mn.h" +#include "mt.h" +#include "mtot3.h" +#include "Filecode.h" +CODE_GROUP (G1_PEICC) +RDATA_GROUP (G1_PEICC) + +#define FILECODE PROC_MEM_TECH_DDR3_MTOT3_FILECODE +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function adjusts the Twrwr value for DDR3. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +VOID +MemTAdjustTwrwr3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + DCT_STRUCT *DCTPtr; + + DCTPtr = TechPtr->NBPtr->DCTPtr; + + // For DDR3, value 0000b-0001b and >= 1011b of Twrwr is reserved. + if (DCTPtr->Timings.Twrwr < 2) { + DCTPtr->Timings.Twrwr = 2; + } else if (DCTPtr->Timings.Twrwr > 10) { + DCTPtr->Timings.Twrwr = 10; + } +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function adjusts the Twrrd value for DDR3. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +VOID +MemTAdjustTwrrd3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + DCT_STRUCT *DCTPtr; + + DCTPtr = TechPtr->NBPtr->DCTPtr; + + // For DDR3, value 0000b, 0001b, and > 1010b of Twrrd is reserved. + if (DCTPtr->Timings.Twrrd < 2) { + DCTPtr->Timings.Twrrd = 2; + } else if (DCTPtr->Timings.Twrrd > 10) { + DCTPtr->Timings.Twrrd = 10; + } +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function gets the LD value for DDR3. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return Value of LD + */ + +INT8 +MemTGetLD3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + INT8 LD; + MEM_NB_BLOCK *NBPtr; + NBPtr = TechPtr->NBPtr; + // + // For DDR3, BIOS calculates the latency difference (Ld) as equal to read CAS latency minus write CAS + // latency, in MEMCLKs (see F2x[1, 0]88[Tcl] and F2x[1, 0]84[Tcwl]) which can be a negative or positive + // value. + // + LD = ((INT8) NBPtr->GetBitField (NBPtr, BFTcl) + 4) - ((INT8) NBPtr->GetBitField (NBPtr, BFTcwl) + 5); + + return LD; +} diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtot3.h b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtot3.h new file mode 100644 index 0000000000..06073fb281 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtot3.h @@ -0,0 +1,117 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mtot3.h + * + * Technology Non-SPD timings for DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** + * + * Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. + * + * AMD is granting you permission to use this software (the Materials) + * pursuant to the terms and conditions of your Software License Agreement + * with AMD. This header does *NOT* give you permission to use the Materials + * or any rights under AMD's intellectual property. Your use of any portion + * of these Materials shall constitute your acceptance of those terms and + * conditions. If you do not agree to the terms and conditions of the Software + * License Agreement, please do not use any portion of these Materials. + * + * CONFIDENTIALITY: The Materials and all other information, identified as + * confidential and provided to you by AMD shall be kept confidential in + * accordance with the terms and conditions of the Software License Agreement. + * + * LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION + * PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, + * OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. + * IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER + * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS + * INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, + * GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER + * RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE + * EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, + * THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + * + * AMD does not assume any responsibility for any errors which may appear in + * the Materials or any other related information provided to you by AMD, or + * result from use of the Materials or any related information. + * + * You agree that you will not reverse engineer or decompile the Materials. + * + * NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + * further information, software, technical information, know-how, or show-how + * available to you. Additionally, AMD retains the right to modify the + * Materials at any time, without notice, and is not obligated to provide such + * modified Materials to you. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with + * "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is + * subject to the restrictions as set forth in FAR 52.227-14 and + * DFAR252.227-7013, et seq., or its successor. Use of the Materials by the + * Government constitutes acknowledgement of AMD's proprietary rights in them. + * + * EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any + * direct product thereof will be exported directly or indirectly, into any + * country prohibited by the United States Export Administration Act and the + * regulations thereunder, without the required authorization from the U.S. + * government nor will be used for any purpose prohibited by the same. + * *************************************************************************** + * + */ + +#ifndef _MTOT3_H_ +#define _MTOT3_H_ + +/*---------------------------------------------------------------------------- + * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS) + * + *---------------------------------------------------------------------------- + */ + +/*----------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *----------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS, STRUCTURES, ENUMS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * FUNCTIONS PROTOTYPE + * + *---------------------------------------------------------------------------- + */ + + +VOID +MemTAdjustTwrwr3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +VOID +MemTAdjustTwrrd3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +INT8 +MemTGetLD3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +#endif /* _MTOT3_H_ */ + + diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtrci3.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtrci3.c new file mode 100644 index 0000000000..29a17307d8 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtrci3.c @@ -0,0 +1,345 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mtrci3.c + * + * Technology Control word initialization for DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** +* +* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. +* +* AMD is granting you permission to use this software (the Materials) +* pursuant to the terms and conditions of your Software License Agreement +* with AMD. This header does *NOT* give you permission to use the Materials +* or any rights under AMD's intellectual property. Your use of any portion +* of these Materials shall constitute your acceptance of those terms and +* conditions. If you do not agree to the terms and conditions of the Software +* License Agreement, please do not use any portion of these Materials. +* +* CONFIDENTIALITY: The Materials and all other information, identified as +* confidential and provided to you by AMD shall be kept confidential in +* accordance with the terms and conditions of the Software License Agreement. +* +* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION +* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED +* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, +* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. +* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER +* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS +* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, +* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER +* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE +* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, +* THE ABOVE LIMITATION MAY NOT APPLY TO YOU. +* +* AMD does not assume any responsibility for any errors which may appear in +* the Materials or any other related information provided to you by AMD, or +* result from use of the Materials or any related information. +* +* You agree that you will not reverse engineer or decompile the Materials. +* +* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any +* further information, software, technical information, know-how, or show-how +* available to you. Additionally, AMD retains the right to modify the +* Materials at any time, without notice, and is not obligated to provide such +* modified Materials to you. +* +* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with +* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is +* subject to the restrictions as set forth in FAR 52.227-14 and +* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the +* Government constitutes acknowledgement of AMD's proprietary rights in them. +* +* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any +* direct product thereof will be exported directly or indirectly, into any +* country prohibited by the United States Export Administration Act and the +* regulations thereunder, without the required authorization from the U.S. +* government nor will be used for any purpose prohibited by the same. +* *************************************************************************** +* +*/ + +/* + *---------------------------------------------------------------------------- + * MODULES USED + * + *---------------------------------------------------------------------------- + */ + + + +#include "AGESA.h" +#include "Ids.h" +#include "mm.h" +#include "mn.h" +#include "mu.h" +#include "mt.h" +#include "mt3.h" +#include "mtrci3.h" +#include "merrhdl.h" +#include "Filecode.h" +CODE_GROUP (G1_PEICC) +RDATA_GROUP (G1_PEICC) + +#define FILECODE PROC_MEM_TECH_DDR3_MTRCI3_FILECODE +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ +extern BUILD_OPT_CFG UserOptions; + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function sends control words + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +VOID +MemTDramControlRegInit3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT8 ChipSel; + UINT8 i; + UINT8 RawCard; + UINT8 Data; + UINT16 CsPresent; + + MEM_DATA_STRUCT *MemPtr; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + MemPtr = NBPtr->MemPtr; + CsPresent = NBPtr->DCTPtr->Timings.CsPresent; + + MemUWait10ns (800, MemPtr); // wait 8us TACT must be changed to optimize to 8 MEM CLKs + + // Set EnDramInit to start DRAM initialization + + MemUWait10ns (600, MemPtr); // wait 6us for PLL LOCK + + for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel += 2) { + // + // If chip select present + // + if ((CsPresent & ((UINT16)3 << ChipSel)) != 0) { + NBPtr->SetBitField (NBPtr, BFMrsChipSel, ChipSel); + + // 2. Program F2x[1, 0]A8[CtrlWordCS]=bit mask for target chip selects. + NBPtr->SetBitField (NBPtr, BFCtrlWordCS, 3 << (ChipSel & 0xFE)); + + RawCard = NBPtr->ChannelPtr->RefRawCard[ChipSel >> 1]; + + for (i = 0; i <= 15; i++) { + // wait 8us for TMRD, must be changed to optimize to 8 MEM CLKs + MemUWait10ns (800, MemPtr); + if ((i != 6) && (i != 7)) { + Data = MemTGetCtlWord3 (TechPtr, i, RawCard, ChipSel); + MemTSendCtlWord3 (TechPtr, i, Data); + } + } + } + } + MemUWait10ns (600, MemPtr); // wait 6us for TSTAB +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function calculates the ControlRC value + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] CtrlWordNum - control Word number. + * @param[in] RawCard - Raw Card + * @param[in] ChipSel - Target Chip Select + * @return Control Word value + */ + +UINT8 +MemTGetCtlWord3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 CtrlWordNum, + IN UINT8 RawCard, + IN UINT8 ChipSel + ) +{ + UINT8 Data; + UINT8 PowerDownMode; + DCT_STRUCT *DCTPtr; + CH_DEF_STRUCT *ChannelPtr; + + DCTPtr = TechPtr->NBPtr->DCTPtr; + ChannelPtr = TechPtr->NBPtr->ChannelPtr; + + Data = 0; //Default value for all control words is 0 + switch (CtrlWordNum) { + case 0: + Data = 0x02; // DA4=1 + break; + case 1: + if (DCTPtr->Timings.DimmSRPresent & ((UINT16) 1 << (ChipSel >> 1))) { + Data = 0x0C; // if single rank, set DBA1 and DBA0 + } + break; + case 2: + Data = ChannelPtr->CtrlWrd02[ChipSel >> 1]; + break; + case 3: + Data = ChannelPtr->CtrlWrd03[ChipSel >> 1]; + break; + case 4: + Data = ChannelPtr->CtrlWrd04[ChipSel >> 1]; + break; + case 5: + Data = ChannelPtr->CtrlWrd05[ChipSel >> 1]; + break; + case 8: + Data = ChannelPtr->CtrlWrd08[ChipSel >> 1]; + break; + case 9: + // RC9 = 0xD except when partial powerdown mode is enabled and mix SR/DR or SR/QR configurations, + // RC9 should be 0x9 for SR and and 0xD for DR or QR RDIMMs. + PowerDownMode = (UINT8) UserOptions.CfgPowerDownMode; + PowerDownMode = (!TechPtr->NBPtr->IsSupported[ChannelPDMode]) ? PowerDownMode : 0; + IDS_OPTION_HOOK (IDS_POWERDOWN_MODE, &PowerDownMode, &(TechPtr->NBPtr->MemPtr->StdHeader)); + if ((PowerDownMode == 1) && + (DCTPtr->Timings.DimmSRPresent & ((UINT16) 1 << (ChipSel >> 1))) && + ((DCTPtr->Timings.DimmDrPresent != 0) || (DCTPtr->Timings.DimmQrPresent != 0))) { + Data = 0x09; + } else { + Data = 0x0D; + } + break; + case 11: + Data = CONVERT_VDDIO_TO_ENCODED (TechPtr->RefPtr->DDR3Voltage); + break; + default:; + } + + return (Data & 0x0F); +} +/* -----------------------------------------------------------------------------*/ +/** + * + * This function sends control word command + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] CmdNum - control number. + * @param[in] Value - value to send + * + */ + +VOID +MemTSendCtlWord3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 CmdNum, + IN UINT8 Value + ) +{ + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + // 1. Program MrsBank and MrsAddress. + // n = [BA2, A2, A1, A0]. + // data = [BA1, BA0, A4, A3]. + // Set all other bits in MrsAddress to zero. + // + NBPtr->SetBitField (NBPtr, BFMrsBank, ((CmdNum & 8) >> 1) | (Value >> 2)); + NBPtr->SetBitField (NBPtr, BFMrsAddress, ((Value & 3) << 3) | (CmdNum & 7)); + IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tCS%d RC%02d %04x\n", (MemNGetBitFieldNb (NBPtr, BFMrsChipSel) & 7), CmdNum, Value); + + // 2.Set SendCtrlWord=1 + NBPtr->SetBitField (NBPtr, BFSendCtrlWord, 1); + // 3.Wait for BFSendCtrlWord=0 + NBPtr->PollBitField (NBPtr, BFSendCtrlWord, 0, PCI_ACCESS_TIMEOUT, FALSE); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function sends specific control words commands before frequency change for certain DRAM buffers. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +VOID +FreqChgCtrlWrd3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT8 ChipSel; + UINT16 Speed; + UINT16 CsPresent; + + MEM_DATA_STRUCT *MemPtr; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + MemPtr = NBPtr->MemPtr; + Speed = NBPtr->DCTPtr->Timings.Speed; + CsPresent = NBPtr->DCTPtr->Timings.CsPresent; + + + for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel += 2) { + // + // If chip select present. + // + if ((CsPresent & ((UINT16)3 << ChipSel)) != 0) { + + NBPtr->SetBitField (NBPtr, BFMrsChipSel, ChipSel); + // program F2x[1, 0]A8[CtrlWordCS]=bit mask for target chip selects. + NBPtr->SetBitField (NBPtr, BFCtrlWordCS, 3 << (ChipSel & 0xFE)); + + //wait 8us for TMRD, must be changed to optimize to 8 MEM CLKs + MemUWait10ns (800, MemPtr); + if (Speed == DDR800_FREQUENCY) { + MemTSendCtlWord3 (TechPtr, 0x0A, 0); + } else if (Speed == DDR1066_FREQUENCY) { + MemTSendCtlWord3 (TechPtr, 0x0A, 1); + } else if (Speed == DDR1333_FREQUENCY) { + MemTSendCtlWord3 (TechPtr, 0x0A, 2); + } else if (Speed == DDR1600_FREQUENCY) { + MemTSendCtlWord3 (TechPtr, 0x0A, 3); + } else if (Speed == DDR1866_FREQUENCY) { + MemTSendCtlWord3 (TechPtr, 0x0A, 4); + } else { + ASSERT (FALSE); + } + } + } +} + diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtrci3.h b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtrci3.h new file mode 100644 index 0000000000..189bbf7b03 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtrci3.h @@ -0,0 +1,114 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mtrci3.h + * + * Technology control word init for DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** + * + * Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. + * + * AMD is granting you permission to use this software (the Materials) + * pursuant to the terms and conditions of your Software License Agreement + * with AMD. This header does *NOT* give you permission to use the Materials + * or any rights under AMD's intellectual property. Your use of any portion + * of these Materials shall constitute your acceptance of those terms and + * conditions. If you do not agree to the terms and conditions of the Software + * License Agreement, please do not use any portion of these Materials. + * + * CONFIDENTIALITY: The Materials and all other information, identified as + * confidential and provided to you by AMD shall be kept confidential in + * accordance with the terms and conditions of the Software License Agreement. + * + * LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION + * PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, + * OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. + * IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER + * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS + * INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, + * GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER + * RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE + * EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, + * THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + * + * AMD does not assume any responsibility for any errors which may appear in + * the Materials or any other related information provided to you by AMD, or + * result from use of the Materials or any related information. + * + * You agree that you will not reverse engineer or decompile the Materials. + * + * NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + * further information, software, technical information, know-how, or show-how + * available to you. Additionally, AMD retains the right to modify the + * Materials at any time, without notice, and is not obligated to provide such + * modified Materials to you. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with + * "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is + * subject to the restrictions as set forth in FAR 52.227-14 and + * DFAR252.227-7013, et seq., or its successor. Use of the Materials by the + * Government constitutes acknowledgement of AMD's proprietary rights in them. + * + * EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any + * direct product thereof will be exported directly or indirectly, into any + * country prohibited by the United States Export Administration Act and the + * regulations thereunder, without the required authorization from the U.S. + * government nor will be used for any purpose prohibited by the same. + * *************************************************************************** + * + */ + +#ifndef _MTRCI3_H_ +#define _MTRCI3_H_ + +/*---------------------------------------------------------------------------- + * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS) + * + *---------------------------------------------------------------------------- + */ + +/*----------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *----------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS, STRUCTURES, ENUMS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * FUNCTIONS PROTOTYPE + * + *---------------------------------------------------------------------------- + */ + +UINT8 +MemTGetCtlWord3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 CtrlWordNum, + IN UINT8 RawCard, + IN UINT8 ChipSel + ); + +VOID +MemTDramControlRegInit3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +#endif /* _MTRCI3_H_ */ + + diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtsdi3.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtsdi3.c new file mode 100644 index 0000000000..1c0f27db11 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtsdi3.c @@ -0,0 +1,530 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mtsdi3.c + * + * Technology Software DRAM Init for DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** +* +* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. +* +* AMD is granting you permission to use this software (the Materials) +* pursuant to the terms and conditions of your Software License Agreement +* with AMD. This header does *NOT* give you permission to use the Materials +* or any rights under AMD's intellectual property. Your use of any portion +* of these Materials shall constitute your acceptance of those terms and +* conditions. If you do not agree to the terms and conditions of the Software +* License Agreement, please do not use any portion of these Materials. +* +* CONFIDENTIALITY: The Materials and all other information, identified as +* confidential and provided to you by AMD shall be kept confidential in +* accordance with the terms and conditions of the Software License Agreement. +* +* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION +* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED +* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, +* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. +* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER +* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS +* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, +* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER +* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE +* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, +* THE ABOVE LIMITATION MAY NOT APPLY TO YOU. +* +* AMD does not assume any responsibility for any errors which may appear in +* the Materials or any other related information provided to you by AMD, or +* result from use of the Materials or any related information. +* +* You agree that you will not reverse engineer or decompile the Materials. +* +* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any +* further information, software, technical information, know-how, or show-how +* available to you. Additionally, AMD retains the right to modify the +* Materials at any time, without notice, and is not obligated to provide such +* modified Materials to you. +* +* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with +* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is +* subject to the restrictions as set forth in FAR 52.227-14 and +* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the +* Government constitutes acknowledgement of AMD's proprietary rights in them. +* +* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any +* direct product thereof will be exported directly or indirectly, into any +* country prohibited by the United States Export Administration Act and the +* regulations thereunder, without the required authorization from the U.S. +* government nor will be used for any purpose prohibited by the same. +* *************************************************************************** +* +*/ + + +/* + *---------------------------------------------------------------------------- + * MODULES USED + * + *---------------------------------------------------------------------------- + */ + + + +#include "AGESA.h" +#include "Ids.h" +#include "mm.h" +#include "mn.h" +#include "mu.h" +#include "mt.h" +#include "mt3.h" +#include "mtsdi3.h" +#include "mtrci3.h" +#include "merrhdl.h" +#include "Filecode.h" +CODE_GROUP (G1_PEICC) +RDATA_GROUP (G1_PEICC) +#define FILECODE PROC_MEM_TECH_DDR3_MTSDI3_FILECODE +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + + + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function initiates software DRAM init for both DCTs + * at the same time. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +BOOLEAN +MemTDramInitSw3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT8 Dct; + UINT8 ChipSel; + + MEM_DATA_STRUCT *MemPtr; + DIE_STRUCT *MCTPtr; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + MemPtr = NBPtr->MemPtr; + MCTPtr = NBPtr->MCTPtr; + + IDS_HDT_CONSOLE (MEM_STATUS, "\nStart Dram Init\n"); + // 3.Program F2x[1,0]7C[EnDramInit]=1 + IDS_HDT_CONSOLE (MEM_FLOW, "\tEnDramInit = 1 for both DCTs\n"); + NBPtr->BrdcstSet (NBPtr, BFEnDramInit, 1); + NBPtr->PollBitField (NBPtr, BFDctAccessDone, 1, PCI_ACCESS_TIMEOUT, TRUE); + + // 4.wait 200us + MemUWait10ns (20000, MemPtr); + + // 5.Program F2x[1, 0]7C[DeassertMemRstX] = 1. + NBPtr->BrdcstSet (NBPtr, BFDeassertMemRstX, 1); + + // 6.wait 500us + MemUWait10ns (50000, MemPtr); + + // Do Phy Fence training before sending MRS commands + if (!NBPtr->IsSupported[FenceTrnBeforeDramInit]) { + AGESA_TESTPOINT (TpProcMemPhyFenceTraining, &(NBPtr->MemPtr->StdHeader)); + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + NBPtr->SwitchDCT (NBPtr, Dct); + if (NBPtr->DCTPtr->Timings.DctMemSize != 0) { + IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct); + NBPtr->PhyFenceTraining (NBPtr); + } + } + } + + // 7.NOP or deselect & take CKE high + NBPtr->BrdcstSet (NBPtr, BFAssertCke, 1); + + // 8.wait 360ns + MemUWait10ns (36, MemPtr); + + // The following steps are performed once for each channel with unbuffered DIMMs + // and once for each chip select on registered DIMMs: + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + NBPtr->SwitchDCT (NBPtr, Dct); + if (NBPtr->DCTPtr->Timings.DctMemSize != 0) { + IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct); + + // Enable Dram Parity if appropriate. + NBPtr->FamilySpecificHook[EnableParityAfterMemRst] (NBPtr, NULL); + + // The following steps are performed with registered DIMMs only and + // must be done for each chip select pair: + if (MCTPtr->Status[SbRegistered]) { + MemTDramControlRegInit3 (TechPtr); + } + + // Initialize LRDIMM's register + TechPtr->TechnologySpecificHook[LrdimmControlRegInit] (TechPtr, NULL); + + for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel++) { + if ((NBPtr->DCTPtr->Timings.CsPresent & ((UINT16)1 << ChipSel)) != 0) { + IDS_HDT_CONSOLE (MEM_STATUS, "\t\tCS %d\n", ChipSel); + // if chip select present + if (!(TechPtr->TechnologySpecificHook[LrdimmSendAllMRCmds] (TechPtr, &ChipSel))) { + MemTSendAllMRCmds3 (TechPtr, ChipSel); + } + // NOTE: wait 512 clocks for DLL-relock + MemUWait10ns (50000, NBPtr->MemPtr); // wait 500us + if (!(MCTPtr->Status[SbRegistered] || MCTPtr->Status[SbLrdimms])) { + break; + } + } + } + + // 17.Send two ZQCL commands (to even then odd chip select) + NBPtr->sendZQCmd (NBPtr); + NBPtr->sendZQCmd (NBPtr); + } + } + + // 18.Program F2x[1,0]7C[EnDramInit]=0 + NBPtr->BrdcstSet (NBPtr, BFEnDramInit, 0); + NBPtr->PollBitField (NBPtr, BFDctAccessDone, 1, PCI_ACCESS_TIMEOUT, TRUE); + // + // For Unbuffered Dimms, Issue MRS for remaining CS without EnDramInit + // + NBPtr->FamilySpecificHook[SendMrsCmdsPerCs] (NBPtr, NBPtr); + + IDS_HDT_CONSOLE (MEM_FLOW, "End Dram Init\n\n"); + return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function calculates the EMRS1 value + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Wl - Indicates if WL mode should be enabled + * @param[in] TargetDIMM - DIMM target for WL + */ + +VOID +MemTEMRS13 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN BOOLEAN Wl, + IN UINT8 TargetDIMM + ) +{ + UINT16 MrsAddress; + UINT8 MaxDimmPerCH; + UINT8 ChipSel; + UINT8 Value8; + + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + MaxDimmPerCH = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, + NBPtr->MCTPtr->SocketId, + NBPtr->ChannelPtr->ChannelID); + ChipSel = (UINT8) (0x0FF & NBPtr->GetBitField (NBPtr, BFMrsChipSel)); + + // BA2=0,BA1=0,BA0=1 + NBPtr->SetBitField (NBPtr, BFMrsBank, 1); + + MrsAddress = 0; + + // program MrsAddress[5,1]=output driver impedance control (DIC): + // based on F2x[1,0]84[DrvImpCtrl] + if (!(NBPtr->IsSupported[CheckDrvImpCtrl])) { + Value8 = (UINT8)NBPtr->GetBitField (NBPtr, BFDrvImpCtrl); + if ((Value8 & ((UINT8) 1 << 1)) != 0) { + MrsAddress |= ((UINT16) 1 << 5); + } + if ((Value8 & ((UINT8) 1 << 0)) != 0) { + MrsAddress |= ((UINT16) 1 << 1); + } + } else { + MrsAddress |= ((UINT16) 1 << 1); + } + // program MrsAddress[9,6,2]=nominal termination resistance of ODT (RTT): + // Different CS may have different RTT. + // + Value8 = NBPtr->MemNGetDramTerm (NBPtr, ChipSel); + + // + // If Write Leveling this DIMM + // + if (Wl) { + if ((ChipSel / NBPtr->CsPerDelay) == TargetDIMM) { + // Program MrsAddress[7] = 1 for Write leveling enable + MrsAddress |= ((UINT16) 1 << 7); + if (ChipSel & 1) { + // Output buffer disabled, MrsAddress[7] (Qoff = 1) + MrsAddress |= ((UINT16) 1 << 12); + } + // Set Rtt_Nom = Rtt_Wr if there are 2 or more dimms + if ((NBPtr->ChannelPtr->DimmQrPresent != 0) || (NBPtr->ChannelPtr->Dimms >= 2)) { + Value8 = NBPtr->MemNGetDynDramTerm (NBPtr, ChipSel); + } else if (NBPtr->IsSupported[WlRttNomFor1of3Cfg] && (MaxDimmPerCH == 3)) { + // For some family, set Rtt_Nom = Rtt_Wr in one of three DIMMs per channel configurations + Value8 = NBPtr->MemNGetDynDramTerm (NBPtr, ChipSel); + } + } + NBPtr->FamilySpecificHook[WLMR1] (NBPtr, &MrsAddress); + } + // + // Turn off Rtt_Nom (DramTerm=0) for certain CS in certain configs. + // + // All odd CS for 4 Dimm Systems + if (MaxDimmPerCH == 4) { + if (ChipSel & 0x01) { + Value8 = 0; + } + // CS 1 and 5 for 3 Dimm configs + } else if (MaxDimmPerCH == 3) { + if ((ChipSel == 1) || (ChipSel == 5)) { + Value8 = 0; + } + } + // All odd CS of any QR Dimms + if ((NBPtr->ChannelPtr->DimmQrPresent & ((UINT8) (1 << (ChipSel >> 1)))) != 0) { + if (ChipSel & 0x01) { + Value8 = 0; + } + } + if ((Value8 & ((UINT8) 1 << 2)) != 0) { + MrsAddress |= ((UINT16) 1 << 9); + } + if ((Value8 & ((UINT8) 1 << 1)) != 0) { + MrsAddress |= ((UINT16) 1 << 6); + } + if ((Value8 & ((UINT8) 1 << 0)) != 0) { + MrsAddress |= ((UINT16) 1 << 2); + } + + // program MrsAddress[12]=output disable (QOFF): + // based on F2x[1,0]84[Qoff] + + if (!NBPtr->IsSupported[CheckQoff]) { + if (NBPtr->GetBitField (NBPtr, BFQoff) != 0) { + MrsAddress |= ((UINT16) 1 << 12); + } + } + + // program MrsAddress[11]=TDQS: + // based on F2x[1,0]94[RDqsEn] + + if ((NBPtr->DCTPtr->Timings.Dimmx4Present != 0) && (NBPtr->DCTPtr->Timings.Dimmx8Present != 0)) { + if (!(NBPtr->IsSupported[SetTDqsForx8DimmOnly]) || ((NBPtr->DCTPtr->Timings.Dimmx8Present & ((UINT8) 1 << (ChipSel >> 1))) != 0)) { + MrsAddress |= ((UINT16) 1 << 11); + } + } + + NBPtr->SetBitField (NBPtr, BFMrsAddress, MrsAddress); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function calculates the EMRS2 value + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +VOID +MemTEMRS23 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT32 MrsAddress; + UINT8 DramTermDyn; + UINT8 MaxDimmPerCH; + UINT8 ChipSel; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + MaxDimmPerCH = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID ); + ChipSel = (UINT8) (0x0FF & NBPtr->GetBitField (NBPtr, BFMrsChipSel)); + + // BA2=0,BA1=1,BA0=0 + NBPtr->SetBitField (NBPtr, BFMrsBank, 2); + + // program MrsAddress[5:3]=CAS write latency (CWL): + MrsAddress = NBPtr->MemNGetMR2CWL (NBPtr); + + // program MrsAddress[6]=auto self refresh method (ASR): + // program MrsAddress[7]=self refresh temperature range (SRT): + MrsAddress |= 1 << 6; + MrsAddress &= ( ~ (1 << 7)); + + // program MrsAddress[10:9]=dynamic termination during writes (RTT_WR): + DramTermDyn = NBPtr->MemNGetDynDramTerm (NBPtr, ChipSel); + // Special Case for 1 DR Unbuffered Dimm in 3 Dimm/Ch + if (!(NBPtr->MCTPtr->Status[SbRegistered])) { + if (MaxDimmPerCH == 3) { + if (NBPtr->ChannelPtr->Dimms == 1) { + if ((NBPtr->ChannelPtr->DimmDrPresent & ((UINT8) (1 << (ChipSel >> 1)))) != 0) { + DramTermDyn = 1; + } + } + } + } + MrsAddress |= (UINT16) DramTermDyn << 9; + + NBPtr->SetBitField (NBPtr, BFMrsAddress, MrsAddress); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function calculates the EMRS3 value + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +VOID +MemTEMRS33 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + // BA2=0,BA1=1,BA0=1 + NBPtr->SetBitField (NBPtr, BFMrsBank, 3); + + // program MrsAddress[1:0]=multi purpose register address location + // (MPR Location):based on F2x[1,0]84[MprLoc] + // program MrsAddress[2]=multi purpose register + // (MPR):based on F2x[1,0]84[MprEn] + NBPtr->SetBitField (NBPtr, BFMrsAddress, (NBPtr->GetBitField (NBPtr, BFDramMRSReg) >> 24) & 0x0007); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This sets MRS value + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + */ + +VOID +MemTMRS3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT32 MrsAddress; + MEM_NB_BLOCK *NBPtr; + UINT32 Ppd; + + NBPtr = TechPtr->NBPtr; + + // BA2=0,BA1=0,BA0=0 + NBPtr->SetBitField (NBPtr, BFMrsBank, 0); + + // program MrsAddress[1:0]=burst length and control method + // (BL):based on F2x[1,0]84[BurstCtrl] + MrsAddress = NBPtr->GetBitField (NBPtr, BFBurstCtrl); + + // program MrsAddress[3]=1 (BT):interleaved + MrsAddress |= (UINT16) 1 << 3; + + // program MrsAddress[6:4,2]=read CAS latency + MrsAddress |= NBPtr->MemNGetMR0CL (NBPtr); + + // program MrsAddress[11:9]=write recovery for auto-precharge + MrsAddress |= NBPtr->MemNGetMR0WR (NBPtr); + + // program MrsAddress[12] (PPD):based on F2x[1,0]84[PChgPDModeSel] + Ppd = NBPtr->GetBitField (NBPtr, BFPchgPDModeSel); + NBPtr->FamilySpecificHook[MR0_PPD] (NBPtr, &Ppd); + IDS_OPTION_HOOK (IDS_MEM_MR0, &Ppd, &TechPtr->NBPtr->MemPtr->StdHeader); + MrsAddress |= Ppd << 12; + + // program MrsAddress[8]=1 (DLL):DLL reset + MrsAddress |= (UINT32) 1 << 8; + + // During memory initialization, the value sent to MR0 is saved for S3 resume + NBPtr->MemNSaveMR0 (NBPtr, MrsAddress); + + NBPtr->SetBitField (NBPtr, BFMrsAddress, MrsAddress); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This send all MR commands to a rank in sequence 2-3-1-0 + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] ChipSel - Target Chip Select + */ + +VOID +MemTSendAllMRCmds3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 ChipSel + ) +{ + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + + NBPtr->SetBitField (NBPtr, BFMrsChipSel, ChipSel); + + // 13.Send EMRS(2) + MemTEMRS23 (TechPtr); + AGESA_TESTPOINT (TpProcMemSendMRS2, &(NBPtr->MemPtr->StdHeader)); + NBPtr->SendMrsCmd (NBPtr); + + // 14.Send EMRS(3). Ordinarily at this time, MrsAddress[2:0]=000b + MemTEMRS33 (TechPtr); + AGESA_TESTPOINT (TpProcMemSendMRS3, &(NBPtr->MemPtr->StdHeader)); + NBPtr->SendMrsCmd (NBPtr); + + // 15.Send EMRS(1). + MemTEMRS13 (TechPtr, FALSE, (ChipSel >> 1)); + AGESA_TESTPOINT (TpProcMemSendMRS1, &(NBPtr->MemPtr->StdHeader)); + NBPtr->SendMrsCmd (NBPtr); + + // 16.Send MRS with MrsAddress[8]=1(reset the DLL) + MemTMRS3 (TechPtr); + AGESA_TESTPOINT (TpProcMemSendMRS0, &(NBPtr->MemPtr->StdHeader)); + NBPtr->SendMrsCmd (NBPtr); +} diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtsdi3.h b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtsdi3.h new file mode 100644 index 0000000000..5d2e11f539 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtsdi3.h @@ -0,0 +1,123 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mtsdi3.h + * + * Technology software DRAM init for DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** + * + * Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. + * + * AMD is granting you permission to use this software (the Materials) + * pursuant to the terms and conditions of your Software License Agreement + * with AMD. This header does *NOT* give you permission to use the Materials + * or any rights under AMD's intellectual property. Your use of any portion + * of these Materials shall constitute your acceptance of those terms and + * conditions. If you do not agree to the terms and conditions of the Software + * License Agreement, please do not use any portion of these Materials. + * + * CONFIDENTIALITY: The Materials and all other information, identified as + * confidential and provided to you by AMD shall be kept confidential in + * accordance with the terms and conditions of the Software License Agreement. + * + * LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION + * PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, + * OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. + * IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER + * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS + * INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, + * GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER + * RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE + * EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, + * THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + * + * AMD does not assume any responsibility for any errors which may appear in + * the Materials or any other related information provided to you by AMD, or + * result from use of the Materials or any related information. + * + * You agree that you will not reverse engineer or decompile the Materials. + * + * NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + * further information, software, technical information, know-how, or show-how + * available to you. Additionally, AMD retains the right to modify the + * Materials at any time, without notice, and is not obligated to provide such + * modified Materials to you. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with + * "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is + * subject to the restrictions as set forth in FAR 52.227-14 and + * DFAR252.227-7013, et seq., or its successor. Use of the Materials by the + * Government constitutes acknowledgement of AMD's proprietary rights in them. + * + * EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any + * direct product thereof will be exported directly or indirectly, into any + * country prohibited by the United States Export Administration Act and the + * regulations thereunder, without the required authorization from the U.S. + * government nor will be used for any purpose prohibited by the same. + * *************************************************************************** + * + */ + +#ifndef _MTSDI3_H_ +#define _MTSDI3_H_ + +/*---------------------------------------------------------------------------- + * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS) + * + *---------------------------------------------------------------------------- + */ + +/*----------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *----------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS, STRUCTURES, ENUMS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * FUNCTIONS PROTOTYPE + * + *---------------------------------------------------------------------------- + */ + +VOID +MemTEMRS33 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +VOID +MemTMRS3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +VOID +MemTEMRS13 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN BOOLEAN Wl, + IN UINT8 TargetDIMM + ); + +VOID +MemTEMRS23 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +#endif /* _MTSDI3_H_ */ + + diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtspd3.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtspd3.c new file mode 100644 index 0000000000..4b799770bc --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtspd3.c @@ -0,0 +1,1221 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mtspd3.c + * + * Technology SPD supporting functions for DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** +* +* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. +* +* AMD is granting you permission to use this software (the Materials) +* pursuant to the terms and conditions of your Software License Agreement +* with AMD. This header does *NOT* give you permission to use the Materials +* or any rights under AMD's intellectual property. Your use of any portion +* of these Materials shall constitute your acceptance of those terms and +* conditions. If you do not agree to the terms and conditions of the Software +* License Agreement, please do not use any portion of these Materials. +* +* CONFIDENTIALITY: The Materials and all other information, identified as +* confidential and provided to you by AMD shall be kept confidential in +* accordance with the terms and conditions of the Software License Agreement. +* +* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION +* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED +* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, +* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. +* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER +* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS +* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, +* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER +* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE +* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, +* THE ABOVE LIMITATION MAY NOT APPLY TO YOU. +* +* AMD does not assume any responsibility for any errors which may appear in +* the Materials or any other related information provided to you by AMD, or +* result from use of the Materials or any related information. +* +* You agree that you will not reverse engineer or decompile the Materials. +* +* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any +* further information, software, technical information, know-how, or show-how +* available to you. Additionally, AMD retains the right to modify the +* Materials at any time, without notice, and is not obligated to provide such +* modified Materials to you. +* +* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with +* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is +* subject to the restrictions as set forth in FAR 52.227-14 and +* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the +* Government constitutes acknowledgement of AMD's proprietary rights in them. +* +* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any +* direct product thereof will be exported directly or indirectly, into any +* country prohibited by the United States Export Administration Act and the +* regulations thereunder, without the required authorization from the U.S. +* government nor will be used for any purpose prohibited by the same. +* *************************************************************************** +* +*/ + +/* + *---------------------------------------------------------------------------- + * MODULES USED + * + *---------------------------------------------------------------------------- + */ + + + +#include "AGESA.h" +#include "AdvancedApi.h" +#include "Ids.h" +#include "mport.h" +#include "mm.h" +#include "mn.h" +#include "mt.h" +#include "mt3.h" +#include "mu.h" +#include "mtspd3.h" +#include "mftds.h" +#include "GeneralServices.h" +#include "Filecode.h" +CODE_GROUP (G1_PEICC) +RDATA_GROUP (G1_PEICC) + +#define FILECODE PROC_MEM_TECH_DDR3_MTSPD3_FILECODE + +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ +BOOLEAN +STATIC +MemTCRCCheck3 ( + IN OUT UINT8 *SPDPtr + ); + +UINT8 +STATIC +MemTSPDGetTCL3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ); + +BOOLEAN +STATIC +MemTCheckBankAddr3 ( + IN UINT8 Encode, + OUT UINT8 *Index + ); + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +extern BUILD_OPT_CFG UserOptions; + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function sets the DRAM mode + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - indicates that the DRAM mode is set to DDR3 + */ + +BOOLEAN +MemTSetDramMode3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + TechPtr->NBPtr->SetBitField (TechPtr->NBPtr, BFLegacyBiosMode, 0); + TechPtr->NBPtr->SetBitField (TechPtr->NBPtr, BFDdr3Mode, 1); + return TRUE; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function determines if DIMMs are present. It checks checksum and interrogates the SPDs + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - indicates that a FATAL error has not occurred + * @return FALSE - indicates that a FATAL error has occurred + */ + +BOOLEAN +MemTDIMMPresence3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT8 Dct; + UINT8 Channel; + UINT8 i; + MEM_PARAMETER_STRUCT *RefPtr; + UINT8 *SpdBufferPtr; + DIE_STRUCT *MCTPtr; + DCT_STRUCT *DCTPtr; + CH_DEF_STRUCT *ChannelPtr; + MEM_NB_BLOCK *NBPtr; + BOOLEAN SPDCtrl; + UINT8 Devwidth; + UINT8 MaxDimms; + UINT8 NumDimmslots; + UINT8 Value8; + UINT16 DimmMask; + UINT32 DimmValidMask; + + NBPtr = TechPtr->NBPtr; + RefPtr = NBPtr->RefPtr; + MCTPtr = NBPtr->MCTPtr; + + SPDCtrl = UserOptions.CfgIgnoreSpdChecksum; + DimmValidMask = 0; + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + NBPtr->SwitchDCT (NBPtr, Dct); + DCTPtr = NBPtr->DCTPtr; + for (Channel = 0; Channel < NBPtr->ChannelCount; Channel++) { + NBPtr->SwitchChannel (NBPtr, Channel); + ChannelPtr = NBPtr->ChannelPtr; + ChannelPtr->DimmQrPresent = 0; + // + // Get the maximum number of DIMMs + // + MaxDimms = MAX_DIMMS_PER_CHANNEL; + NumDimmslots = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, + MCTPtr->SocketId, + ChannelPtr->ChannelID); + DimmValidMask |= (NumDimmslots == 3) ? 0x7 : 0x3; + + for (i = 0; i < MaxDimms; i++) { + // Bitmask representing dimm #i. + DimmMask = (UINT16)1 << i; + // + if (MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, i)) { + MCTPtr->DimmPresent |= DimmMask; + // + // Check for valid checksum value + // + AGESA_TESTPOINT (TpProcMemSPDChecking, &(NBPtr->MemPtr->StdHeader)); + if (SpdBufferPtr[SPD_TYPE] == JED_DDR3SDRAM) { + ChannelPtr->ChDimmValid |= DimmMask; + MCTPtr->DimmValid |= DimmMask; + } else if (NBPtr->IsSupported[excel847_0 ]) { + return FALSE; + } else { + // Current socket is set up to only support DDR3 dimms. + IDS_ERROR_TRAP; + } + if (!MemTCRCCheck3 (SpdBufferPtr) && !SPDCtrl) { + // + // NV_SPDCHK_RESTRT is set to 0, + // cannot ignore faulty SPD checksum + // + // Indicate checksum error + ChannelPtr->DimmSpdCse |= DimmMask; + PutEventLog (AGESA_ERROR, MEM_ERROR_CHECKSUM_NV_SPDCHK_RESTRT_ERROR, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); + SetMemError (AGESA_ERROR, MCTPtr); + } + // + // Check module type information. + // + if (SpdBufferPtr[SPD_DIMM_TYPE] == JED_LRDIMM) { + // + // LRDIMMS + // + if (i < NumDimmslots) { + ChannelPtr->LrDimmPresent |= DimmMask; + MCTPtr->LrDimmPresent |= DimmMask; + + if (!UserOptions.CfgMemoryLRDimmCapable) { + PutEventLog (AGESA_WARNING, MEM_WARNING_UNSUPPORTED_LRDIMM, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); + IDS_ERROR_TRAP; + } + TechPtr->TechnologySpecificHook[LrdimmPresence] (TechPtr, &i); + } + } + if (SpdBufferPtr[SPD_DIMM_TYPE] == JED_RDIMM || SpdBufferPtr[SPD_DIMM_TYPE] == JED_MINIRDIMM) { + // + // RDIMMS + // + ChannelPtr->RegDimmPresent |= DimmMask; + MCTPtr->RegDimmPresent |= DimmMask; + if (!UserOptions.CfgMemoryRDimmCapable) { + PutEventLog (AGESA_WARNING, MEM_WARNING_UNSUPPORTED_RDIMM, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); + IDS_ERROR_TRAP; + } + } + if ((SpdBufferPtr[SPD_DIMM_TYPE] == JED_UDIMM) && !UserOptions.CfgMemoryUDimmCapable) { + PutEventLog (AGESA_WARNING, MEM_WARNING_UNSUPPORTED_UDIMM, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); + IDS_ERROR_TRAP; + } + if (SpdBufferPtr[SPD_DIMM_TYPE] == JED_SODIMM) { + ChannelPtr->SODimmPresent |= DimmMask; + if (!UserOptions.CfgMemorySODimmCapable) { + PutEventLog (AGESA_WARNING, MEM_WARNING_UNSUPPORTED_SODIMM, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); + IDS_ERROR_TRAP; + } + } + // + // Check error correction type + // + if ((SpdBufferPtr[SPD_ECCBITS] & JED_ECC) != 0) { + MCTPtr->DimmEccPresent |= DimmMask; // Dimm has ECC + } + // + // Get the Dimm width data + // + Devwidth = SpdBufferPtr[SPD_DEV_WIDTH] & 0x7; + switch (Devwidth) { + case 0: + ChannelPtr->Dimmx4Present |= DimmMask; + if ((ChannelPtr->LrDimmPresent & DimmMask) == 0) { + // + // DimmNibbleAccess indicates that a DIMM will use nibble signaling and use nibble training. + // LRDIMMs will not use Nibble based signaling even if x4 parts are present. + // + if (i < NumDimmslots) { + ChannelPtr->DimmNibbleAccess |= DimmMask; + } + } + Devwidth = 4; + break; + case 1: + ChannelPtr->Dimmx8Present |= DimmMask; + Devwidth = 8; + break; + case 2: + ChannelPtr->Dimmx16Present |= DimmMask; + Devwidth = 16; + break; + default: + IDS_ERROR_TRAP; + } + // + // Check for 'analysis probe installed' + // if (SpdBufferPtr[SPD_ATTRIB] & JED_PROBE_MSK) + // + // Determine the geometry of the DIMM module + // if (SpdBufferPtr[SPD_DM_BANKS] & SP_DPL_BIT) + // + // specify the number of ranks + // + Value8 = ((SpdBufferPtr[SPD_RANKS] >> 3) & 0x07) + 1; + if (Value8 == 5) { + // Octal Rank + Value8 = 8; + } + // + // For LRDIMMS we will assume that if there are at least 4 Physical ranks, then it Could be used + // as a QR RDIMM with a rank Mux of x1 and therefore all four CS will be used. So an 8R LRDIMM will + // be marked as a QR even if Rank multiplication allows it to use only 2 logical ranks. + // + if ((ChannelPtr->LrDimmPresent & DimmMask) != 0) { + // + // LRDIMM Physical Ranks + // + ChannelPtr->LrdimmPhysicalRanks[i] = Value8; + } + if (Value8 > 2) { + if (!UserOptions.CfgMemoryQuadRankCapable) { + PutEventLog (AGESA_WARNING, MEM_WARNING_UNSUPPORTED_QRDIMM, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); + } + // + // Mark this Dimm as Quad Rank + // + ChannelPtr->DimmQrPresent |= DimmMask; + Value8 = 2; + } else if (Value8 == 2) { + ChannelPtr->DimmDrPresent |= DimmMask; // Dual rank dimms + } else { + ChannelPtr->DimmSRPresent |= DimmMask; // Single rank dimms + } + // + // Calculate bus loading per Channel + if (Devwidth == 16) { + Devwidth = 4; + } else if (Devwidth == 4) { + Devwidth = 16; + } + // + // Double Addr bus load value for dual rank DIMMs (Unless LRDIMM) + // + if (((ChannelPtr->LrDimmPresent & DimmMask) == 0) && (Value8 == 2) ) { + Devwidth = Devwidth << 1; + } + // + ChannelPtr->Ranks = ChannelPtr->Ranks + Value8; + ChannelPtr->Loads = ChannelPtr->Loads + Devwidth; + if ((i < NumDimmslots) || ((ChannelPtr->DimmQrPresent & DimmMask) == 0)) { + ChannelPtr->Dimms++; + } + // + // Check address mirror support for Unbuffered Dimms or LRDimms + // + if ((ChannelPtr->RegDimmPresent & DimmMask) == 0) { + if ((SpdBufferPtr[SPD_ADDRMAP] & 1) != 0) { + ChannelPtr->DimmMirrorPresent |= DimmMask; + } + } + // + // Get byte62: Reference Raw Card information + // + ChannelPtr->RefRawCard[i] = SpdBufferPtr[SPD_RAWCARD] & 0x1F; + // + // Get control word values for RC3, RC4 and RC5 + // + ChannelPtr->CtrlWrd03[i] = SpdBufferPtr[SPD_CTLWRD03] >> 4; + ChannelPtr->CtrlWrd04[i] = SpdBufferPtr[SPD_CTLWRD04] & 0x0F; + ChannelPtr->CtrlWrd05[i] = SpdBufferPtr[SPD_CTLWRD05] >> 4; + // + // Temporarily store info. of SPD byte 63 into CtrlWrd02(s), + // and they will be used late to calculate real RC2 and RC8 value + // + ChannelPtr->CtrlWrd02[i] = SpdBufferPtr[SPD_ADDRMAP] & 0x03; + // + // Copy the number of registers to the Ps Block to persist across frequency changes + // + NBPtr->PsPtr->NumOfReg[i] = SpdBufferPtr[SPD_ADDRMAP] & 0x03; + // + // Workaround for early revisions of DIMMs which SPD byte 63 is 0 + // + if (NBPtr->PsPtr->NumOfReg[i] == JED_UNDEFINED) { + NBPtr->PsPtr->NumOfReg[i] = 1; + } + } // if DIMM present + } // Dimm loop + + if (Channel == 0) { + DCTPtr->Timings.DctDimmValid = ChannelPtr->ChDimmValid; + DCTPtr->Timings.DimmMirrorPresent = ChannelPtr->DimmMirrorPresent; + DCTPtr->Timings.DimmSpdCse = ChannelPtr->DimmSpdCse; + DCTPtr->Timings.DimmQrPresent = ChannelPtr->DimmQrPresent; + DCTPtr->Timings.DimmDrPresent = ChannelPtr->DimmDrPresent; + DCTPtr->Timings.DimmSRPresent = ChannelPtr->DimmSRPresent; + DCTPtr->Timings.Dimmx4Present = ChannelPtr->Dimmx4Present; + DCTPtr->Timings.Dimmx8Present = ChannelPtr->Dimmx8Present; + DCTPtr->Timings.Dimmx16Present = ChannelPtr->Dimmx16Present; + } + if ((Channel != 1) || (Dct != 1)) { + MCTPtr->DimmPresent <<= 8; + MCTPtr->DimmValid <<= 8; + MCTPtr->RegDimmPresent <<= 8; + MCTPtr->LrDimmPresent <<= 8; + MCTPtr->DimmEccPresent <<= 8; + MCTPtr->DimmParPresent <<= 8; + DimmValidMask <<= 8; + } + } // Channel loop + } // DCT loop + + // If we have DIMMs, some further general characteristics checking + if (MCTPtr->DimmValid != 0) { + // If there are registered dimms, all the dimms must be registered + if (MCTPtr->RegDimmPresent == MCTPtr->DimmValid) { + // All dimms registered + MCTPtr->Status[SbRegistered] = TRUE; + MCTPtr->Status[SbParDimms] = TRUE; // All DDR3 RDIMMs are parity capable + TechPtr->SetDqsEccTmgs = MemTSetDQSEccTmgsRDdr3; // Change the function pointer for DQS ECC timing + } else if (MCTPtr->RegDimmPresent != 0) { + // We have an illegal DIMM mismatch + PutEventLog (AGESA_FATAL, MEM_ERROR_MODULE_TYPE_MISMATCH_DIMM, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); + SetMemError (AGESA_FATAL, MCTPtr); + } + // If there are LrDimms, all the dimms must be LrDimms + if (MCTPtr->LrDimmPresent == (MCTPtr->DimmValid & DimmValidMask)) { + // All dimms LRDIMMs + MCTPtr->Status[SbLrdimms] = TRUE; + MCTPtr->Status[SbParDimms] = TRUE; // All DDR3 RDIMMs are parity capable + } else if (MCTPtr->LrDimmPresent != 0) { + // We have an illegal DIMM mismatch + PutEventLog (AGESA_FATAL, MEM_ERROR_MODULE_TYPE_MISMATCH_DIMM, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); + SetMemError (AGESA_FATAL, MCTPtr); + } + + // check the ECC capability of the DIMMs + if (MCTPtr->DimmEccPresent == MCTPtr->DimmValid) { + MCTPtr->Status[SbEccDimms] = TRUE; // All dimms ECC capable + } + } else { + } + + NBPtr->SwitchDCT (NBPtr, 0); + NBPtr->SwitchChannel (NBPtr, 0); + return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL); +} + + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function finds the maximum frequency that each channel is capable to run at. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - indicates that a FATAL error has not occurred + * @return FALSE - indicates that a FATAL error has occurred + */ + +BOOLEAN +MemTSPDGetTargetSpeed3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT8 *SpdBufferPtr; + UINT8 Dimm; + UINT8 Dct; + UINT8 Channel; + INT32 MTB_ps; + INT32 FTB_ps; + INT32 TCKmin_ps; + INT32 Value32; + MEM_NB_BLOCK *NBPtr; + DCT_STRUCT *DCTPtr; + CH_DEF_STRUCT *ChannelPtr; + + NBPtr = TechPtr->NBPtr; + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + NBPtr->SwitchDCT (NBPtr, Dct); + DCTPtr = NBPtr->DCTPtr; + TCKmin_ps = 0; + for (Channel = 0; Channel < NBPtr->ChannelCount; Channel++) { + NBPtr->SwitchChannel (NBPtr, Channel); + ChannelPtr = NBPtr->ChannelPtr; + for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) { + if ((ChannelPtr->ChDimmValid & ((UINT8)1 << Dimm)) != 0) { + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, Dimm); + + // Determine tCKmin(all) which is the largest tCKmin + // value for all modules on the memory Channel (SPD byte 12). + // + MTB_ps = ((INT32) SpdBufferPtr[SPD_DIVIDENT] * 1000) / SpdBufferPtr[SPD_DIVISOR]; + FTB_ps = (SpdBufferPtr[SPD_FTB] >> 4) / (SpdBufferPtr[SPD_FTB] & 0xF); + Value32 = (MTB_ps * SpdBufferPtr[SPD_TCK]) + (FTB_ps * (INT8) SpdBufferPtr[SPD_TCK_FTB]) ; + if (TCKmin_ps < Value32) { + TCKmin_ps = Value32; + } + } + } + } + if (TCKmin_ps <= 938) { + DCTPtr->Timings.TargetSpeed = DDR2133_FREQUENCY; + } else if (TCKmin_ps <= 1071) { + DCTPtr->Timings.TargetSpeed = DDR1866_FREQUENCY; + } else if (TCKmin_ps <= 1250) { + DCTPtr->Timings.TargetSpeed = DDR1600_FREQUENCY; + } else if (TCKmin_ps <= 1500) { + DCTPtr->Timings.TargetSpeed = DDR1333_FREQUENCY; + } else if (TCKmin_ps <= 1875) { + DCTPtr->Timings.TargetSpeed = DDR1066_FREQUENCY; + } else if (TCKmin_ps <= 2500) { + DCTPtr->Timings.TargetSpeed = DDR800_FREQUENCY; + } else { + DCTPtr->Timings.TargetSpeed = DDR667_FREQUENCY; + } + } + + // Ensure the target speed can be applied to all channels of the current node + NBPtr->SyncTargetSpeed (NBPtr); + + // Set the start-up frequency + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + NBPtr->SwitchDCT (NBPtr, Dct); + NBPtr->DCTPtr->Timings.Speed = TechPtr->NBPtr->StartupSpeed; + } + return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function check the symmetry of DIMM pairs (DIMM on Channel A matching with + * DIMM on Channel B), the overall DIMM population, and determine the width mode: + * 64-bit, 64-bit muxed, 128-bit. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - indicates that a FATAL error has not occurred + * @return FALSE - indicates that a FATAL error has occurred + */ + +BOOLEAN +MemTSPDCalcWidth3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT8 *SpdBufferAPtr; + UINT8 *SpdBufferBPtr; + MEM_NB_BLOCK *NBPtr; + DIE_STRUCT *MCTPtr; + DCT_STRUCT *DCTPtr; + UINT8 i; + UINT16 DimmMask; + UINT8 UngangMode; + + NBPtr = TechPtr->NBPtr; + MCTPtr = NBPtr->MCTPtr; + DCTPtr = NBPtr->DCTPtr; + UngangMode = UserOptions.CfgMemoryModeUnganged; + // Does not support ganged mode for DDR3 dimms + ASSERT (UngangMode); + IDS_OPTION_HOOK (IDS_GANGING_MODE, &UngangMode, &(NBPtr->MemPtr->StdHeader)); + + // Check symmetry of channel A and channel B dimms for 128-bit mode + // capability. + // + AGESA_TESTPOINT (TpProcMemModeChecking, &(NBPtr->MemPtr->StdHeader)); + i = 0; + if (!UngangMode) { + if (MCTPtr->DctData[0].Timings.DctDimmValid == MCTPtr->DctData[1].Timings.DctDimmValid) { + for (; i < MAX_DIMMS_PER_CHANNEL; i++) { + DimmMask = (UINT16)1 << i; + if ((DCTPtr->Timings.DctDimmValid & DimmMask) != 0) { + NBPtr->SwitchDCT (NBPtr, 0); + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferAPtr, i); + NBPtr->SwitchDCT (NBPtr, 1); + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferBPtr, i); + // compare rows and columns + if ((SpdBufferAPtr[SPD_ROW_SZ]&0x3F) != (SpdBufferBPtr[SPD_ROW_SZ]&0x3F)) { + break; + } + if ((SpdBufferAPtr[SPD_DENSITY]&0x0F) != (SpdBufferBPtr[SPD_DENSITY]&0x0F)) { + break; + } + // compare ranks and devwidth + if ((SpdBufferAPtr[SPD_DEV_WIDTH]&0x7F) != (SpdBufferBPtr[SPD_DEV_WIDTH]&0x7F)) { + break; + } + } + } + } + if (i < MAX_DIMMS_PER_CHANNEL) { + PutEventLog (AGESA_ALERT, MEM_ALERT_ORG_MISMATCH_DIMM, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); + SetMemError (AGESA_ALERT, MCTPtr); + } else { + NBPtr->Ganged = TRUE; + MCTPtr->GangedMode = TRUE; + MCTPtr->Status[Sb128bitmode] = TRUE; + NBPtr->SetBitField (NBPtr, BFDctGangEn, 1); + } + } + + return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL); +} + + +/* -----------------------------------------------------------------------------*/ +/** + * + * Initialize DCT Timing registers as per DIMM SPD. + * For primary timing (T, CL) use best case T value. + * For secondary timing params., use most aggressive settings + * of slowest DIMM. + * + * Note: + * There are three components to determining "maximum frequency": SPD component, + * Bus load component, and "Preset" max frequency component. + * The SPD component is a function of the min cycle time specified by each DIMM, + * and the interaction of cycle times from all DIMMs in conjunction with CAS + * latency. The SPD component only applies when user timing mode is 'Auto'. + * + * The Bus load component is a limiting factor determined by electrical + * characteristics on the bus as a result of varying number of device loads. The + * Bus load component is specific to each platform but may also be a function of + * other factors. The bus load component only applies when user timing mode is + * ' Auto'. + * + * The Preset component is subdivided into three items and is the minimum of + * the set: Silicon revision, user limit setting when user timing mode is 'Auto' and + * memclock mode is 'Limit', OEM build specification of the maximum frequency. + * The Preset component only applies when user timing mode is 'Auto'. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - indicates that a FATAL error has not occurred + * @return FALSE - indicates that a FATAL error has occurred + */ + +BOOLEAN +MemTAutoCycTiming3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + CONST UINT8 SpdIndexes[] = { + SPD_TRCD, + SPD_TRP, + SPD_TRTP, + SPD_TRAS, + SPD_TRC, + SPD_TWR, + SPD_TRRD, + SPD_TWTR, + SPD_TFAW + }; + + CONST UINT8 SpdFTBIndexes[] = { + SPD_TRCD_FTB, + SPD_TRP_FTB, + 0, + 0, + SPD_TRC_FTB, + 0, + 0, + 0, + 0 + }; + + UINT8 *SpdBufferPtr; + INT32 MiniMaxTmg[GET_SIZE_OF (SpdIndexes)]; + UINT8 MiniMaxTrfc[4]; + + DIE_STRUCT *MCTPtr; + DCT_STRUCT *DCTPtr; + MEM_NB_BLOCK *NBPtr; + UINT16 DimmMask; + INT32 Value32; + INT32 MTB_ps; + INT32 FTB_ps; + INT32 TCK_ps; + UINT8 i; + UINT8 j; + UINT8 Value8; + UINT8 *StatTmgPtr; + UINT16 *StatDimmTmgPtr; + + NBPtr = TechPtr->NBPtr; + MCTPtr = NBPtr->MCTPtr; + DCTPtr = NBPtr->DCTPtr; + // initialize mini-max arrays + for (j = 0; j < GET_SIZE_OF (MiniMaxTmg); j++) { + MiniMaxTmg[j] = 0; + } + for (j = 0; j < GET_SIZE_OF (MiniMaxTrfc); j++) { + MiniMaxTrfc[j] = 0; + } + + // ====================================================================== + // Get primary timing (CAS Latency and Cycle Time) + // ====================================================================== + // Get OEM specific load variant max + // + + //====================================================================== + // Gather all DIMM mini-max values for cycle timing data + //====================================================================== + // + DimmMask = 1; + for (i = 0; i < (MAX_CS_PER_CHANNEL / 2); i++) { + if ((DCTPtr->Timings.DctDimmValid & DimmMask) != 0) { + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, i); + MTB_ps = ((INT32) SpdBufferPtr[SPD_DIVIDENT] * 1000) / SpdBufferPtr[SPD_DIVISOR]; + FTB_ps = (SpdBufferPtr[SPD_FTB] >> 4) / (SpdBufferPtr[SPD_FTB] & 0xF); + + for (j = 0; j < GET_SIZE_OF (SpdIndexes); j++) { + Value32 = (UINT16)SpdBufferPtr[SpdIndexes[j]]; + if (SpdIndexes[j] == SPD_TRC) { + Value32 |= ((UINT16)SpdBufferPtr[SPD_UPPER_TRC] & 0xF0) << 4; + } else if (SpdIndexes[j] == SPD_TRAS) { + Value32 |= ((UINT16)SpdBufferPtr[SPD_UPPER_TRAS] & 0x0F) << 8; + } else if (SpdIndexes[j] == SPD_TFAW) { + Value32 |= ((UINT16)SpdBufferPtr[SPD_UPPER_TFAW] & 0x0F) << 8; + } + + Value32 *= MTB_ps; + if (SpdFTBIndexes[j] != 0) { + Value32 += (FTB_ps * (INT8) SpdBufferPtr[SpdFTBIndexes[j]]) ; + } + if (MiniMaxTmg[j] < Value32) { + MiniMaxTmg[j] = Value32; + } + } + + // get Trfc0 - Trfc3 values + Value8 = SpdBufferPtr[SPD_DENSITY] & 0x0F; + if (MiniMaxTrfc[i] < Value8) { + MiniMaxTrfc[i] = Value8; + } + } + DimmMask <<= 1; + } + + // ====================================================================== + // Convert DRAM CycleTiming values and store into DCT structure + // ====================================================================== + // + TCK_ps = 1000500 / DCTPtr->Timings.Speed; + + StatDimmTmgPtr = &DCTPtr->Timings.DIMMTrcd; + StatTmgPtr = &DCTPtr->Timings.Trcd; + for (j = 0; j < GET_SIZE_OF (SpdIndexes); j++) { + Value32 = MiniMaxTmg[j]; + + MiniMaxTmg[j] = (MiniMaxTmg[j] + TCK_ps - 1) / TCK_ps; + + StatDimmTmgPtr[j] = (UINT16) (Value32 / (1000 / 40)); + StatTmgPtr[j] = (UINT8) MiniMaxTmg[j]; + } + DCTPtr->Timings.Trfc0 = MiniMaxTrfc[0]; + DCTPtr->Timings.Trfc1 = MiniMaxTrfc[1]; + DCTPtr->Timings.Trfc2 = MiniMaxTrfc[2]; + DCTPtr->Timings.Trfc3 = MiniMaxTrfc[3]; + + DCTPtr->Timings.CasL = MemTSPDGetTCL3 (TechPtr); + + //====================================================================== + // Program DRAM Timing values + //====================================================================== + // + NBPtr->ProgramCycTimings (NBPtr); + + MemFInitTableDrive (NBPtr, MTAfterAutoCycTiming); + + return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function sets the bank addressing, program Mask values and build a chip-select population map. + * This routine programs PCI 0:24N:2x80 config register. + * This routine programs PCI 0:24N:2x60,64,68,6C config registers (CS Mask 0-3) + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - indicates that a FATAL error has not occurred + * @return FALSE - indicates that a FATAL error has occurred + */ + +BOOLEAN +MemTSPDSetBanks3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT8 *SpdBufferPtr; + UINT8 i; + UINT8 ChipSel; + UINT8 DimmID; + UINT8 Value8; + UINT8 Rows; + UINT8 Cols; + UINT8 Ranks; + UINT8 Banks; + UINT32 BankAddrReg; + UINT32 CsMask; + UINT16 CSSpdCSE; + UINT16 CSExclude; + UINT16 DimmQRDR; + DIE_STRUCT *MCTPtr; + DCT_STRUCT *DCTPtr; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + MCTPtr = NBPtr->MCTPtr; + DCTPtr = NBPtr->DCTPtr; + BankAddrReg = 0; + CSSpdCSE = 0; + CSExclude = 0; + + for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel += 2) { + DimmID = ChipSel >> 1; + + DimmQRDR = (DCTPtr->Timings.DimmQrPresent) | (DCTPtr->Timings.DimmDrPresent); + if ((DCTPtr->Timings.DimmSpdCse & ((UINT16) 1 << DimmID)) != 0) { + CSSpdCSE |= (UINT16) ((DimmQRDR & (UINT16) 1 << DimmID) ? 3 : 1) << ChipSel; + } + if ((DCTPtr->Timings.DimmExclude & ((UINT16) 1 << DimmID)) != 0) { + CSExclude |= (UINT16) ((DimmQRDR & (UINT16) 1 << DimmID) ? 3: 1) << ChipSel; + } + + if ((DCTPtr->Timings.DctDimmValid & ((UINT16)1 << DimmID)) != 0) { + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, DimmID); + + // Get the basic data + Rows = (SpdBufferPtr[SPD_ROW_SZ] >> 3) & 0x7; + Cols = SpdBufferPtr[SPD_COL_SZ] & 0x7; + Banks = (SpdBufferPtr[SPD_L_BANKS] >> 4) & 0x7; + Ranks = ((SpdBufferPtr[SPD_RANKS] >> 3) & 0x07) + 1; + if (Ranks == 5) { + Ranks = 8; + } + // + // Configure the bank encoding + // Use a 6-bit key into a lookup table. + // Key (index) = RRRBCC, where CC is the number of Columns minus 9, + // RRR is the number of Rows minus 12, and B is the number of banks + // minus 3. + // + Value8 = Cols; + Value8 |= (Banks == 1) ? 4 : 0; + Value8 |= Rows << 3; + + if (MemTCheckBankAddr3 (Value8, &i)) { + // + // Mask value=(2pow(rows+cols+banks+3)-1)>>8, + // or 2pow(rows+cols+banks-5)-1 + // + Value8 = (Rows + 12) + (Cols + 9) + (Banks + 3) + 3 - 8; + if (MCTPtr->Status[Sb128bitmode]) { + Value8++; + } + + DCTPtr->Timings.CsPresent |= (UINT16)1 << ChipSel; + + if (Ranks >= 2) { + DCTPtr->Timings.CsPresent |= (UINT16)1 << (ChipSel + 1); + } + // + // Determine LRDIMM Rank Multiplication + // + if (TechPtr->TechnologySpecificHook[LrdimmRankMultiplication] (TechPtr, &DimmID)) { + // + // Increase the CS Size by the rank multiplication factor + // + Value8 += ((NBPtr->ChannelPtr->LrDimmRankMult[DimmID]) >> 1); + CsMask = ((UINT32)1 << Value8) - 1; + CsMask &= NBPtr->CsRegMsk; + CsMask |= (NBPtr->GetBitField (NBPtr, BFRankDef0 + DimmID) & 0x03); + } else { + CsMask = ((UINT32)1 << Value8) - 1; + CsMask &= NBPtr->CsRegMsk; + } + // + // Update the DRAM CS Mask and BankAddrReg for this chipselect + // + if ((DCTPtr->Timings.CsPresent & (UINT16)3 << ChipSel) != 0) { + NBPtr->SetBitField (NBPtr, BFCSMask0Reg + (ChipSel >> 1), (CsMask)); + BankAddrReg |= ((UINT32)i << (ChipSel << 1)); + } + } else { + // + // Dimm is not supported, as no address mapping is found. + // + DCTPtr->Timings.CsPresent |= (UINT16)1 << ChipSel; + DCTPtr->Timings.CsTestFail |= (UINT16)1 << ChipSel; + if (Ranks >= 2) { + DCTPtr->Timings.CsPresent |= (UINT16)1 << (ChipSel + 1); + DCTPtr->Timings.CsTestFail |= (UINT16)1 << (ChipSel + 1); + } + PutEventLog (AGESA_ERROR, MEM_ERROR_NO_ADDRESS_MAPPING, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, DimmID, &NBPtr->MemPtr->StdHeader); + SetMemError (AGESA_ERROR, MCTPtr); + } + } //if (MemTCheckBankAddr3 (Value8, &i) + } + // For ranks that need to be excluded, the loading of this rank should be considered + // in timing, so need to set CsPresent before setting CsTestFail + if ((CSSpdCSE != 0) || (CSExclude != 0)) { + if (!NBPtr->MemPtr->ErrorHandling (MCTPtr, NBPtr->Dct, (CSSpdCSE | CSExclude), &NBPtr->MemPtr->StdHeader)) { + ASSERT (FALSE); + } + } + + // If there are no chip selects, we have an error situation. + if (DCTPtr->Timings.CsPresent == 0) { + PutEventLog (AGESA_ERROR, MEM_ERROR_NO_CHIPSELECT, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader); + SetMemError (AGESA_ERROR, MCTPtr); + } + + NBPtr->SetBitField (NBPtr, BFDramBankAddrReg, BankAddrReg); + + return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function returns the low bit that will be swapped to enable CS interleaving + * + * @param[in] BankEnc - AddrMap Bank encoding from F2x80 + * @param[in] *LowBit - pointer to low bit + * @param[in] *HiBit - pointer hight bit + * + */ + +VOID +MemTGetCSIntLvAddr3 ( + IN UINT8 BankEnc, + OUT UINT8 *LowBit, + OUT UINT8 *HiBit + ) +{ + CONST UINT8 ArrCodesLo[] = {0, 8, 8, 0, 0, 8, 9, 8, 9, 9, 8, 9}; + CONST UINT8 ArrCodesHi[] = {0, 20, 21, 0, 0, 22, 22, 23, 23, 24, 24, 25}; + ASSERT (BankEnc < GET_SIZE_OF (ArrCodesLo)); + ASSERT (BankEnc < GET_SIZE_OF (ArrCodesHi)); + // return ArrCodes[BankEnc]; + *LowBit = ArrCodesLo[BankEnc]; + *HiBit = ArrCodesHi[BankEnc]; +} + +/*---------------------------------------------------------------------------- + * LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function determines if the checksum is correct + * + * @param[in] *SPDPtr - Pointer to SPD data + * + * @return TRUE - CRC check passes + * @return FALSE - CRC check fails + */ + +BOOLEAN +STATIC +MemTCRCCheck3 ( + IN OUT UINT8 *SPDPtr + ) +{ + UINT16 Crc; + INT16 i; + INT16 j; + INT16 Count; + + if (SPDPtr[SPD_TYPE] == JED_DDR3SDRAM) { + Count = (SPDPtr[SPD_BYTE_USED] & 0x80) ? 117 : 126; + Crc = 0; + for (j = 0; j < Count; j++) { + Crc = Crc ^ ((UINT16)SPDPtr[j] << 8); + for (i = 0; i < 8; i++) { + if (Crc & 0x8000) { + Crc = (Crc << 1) ^ 0x1021; + } else { + Crc = (Crc << 1); + } + } + } + if (*(UINT16 *) (SPDPtr + 126) == Crc) { + return TRUE; + } + } + + return FALSE; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function returns the CAS latency of the current frequency (DCTPtr->Timings.Speed). + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return CAS Latency + */ + +UINT8 +STATIC +MemTSPDGetTCL3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT8 *SpdBufferPtr; + UINT8 CLdesired; + UINT8 CLactual; + UINT8 Dimm; + UINT8 Channel; + UINT16 CASLat; + UINT16 Mask16; + INT32 MTB_ps; + INT32 FTB_ps; + INT32 TAAmin_ps; + INT32 TCKproposed_ps; + INT32 Value32; + BOOLEAN CltFail; + MEM_NB_BLOCK *NBPtr; + DCT_STRUCT *DCTPtr; + CH_DEF_STRUCT *ChannelPtr; + + NBPtr = TechPtr->NBPtr; + DCTPtr = NBPtr->DCTPtr; + + CASLat = 0xFFFF; + TAAmin_ps = 0; + CltFail = FALSE; + + for (Channel = 0; Channel < NBPtr->ChannelCount; Channel++) { + NBPtr->SwitchChannel (NBPtr, Channel); + ChannelPtr = NBPtr->ChannelPtr; + for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) { + if ((ChannelPtr->ChDimmValid & ((UINT8)1 << Dimm)) != 0) { + MemTGetDimmSpdBuffer3 (TechPtr, &SpdBufferPtr, Dimm); + + // Step 1: Determine the common set of supported CAS Latency + // values for all modules on the memory Channel using the CAS + // Latencies Supported in SPD bytes 14 and 15. + // + CASLat &= ((UINT16)SpdBufferPtr[SPD_CASHI] << 8) | SpdBufferPtr[SPD_CASLO]; + + // Step 2: Determine tAAmin(all) which is the largest tAAmin + // value for all modules on the memory Channel (SPD byte 16). + // + MTB_ps = ((INT32) SpdBufferPtr[SPD_DIVIDENT] * 1000) / SpdBufferPtr[SPD_DIVISOR]; + FTB_ps = (SpdBufferPtr[SPD_FTB] >> 4) / (SpdBufferPtr[SPD_FTB] & 0xF); + Value32 = (MTB_ps * SpdBufferPtr[SPD_TAA]) + (FTB_ps * (INT8) SpdBufferPtr[SPD_TAA_FTB]) ; + if (TAAmin_ps < Value32) { + TAAmin_ps = Value32; + } + + // Step 3: Determine tCKmin(all) which is the largest tCKmin + // value for all modules on the memory Channel (SPD byte 12). + // * This step has been done in SPDGetTargetSpeed + } + } + } + + TCKproposed_ps = 1000500 / DCTPtr->Timings.Speed; + + // Step 4: For a proposed tCK value (tCKproposed) between tCKmin(all) and tCKmax, + // determine the desired CAS Latency. If tCKproposed is not a standard JEDEC + // value (2.5, 1.875, 1.5, or 1.25 ns) then tCKproposed must be adjusted to the + // next lower standard tCK value for calculating CLdesired. + // CLdesired = ceiling ( tAAmin(all) / tCKproposed ) + // where tAAmin is defined in Byte 16. The ceiling function requires that the + // quotient be rounded up always. + // + CLdesired = (UINT8) ((TAAmin_ps + TCKproposed_ps - 1) / TCKproposed_ps); + + // Step 5: Choose an actual CAS Latency (CLactual) that is greater than or equal + // to CLdesired and is supported by all modules on the memory Channel as + // determined in step 1. If no such value exists, choose a higher tCKproposed + // value and repeat steps 4 and 5 until a solution is found. + // + CLactual = 4; + for (Mask16 = 1; Mask16 < 0x8000; Mask16 <<= 1) { + if (CASLat & Mask16) { + if (CLdesired <= CLactual) { + break; + } + } + CLactual++; + } + if (Mask16 == 0x8000) { + CltFail = TRUE; + } + + // Step 6: Once the calculation of CLactual is completed, the BIOS must also + // verify that this CAS Latency value does not exceed tAAmax, which is 20 ns + // for all DDR3 speed grades, by multiplying CLactual times tCKproposed. If + // not, choose a lower CL value and repeat steps 5 and 6 until a solution is found. + // + if ((TCKproposed_ps * CLactual) > 20000) { + CltFail = TRUE; + } + + if (!CltFail) { + DCTPtr->Timings.CasL = CLactual; + } else { + // Fail to find supported Tcl, use 6 clocks since it is required for all DDR3 speed bin. + DCTPtr->Timings.CasL = 6; + } + + return DCTPtr->Timings.CasL; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function returns the encoded value of bank address. + * + * @param[in] Encode - RRRBCC, where CC is the number of Columns minus 9, + * RRR is the number of Rows minus 12, and B is the number of banks + * minus 3. + * @param[out] *Index - index in bank address table + * @return TRUE - encoded value is found. + * FALSE - encoded value is not found. + */ + +BOOLEAN +STATIC +MemTCheckBankAddr3 ( + IN UINT8 Encode, + OUT UINT8 *Index + ) +{ + UINT8 i; + CONST UINT8 TabBankAddr[] = { + 0x3F, 0x01, 0x09, 0x3F, 0x3F, 0x11, + 0x0A, 0x19, 0x12, 0x1A, 0x21, 0x22 + }; + + for (i = 0; i < GET_SIZE_OF (TabBankAddr); i++) { + if (Encode == TabBankAddr[i]) { + *Index = i; + return TRUE; + } + } + return FALSE; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function returns a pointer to the SPD Buffer of a specific dimm on + * the current channel. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in,out] **SpdBuffer - Pointer to a pointer to a UINT8 Buffer + * @param[in] Dimm - Dimm number + * + * + * @return BOOLEAN - Value of DimmPresent + * TRUE = Dimm is present, pointer is valid + * FALSE = Dimm is not present, pointer has not been modified. + */ + +BOOLEAN +MemTGetDimmSpdBuffer3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN OUT UINT8 **SpdBuffer, + IN UINT8 Dimm + ) +{ + CH_DEF_STRUCT *ChannelPtr; + SPD_DEF_STRUCT *SPDPtr; + BOOLEAN DimmPresent; + + DimmPresent = FALSE; + ChannelPtr = TechPtr->NBPtr->ChannelPtr; + ASSERT (Dimm < (sizeof (ChannelPtr->DimmSpdPtr) / sizeof (ChannelPtr->DimmSpdPtr[0]))) + SPDPtr = ChannelPtr->DimmSpdPtr[Dimm]; + + + if (SPDPtr != NULL) { + DimmPresent = SPDPtr->DimmPresent; + if (DimmPresent) { + *SpdBuffer = SPDPtr->Data; + } + } + return DimmPresent; +} + diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtspd3.h b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtspd3.h new file mode 100644 index 0000000000..8eb9829238 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtspd3.h @@ -0,0 +1,203 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mtspd3.h + * + * Technology SPD support for DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** + * + * Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. + * + * AMD is granting you permission to use this software (the Materials) + * pursuant to the terms and conditions of your Software License Agreement + * with AMD. This header does *NOT* give you permission to use the Materials + * or any rights under AMD's intellectual property. Your use of any portion + * of these Materials shall constitute your acceptance of those terms and + * conditions. If you do not agree to the terms and conditions of the Software + * License Agreement, please do not use any portion of these Materials. + * + * CONFIDENTIALITY: The Materials and all other information, identified as + * confidential and provided to you by AMD shall be kept confidential in + * accordance with the terms and conditions of the Software License Agreement. + * + * LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION + * PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, + * OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. + * IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER + * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS + * INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, + * GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER + * RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE + * EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, + * THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + * + * AMD does not assume any responsibility for any errors which may appear in + * the Materials or any other related information provided to you by AMD, or + * result from use of the Materials or any related information. + * + * You agree that you will not reverse engineer or decompile the Materials. + * + * NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + * further information, software, technical information, know-how, or show-how + * available to you. Additionally, AMD retains the right to modify the + * Materials at any time, without notice, and is not obligated to provide such + * modified Materials to you. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with + * "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is + * subject to the restrictions as set forth in FAR 52.227-14 and + * DFAR252.227-7013, et seq., or its successor. Use of the Materials by the + * Government constitutes acknowledgement of AMD's proprietary rights in them. + * + * EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any + * direct product thereof will be exported directly or indirectly, into any + * country prohibited by the United States Export Administration Act and the + * regulations thereunder, without the required authorization from the U.S. + * government nor will be used for any purpose prohibited by the same. + * *************************************************************************** + * + */ + +#ifndef _MTSPD3_H_ +#define _MTSPD3_H_ + +/*---------------------------------------------------------------------------- + * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS) + * + *---------------------------------------------------------------------------- + */ + +/*----------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *----------------------------------------------------------------------------- + */ + +/*=============================================================================== + * Jedec DDR III + *=============================================================================== + */ +#define SPD_BYTE_USED 0 +#define SPD_TYPE 2 /* SPD byte read location */ +#define JED_DDR_SDRAM 7 /* Jedec defined bit field */ +#define JED_DDR2_SDRAM 8 /* Jedec defined bit field */ +#define JED_DDR3SDRAM 0xB /* Jedec defined bit field */ + +#define SPD_DIMM_TYPE 3 +#define SPD_ATTRIB 21 +#define JED_DIF_CK_MSK 0x20 /* Differential Clock Input */ +#define JED_RDIMM 1 +#define JED_MINIRDIMM 5 +#define JED_UDIMM 2 +#define JED_SODIMM 3 +#define JED_LRDIMM 0xB +#define JED_UNDEFINED 0 /* Undefined value */ + +#define SPD_L_BANKS 4 /* [7:4] number of [logical] banks on each device */ +#define SPD_DENSITY 4 /* bit 3:0 */ +#define SPD_ROW_SZ 5 /* bit 5:3 */ +#define SPD_COL_SZ 5 /* bit 2:0 */ +#define SPD_RANKS 7 /* bit 5:3 */ +#define SPD_DEV_WIDTH 7 /* bit 2:0 */ +#define SPD_ECCBITS 8 /* bit 4:3 */ +#define JED_ECC 8 +#define SPD_RAWCARD 62 /* bit 2:0 */ +#define SPD_ADDRMAP 63 /* bit 0 */ + +#define SPD_CTLWRD03 70 /* bit 7:4 */ +#define SPD_CTLWRD04 71 /* bit 3:0 */ +#define SPD_CTLWRD05 71 /* bit 7:4 */ + +#define SPD_FTB 9 + +#define SPD_DIVIDENT 10 +#define SPD_DIVISOR 11 + +#define SPD_TCK 12 +#define SPD_CASLO 14 +#define SPD_CASHI 15 +#define SPD_TAA 16 + +#define SPD_TRP 20 +#define SPD_TRRD 19 +#define SPD_TRCD 18 +#define SPD_TRAS 22 +#define SPD_TWR 17 +#define SPD_TWTR 26 +#define SPD_TRTP 27 +#define SPD_TRC 23 +#define SPD_UPPER_TRC 21 /* bit 7:4 */ +#define SPD_UPPER_TRAS 21 /* bit 3:0 */ +#define SPD_TFAW 29 +#define SPD_UPPER_TFAW 28 /* bit 3:0 */ + +#define SPD_TCK_FTB 34 +#define SPD_TAA_FTB 35 +#define SPD_TRCD_FTB 36 +#define SPD_TRP_FTB 37 +#define SPD_TRC_FTB 38 + +/*----------------------------- + * Jedec DDR II related equates + *----------------------------- + */ + +#define CL_DEF 4 /* Default value for failsafe operation. 4=CL 6.0 T */ +#define T_DEF 4 /* Default value for failsafe operation. 4=2.5ns (cycle time) */ + +#define BIAS_TRTP_T 4 +#define BIAS_TRCD_T 5 +#define BIAS_TRAS_T 15 +#define BIAS_TRC_T 11 +#define BIAS_TRRD_T 4 +#define BIAS_TWR_T 4 +#define BIAS_TRP_T 5 +#define BIAS_TWTR_T 4 +#define BIAS_TFAW_T 14 + +#define MIN_TRTP_T 4 +#define MAX_TRTP_T 7 +#define MIN_TRCD_T 5 +#define MAX_TRCD_T 12 +#define MIN_TRAS_T 15 +#define MAX_TRAS_T 30 +#define MIN_TRC_T 11 +#define MAX_TRC_T 42 +#define MIN_TRRD_T 4 +#define MAX_TRRD_T 7 +#define MIN_TWR_T 5 +#define MAX_TWR_T 12 +#define MIN_TRP_T 5 +#define MAX_TRP_T 12 +#define MIN_TWTR_T 4 +#define MAX_TWTR_T 7 +#define MIN_TFAW_T 16 +#define MAX_TFAW_T 32 + +/*---------------------------------------------------------------------------- + * TYPEDEFS, STRUCTURES, ENUMS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * FUNCTIONS PROTOTYPE + * + *---------------------------------------------------------------------------- + */ + + +#endif /* _MTSPD3_H_ */ + + diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mttecc3.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mttecc3.c new file mode 100644 index 0000000000..09bc43cc2b --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mttecc3.c @@ -0,0 +1,190 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mttecc3.c + * + * Technology ECC byte support for registered DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** +* +* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. +* +* AMD is granting you permission to use this software (the Materials) +* pursuant to the terms and conditions of your Software License Agreement +* with AMD. This header does *NOT* give you permission to use the Materials +* or any rights under AMD's intellectual property. Your use of any portion +* of these Materials shall constitute your acceptance of those terms and +* conditions. If you do not agree to the terms and conditions of the Software +* License Agreement, please do not use any portion of these Materials. +* +* CONFIDENTIALITY: The Materials and all other information, identified as +* confidential and provided to you by AMD shall be kept confidential in +* accordance with the terms and conditions of the Software License Agreement. +* +* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION +* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED +* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, +* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. +* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER +* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS +* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, +* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER +* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE +* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, +* THE ABOVE LIMITATION MAY NOT APPLY TO YOU. +* +* AMD does not assume any responsibility for any errors which may appear in +* the Materials or any other related information provided to you by AMD, or +* result from use of the Materials or any related information. +* +* You agree that you will not reverse engineer or decompile the Materials. +* +* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any +* further information, software, technical information, know-how, or show-how +* available to you. Additionally, AMD retains the right to modify the +* Materials at any time, without notice, and is not obligated to provide such +* modified Materials to you. +* +* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with +* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is +* subject to the restrictions as set forth in FAR 52.227-14 and +* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the +* Government constitutes acknowledgement of AMD's proprietary rights in them. +* +* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any +* direct product thereof will be exported directly or indirectly, into any +* country prohibited by the United States Export Administration Act and the +* regulations thereunder, without the required authorization from the U.S. +* government nor will be used for any purpose prohibited by the same. +* *************************************************************************** +* +*/ + +/* + *---------------------------------------------------------------------------- + * MODULES USED + * + *---------------------------------------------------------------------------- + */ + + +#include "AGESA.h" +#include "mm.h" +#include "mn.h" +#include "mt.h" +#include "Filecode.h" +CODE_GROUP (G1_PEICC) +RDATA_GROUP (G1_PEICC) + +#define FILECODE PROC_MEM_TECH_DDR3_MTTECC3_FILECODE +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function sets the DQS ECC timings for registered DDR3 + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - No fatal error occurs. + * @return FALSE - Fatal error occurs. + */ + +BOOLEAN +MemTSetDQSEccTmgsRDdr3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + UINT8 Dct; + UINT8 Dimm; + UINT8 i; + UINT8 *WrDqsDly; + UINT16 *RcvEnDly; + UINT8 *RdDqsDly; + UINT8 *WrDatDly; + UINT8 EccByte; + INT16 TempValue; + + MEM_NB_BLOCK *NBPtr; + CH_DEF_STRUCT *ChannelPtr; + + EccByte = TechPtr->MaxByteLanes (); + NBPtr = TechPtr->NBPtr; + + if (NBPtr->MCTPtr->NodeMemSize) { + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + NBPtr->SwitchDCT (NBPtr, Dct); + if (NBPtr->DCTPtr->Timings.DctMemSize != 0) { + ChannelPtr = NBPtr->ChannelPtr; + for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) { + if (NBPtr->DCTPtr->Timings.CsEnabled & ((UINT16)3 << (Dimm * 2))) { + i = Dimm * TechPtr->DlyTableWidth (); + WrDqsDly = &ChannelPtr->WrDqsDlys[i]; + RcvEnDly = &ChannelPtr->RcvEnDlys[i]; + RdDqsDly = &ChannelPtr->RdDqsDlys[i]; + WrDatDly = &ChannelPtr->WrDatDlys[i]; + // Receiver DQS Enable: + // Receiver DQS enable for ECC bytelane = Receiver DQS enable for bytelane 3 - + // [write DQS for bytelane 3 - write DQS for ECC] + + TempValue = (INT16) RcvEnDly[3] - (INT16) (WrDqsDly[3] - WrDqsDly[EccByte]); + if (TempValue < 0) { + TempValue = 0; + } + RcvEnDly[EccByte] = (UINT16) TempValue; + + // Read DQS: + // Read DQS for ECC bytelane = read DQS of byte lane 3 + // + RdDqsDly[EccByte] = RdDqsDly[3]; + + // Write Data: + // Write Data for ECC bytelane = Write DQS for ECC + + // [write data for bytelane 3 - Write DQS for bytelane 3] + TempValue = (INT16) (WrDqsDly[EccByte] + (INT8) (WrDatDly[3] - WrDqsDly[3])); + if (TempValue < 0) { + TempValue = 0; + } + WrDatDly[EccByte] = (UINT8) TempValue; + + NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (Dimm, EccByte), RcvEnDly[EccByte]); + NBPtr->SetTrainDly (NBPtr, AccessRdDqsDly, DIMM_BYTE_ACCESS (Dimm, EccByte), RdDqsDly[EccByte]); + NBPtr->SetTrainDly (NBPtr, AccessWrDatDly, DIMM_BYTE_ACCESS (Dimm, EccByte), WrDatDly[EccByte]); + } + } + } + } + } + return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL); +}
\ No newline at end of file diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mttwl3.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mttwl3.c new file mode 100644 index 0000000000..45884a6c17 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mttwl3.c @@ -0,0 +1,742 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mttwl3.c + * + * Technology Phy assisted write levelization for DDR3 + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Mem/Tech/DDR3) + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + **/ +/***************************************************************************** +* +* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. +* +* AMD is granting you permission to use this software (the Materials) +* pursuant to the terms and conditions of your Software License Agreement +* with AMD. This header does *NOT* give you permission to use the Materials +* or any rights under AMD's intellectual property. Your use of any portion +* of these Materials shall constitute your acceptance of those terms and +* conditions. If you do not agree to the terms and conditions of the Software +* License Agreement, please do not use any portion of these Materials. +* +* CONFIDENTIALITY: The Materials and all other information, identified as +* confidential and provided to you by AMD shall be kept confidential in +* accordance with the terms and conditions of the Software License Agreement. +* +* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION +* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED +* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, +* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. +* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER +* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS +* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, +* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER +* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE +* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, +* THE ABOVE LIMITATION MAY NOT APPLY TO YOU. +* +* AMD does not assume any responsibility for any errors which may appear in +* the Materials or any other related information provided to you by AMD, or +* result from use of the Materials or any related information. +* +* You agree that you will not reverse engineer or decompile the Materials. +* +* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any +* further information, software, technical information, know-how, or show-how +* available to you. Additionally, AMD retains the right to modify the +* Materials at any time, without notice, and is not obligated to provide such +* modified Materials to you. +* +* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with +* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is +* subject to the restrictions as set forth in FAR 52.227-14 and +* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the +* Government constitutes acknowledgement of AMD's proprietary rights in them. +* +* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any +* direct product thereof will be exported directly or indirectly, into any +* country prohibited by the United States Export Administration Act and the +* regulations thereunder, without the required authorization from the U.S. +* government nor will be used for any purpose prohibited by the same. +* *************************************************************************** +* +*/ + +/* + *---------------------------------------------------------------------------- + * MODULES USED + * + *---------------------------------------------------------------------------- + */ + + + +#include "AGESA.h" +#include "Ids.h" +#include "mm.h" +#include "mn.h" +#include "mu.h" +#include "mt.h" +#include "mp.h" +#include "mtsdi3.h" +#include "mtlrdimm3.h" +#include "merrhdl.h" +#include "OptionMemory.h" +#include "PlatformMemoryConfiguration.h" +#include "GeneralServices.h" +#include "Filecode.h" +CODE_GROUP (G1_PEICC) +RDATA_GROUP (G1_PEICC) + +#define FILECODE PROC_MEM_TECH_DDR3_MTTWL3_FILECODE +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ +extern MEM_PSC_FLOW_BLOCK* memPlatSpecFlowArray[]; + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +BOOLEAN +STATIC +MemTWriteLevelizationHw3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Pass + ); + +VOID +STATIC +MemTWLPerDimmHw3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Dimm, + IN UINT8 Pass + ); + +VOID +STATIC +MemTPrepareDIMMs3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 TargetDIMM, + IN BOOLEAN Wl + ); + +VOID +STATIC +MemTProcConfig3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Dimm, + IN UINT8 Pass + ); + +VOID +STATIC +MemTBeginWLTrain3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Dimm + ); + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function executes first pass of Phy assisted write levelization + * for a specific node (DDR800). + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - No fatal error occurs. + * @return FALSE - Fatal error occurs. + */ + +BOOLEAN +MemTWriteLevelizationHw3Pass1 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + return MemTWriteLevelizationHw3 (TechPtr, 1); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function executes second pass of Phy assisted write levelization + * for a specific node (DDR1066 and above). + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - No fatal error occurs. + * @return FALSE - Fatal error occurs. + */ + +BOOLEAN +MemTWriteLevelizationHw3Pass2 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + // If current speed is higher than start-up speed, do second pass of WL + if (TechPtr->NBPtr->DCTPtr->Timings.Speed > TechPtr->NBPtr->StartupSpeed) { + return MemTWriteLevelizationHw3 (TechPtr, 2); + } + return TRUE; +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function prepares for Phy assisted training. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - No fatal error occurs. + * @return FALSE - Fatal error occurs. + */ + +BOOLEAN +MemTPreparePhyAssistedTraining ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + // Disable auto refresh by configuring F2x[1, 0]8C[DisAutoRefresh] = 1. + TechPtr->NBPtr->BrdcstSet (TechPtr->NBPtr, BFDisAutoRefresh, 1); + // Disable ZQ calibration short command by configuring F2x[1, 0]94[ZqcsInterval] = 00b. + TechPtr->NBPtr->BrdcstSet (TechPtr->NBPtr, BFZqcsInterval, 0); + // Attempt to get the seeds value from PSC tables for WL and RxEn pass1 training if applicable. + if (!TechPtr->NBPtr->PsPtr->MemPGetPass1Seeds (TechPtr->NBPtr)) { + ASSERT (FALSE); + } + + return (BOOLEAN) (TechPtr->NBPtr->MCTPtr->ErrCode < AGESA_FATAL); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function revert to normal settings when exiting from Phy assisted training. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - No fatal error occurs. + * @return FALSE - Fatal error occurs. + */ + +BOOLEAN +MemTExitPhyAssistedTraining ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + MEM_NB_BLOCK *NBPtr; + NBPtr = TechPtr->NBPtr; + + // 13.Program F2x[1, 0]8C[DisAutoRefresh] = 0. + NBPtr->BrdcstSet (NBPtr, BFDisAutoRefresh, 0); + // 14.Program F2x[1, 0]94[ZqcsInterval] to the proper interval for the current memory configuration. + NBPtr->BrdcstSet (NBPtr, BFZqcsInterval, 2); + NBPtr->FamilySpecificHook[ExitPhyAssistedTraining] (NBPtr, NBPtr); + + return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL); +} + +/*---------------------------------------------------------------------------- + * LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function executed hardware based write levelization for a specific die + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Pass - Pass number (1 (400Mhz) or 2 (>400Mhz)) + * + * @pre Auto refresh and ZQCL must be disabled + * + * @return TRUE - No fatal error occurs. + * @return FALSE - Fatal error occurs. + */ + +BOOLEAN +STATIC +MemTWriteLevelizationHw3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Pass + ) +{ + MEM_NB_BLOCK *NBPtr; + DCT_STRUCT *DCTPtr; + UINT8 Dct; + UINT8 ChipSel; + + NBPtr = TechPtr->NBPtr; + + IDS_HDT_CONSOLE (MEM_STATUS, "\nStart write leveling\n"); + AGESA_TESTPOINT (TpProcMemWriteLevelizationTraining, &(NBPtr->MemPtr->StdHeader)); + // Begin DQS Write timing training + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + NBPtr->SwitchDCT (NBPtr, Dct); + IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct); + DCTPtr = NBPtr->DCTPtr; + + TechPtr->WLCriticalDelay = 0x00; + + //training for each Dimm/CS + for (ChipSel = 0; ChipSel < NBPtr->CsPerChannel; ChipSel = ChipSel + NBPtr->CsPerDelay) { + if ((DCTPtr->Timings.CsEnabled & ((UINT16) ((NBPtr->CsPerDelay == 2)? 3 : 1) << ChipSel)) != 0) { + if (!(NBPtr->MCTPtr->Status[SbLrdimms]) || ((NBPtr->ChannelPtr->LrDimmPresent & ((UINT8) 1 << (ChipSel >> 1))) != 0)) { + IDS_HDT_CONSOLE (MEM_STATUS, "\t\tCS %d\n", ChipSel); + MemTWLPerDimmHw3 (TechPtr, (ChipSel / NBPtr->CsPerDelay), Pass); + } + } + } + + NBPtr->FamilySpecificHook[CalcWrDqDqsEarly] (NBPtr, NULL); + } + IDS_HDT_CONSOLE (MEM_FLOW, "End write leveling\n\n"); + return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function initializes per DIMM write levelization + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Dimm - DIMM to be trained + * @param[in] Pass - Pass number (1 (400Mhz) or 2 (>400Mhz)) + * + */ + +VOID +STATIC +MemTWLPerDimmHw3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Dimm, + IN UINT8 Pass + ) +{ + MEM_DATA_STRUCT *MemPtr; + MEM_NB_BLOCK *NBPtr; + + NBPtr = TechPtr->NBPtr; + MemPtr = NBPtr->MemPtr; + + ASSERT (Dimm < (NBPtr->CsPerChannel / NBPtr->CsPerDelay)); + + // 1. A. Specify the target Dimm that is to be trained by programming + // F2x[1, 0]9C_x08[TrDimmSel]. + NBPtr->SetBitField (NBPtr, BFTrDimmSel, Dimm); + + TechPtr->TargetDIMM = Dimm; + NBPtr->FamilySpecificHook[InitPerNibbleTrn] (NBPtr, NULL); + for (TechPtr->TrnNibble = NIBBLE_0; TechPtr->TrnNibble <= (NBPtr->FamilySpecificHook[TrainWlPerNibble] (NBPtr, &Dimm)? NIBBLE_0 : NIBBLE_1); TechPtr->TrnNibble++) { + // 2. Prepare the DIMMs for write levelization using DDR3-defined + // MR commands. + MemTPrepareDIMMs3 (TechPtr, Dimm, TRUE); + + // 3. After the DIMMs are configured, BIOS waits 40 MEMCLKs to + // satisfy DDR3-defined internal DRAM timing. + NBPtr->WaitXMemClks (NBPtr, 40); + + // 4. Configure the processor's DDR phy for write levelization training: + MemTProcConfig3 (TechPtr, Dimm, Pass); + + // 5. Begin write levelization training + MemTBeginWLTrain3 (TechPtr, Dimm); + } + // 7. Program the target Dimm back to normal operation + MemTPrepareDIMMs3 (TechPtr, Dimm, FALSE); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function prepares the DIMMS for Write Levelization + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] TargetDIMM - DIMM to be trained + * @param[in] Wl - Indicates if WL mode should be enabled + * + */ + +VOID +STATIC +MemTPrepareDIMMs3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 TargetDIMM, + IN BOOLEAN Wl + ) +{ + MEM_NB_BLOCK *NBPtr; + UINT8 ChipSel; + + NBPtr = TechPtr->NBPtr; + + AGESA_TESTPOINT (TpProcMemWlPrepDimms, &(NBPtr->MemPtr->StdHeader)); + ASSERT (TargetDIMM < (NBPtr->CsPerChannel / NBPtr->CsPerDelay)); + TechPtr->TargetDIMM = TargetDIMM; + if (!(TechPtr->TechnologySpecificHook[WlTrainingPrepareLrdimm] (TechPtr, &Wl))) { + for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel++) { + if ((NBPtr->DCTPtr->Timings.CsPresent & ((UINT16)1 << ChipSel)) != 0) { + NBPtr->SetBitField (NBPtr, BFMrsChipSel, ChipSel); + // Set MR1 to F2x7C[MrsAddress], F2x7C[MrsBank]=1 + MemTEMRS13 (TechPtr, Wl, TargetDIMM); + NBPtr->SendMrsCmd (NBPtr); + // Set MR2 to F2x7C[MrsAddress], F2x7C[MrsBank]=1 + MemTEMRS23 (TechPtr); + // Send command + NBPtr->SendMrsCmd (NBPtr); + } + } + if (Wl) { + // Program WrLvOdt for the Target DIMM (or CS) + NBPtr->SetBitField (NBPtr, BFWrLvOdt, NBPtr->ChannelPtr->PhyWLODT[TargetDIMM]); + } + } +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function programs seed values for Write Levelization + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Dimm - DIMM to be trained + * @param[in] Pass - Pass for WL training (1 - 400Mhz or 2 - >400Mhz) + * + */ + +VOID +STATIC +MemTProcConfig3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Dimm, + IN UINT8 Pass + ) +{ + DIE_STRUCT *MCTPtr; + CH_DEF_STRUCT *ChannelPtr; + MEM_NB_BLOCK *NBPtr; + UINT16 WrDqsDly; + // Memclk Delay incurred by register. + UINT8 MemClkRegDly; + UINT8 ByteLane; + UINT8 DefaultSeed; + UINT8 CurrentSeed; + UINT8 *Seed; + UINT8 RCW2; + UINT16 Speed; + INT16 WrDqsBias; + + NBPtr = TechPtr->NBPtr; + MCTPtr = NBPtr->MCTPtr; + ChannelPtr = TechPtr->NBPtr->ChannelPtr; + + AGESA_TESTPOINT (TpProcMemWlConfigDimms, &(NBPtr->MemPtr->StdHeader)); + RCW2 = ChannelPtr->CtrlWrd02[Dimm]; + Speed = TechPtr->NBPtr->DCTPtr->Timings.Speed; + + IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t Byte: 00 01 02 03 04 05 06 07 ECC\n"); + IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeeds: "); + // Program an initialization Value to registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52 to set + // the gross and fine delay for all the byte lane fields. If the target frequency is different than 400MHz, + // BIOS must execute two training passes for each Dimm. For pass 1 at a 400MHz MEMCLK frequency, + // use an initial total delay value. + if (Pass == 1) { + // + // Get the default value of seed + // + if (MCTPtr->Status[SbRegistered]) { + // + // RDIMM + // + if (Speed == DDR667_FREQUENCY) { + DefaultSeed = ((RCW2 & BIT0) == 0) ? 0x3B : 0x4B; + } else { + DefaultSeed = ((RCW2 & BIT0) == 0) ? 0x41 : 0x51; + } + } else if (ChannelPtr->SODimmPresent != 0) { + // + // SODIMMM + // + DefaultSeed = 0x12; + } else if (MCTPtr->Status[SbLrdimms]) { + // + // LRDIMM + // + DefaultSeed = 0xF7; + } else { + // + // UDIMMM + // + DefaultSeed = 0x1A; + } + + NBPtr->FamilySpecificHook[OverrideWLSeed] (NBPtr, &DefaultSeed); + ASSERT (Speed >= DDR667_FREQUENCY); + + // Get platform override seed + Seed = (UINT8 *) FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_WL_SEED, MCTPtr->SocketId, ChannelPtr->ChannelID, Dimm, + &(NBPtr->MCTPtr->LogicalCpuid), &(NBPtr->MemPtr->StdHeader)); + for (ByteLane = 0; ByteLane < TechPtr->DlyTableWidth (); ByteLane++) { + // This includes ECC as byte 8 + CurrentSeed = ((Seed != NULL) ? Seed[ByteLane] : DefaultSeed); + ChannelPtr->WrDqsDlys[Dimm * TechPtr->DlyTableWidth () + ByteLane] = CurrentSeed; + + if (NBPtr->IsSupported[WLSeedAdjust]) { + if ((CurrentSeed & 0x20) != 0) { + // If (SeedGross is odd) then SeedPreGross = 1 + CurrentSeed = (CurrentSeed & 0x1F) | 0x20; + } else { + // If (SeedGross is even) then SeedPreGross = 2 + CurrentSeed = (CurrentSeed & 0x1F) | 0x40; + } + } + + NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), CurrentSeed); + IDS_HDT_CONSOLE (MEM_FLOW, "%02x ", CurrentSeed); + } + } else { + //10.Multiply the previously saved delay values in Pass 1, step #5 by (target frequency)/400 to find + //the gross and fine delay initialization values at the target frequency. Use these values as the initial + //seed values when executing Pass 2, step #4. + for (ByteLane = 0; ByteLane < TechPtr->DlyTableWidth (); ByteLane++) { + // This includes ECC as byte 8 + WrDqsDly = ChannelPtr->WrDqsDlys[Dimm * TechPtr->DlyTableWidth () + ByteLane]; + TechPtr->Bytelane = ByteLane; + NBPtr->FamilySpecificHook[TrainWlPerNibbleSeed] (NBPtr, &WrDqsDly); + + if (MCTPtr->Status[SbRegistered]) { + // + // For Registered Dimms + // + MemClkRegDly = ((RCW2 & BIT0) == 0) ? 0x20 : 0x30; + } else { + // + // Unbuffered Dimms and LRDIMMs + // + MemClkRegDly = 0; + } + // + // Recover any adjustmen to delay for WrDqDqsEarly + // + WrDqsBias = 0; + NBPtr->FamilySpecificHook[AdjustWrDqsBeforeSeedScaling] (NBPtr, &WrDqsBias); + + // Scale WrDqsDly to the next speed + WrDqsDly = (UINT16) (MemClkRegDly + ((((INT32) WrDqsDly - MemClkRegDly - WrDqsBias) * Speed) / TechPtr->PrevSpeed)); + + ChannelPtr->WrDqsDlys[Dimm * TechPtr->DlyTableWidth () + ByteLane] = (UINT8) WrDqsDly; + + if (NBPtr->IsSupported[WLSeedAdjust]) { + if ((WrDqsDly & 0x20) != 0) { + // If (SeedGross is odd) then SeedPreGross = 1 + WrDqsDly = (WrDqsDly & 0x1F) | 0x20; + } else { + // If (SeedGross is even) then SeedPreGross = 2 + WrDqsDly = (WrDqsDly & 0x1F) | 0x40; + } + } + NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), WrDqsDly); + IDS_HDT_CONSOLE (MEM_FLOW, "%02x ", WrDqsDly); + } + } + IDS_HDT_CONSOLE (MEM_FLOW, "\n"); +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function begins WL training for a specific DIMM + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * @param[in] Dimm - DIMM to be trained + * + */ + +VOID +STATIC +MemTBeginWLTrain3 ( + IN OUT MEM_TECH_BLOCK *TechPtr, + IN UINT8 Dimm + ) +{ + MEM_DATA_STRUCT *MemPtr; + DIE_STRUCT *MCTPtr; + MEM_NB_BLOCK *NBPtr; + UINT8 ByteLane; + UINT8 Seed; + UINT8 Delay; + INT16 Delay16; + + NBPtr = TechPtr->NBPtr; + MemPtr = NBPtr->MemPtr; + MCTPtr = NBPtr->MCTPtr; + + AGESA_TESTPOINT (TpProcMemWlTrainTargetDimm, &(MemPtr->StdHeader)); + // Assert ODT pins for write leveling + NBPtr->SetBitField (NBPtr, BFWrLvOdtEn, 1); + + // Wait 10 MEMCLKs to allow for ODT signal settling. + NBPtr->WaitXMemClks (NBPtr, 10); + + IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tWrtLvTrEn = 1\n"); + // Program F2x[1, 0]9C_x08[WrtLlTrEn]=1. + NBPtr->SetBitField (NBPtr, BFWrtLvTrEn, 1); + + // Wait 200 MEMCLKs. + NBPtr->WaitXMemClks (NBPtr, 200); + + // Program F2x[1, 0]9C_x08[WrtLlTrEn]=0. + NBPtr->SetBitField (NBPtr, BFWrtLvTrEn, 0); + + // Read from registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52 to get the gross and fine Delay settings + // for the target Dimm and save these values. + IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t PRE: "); + for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) { + // This includes ECC as byte 8 + Seed = NBPtr->ChannelPtr->WrDqsDlys[(Dimm * TechPtr->DlyTableWidth ()) + ByteLane]; + Delay = (UINT8)NBPtr->GetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (Dimm, ByteLane)); + IDS_HDT_CONSOLE (MEM_FLOW, "%02x ", Delay); + + TechPtr->Bytelane = ByteLane; + TechPtr->TargetDIMM = Dimm; + NBPtr->FamilySpecificHook[TrainWlPerNibbleAdjustWLDly] (NBPtr, &Delay); + + if (NBPtr->IsSupported[WLSeedAdjust]) { + // Recover WrDqsGrossDly: + // WrDqsGrossDly = SeedGross + PhRecGrossDlyByte - SeedPreGross + if ((Seed & 0x20) != 0) { + // If (SeedGross is odd) then SeedPreGross = 1 + if ((NBPtr->IsSupported[WLNegativeDelay]) && ((Seed & 0x80) != 0)) { + // If the seed was negative, save the most negative delay in WLCriticalDelay + TechPtr->WLCriticalDelay = MIN (TechPtr->WLCriticalDelay, (INT16)Delay - 0x40); + Delay -= 0x40; + } else { + Delay += (Seed & 0xE0) - 0x20; + } + } else { + // If (SeedGross is even) then SeedPreGross = 2 + if (((Seed & 0xE0) == 0) && (Delay < 0x40)) { + // If SeedGross is 0 and PhRecGrossDlyByte is less than SeedPreGross, + // we have a negative result and need to program the delay to 0 + if (NBPtr->IsSupported[WLNegativeDelay]) { + // + // Save the lowest negative delay value across all Dimms and Bytelanes + // + TechPtr->WLCriticalDelay = MIN (TechPtr->WLCriticalDelay, (INT16)Delay - 0x40); + Delay -= 0x40; + } else { + Delay = 0; + } + } else { + if (NBPtr->GetBitField (NBPtr, BFWrDqDqsEarly) != 0) { + Delay = Delay + (Seed & 0xE0); + Delay16 = Delay - 0x40; + Delay = (UINT8)Delay16; + TechPtr->WLCriticalDelay = MIN (TechPtr->WLCriticalDelay, Delay16); + } else { + Delay += (Seed & 0xE0) - 0x40; + } + } + } + } else if (((Seed >> 5) == 0) && ((Delay >> 5) == 3)) { + IDS_OPTION_HOOK (IDS_CHECK_NEGATIVE_WL, &Delay, &(TechPtr->NBPtr->MemPtr->StdHeader)); + // If seed has gross delay of 0 and PRE has gross delay of 3, + // then round the total delay of TxDqs to 0. + Delay = 0; + } + + if ((!NBPtr->IsSupported[WLNegativeDelay]) && ((Delay > (Seed + 0x20)) || (Seed > (Delay + 0x20)))) { + // + // If PRE comes back with more than Seed +/- 0x20, then this is an + // unexpected condition. Log the condition. + // + PutEventLog (AGESA_ERROR, MEM_ERROR_WL_PRE_OUT_OF_RANGE, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, ((Seed << 8) + Delay), &NBPtr->MemPtr->StdHeader); + } + NBPtr->SetTrainDly (NBPtr, AccessWrDqsDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), Delay); + NBPtr->ChannelPtr->WrDqsDlys[(Dimm * TechPtr->DlyTableWidth ()) + ByteLane] = Delay; + } + + IDS_HDT_CONSOLE_DEBUG_CODE ( + IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\tWrDqs: "); + for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) { + IDS_HDT_CONSOLE (MEM_FLOW, "%02x ", NBPtr->ChannelPtr->WrDqsDlys[(Dimm * TechPtr->DlyTableWidth ()) + ByteLane]); + } + IDS_HDT_CONSOLE (MEM_FLOW, "\n\n"); + ); + + // Disable write leveling ODT pins + NBPtr->SetBitField (NBPtr, BFWrLvOdtEn, 0); + + // Wait 10 MEMCLKs to allow for ODT signal settling. + NBPtr->WaitXMemClks (NBPtr, 10); + +} + +/* -----------------------------------------------------------------------------*/ +/** + * + * This function programs register after Phy assisted training is finish. + * + * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK + * + * @return TRUE - No fatal error occurs. + * @return FALSE - Fatal error occurs. + */ + +BOOLEAN +MemTExitPhyAssistedTrainingClient3 ( + IN OUT MEM_TECH_BLOCK *TechPtr + ) +{ + MEM_NB_BLOCK *NBPtr; + UINT8 Dct; + UINT8 ChipSel; + NBPtr = TechPtr->NBPtr; + + NBPtr->FamilySpecificHook[ReEnablePhyComp] (NBPtr, NBPtr); + NBPtr->BrdcstSet (NBPtr, BFDisDllShutdownSR, 1); + NBPtr->BrdcstSet (NBPtr, BFEnterSelfRef, 1); + NBPtr->PollBitField (NBPtr, BFEnterSelfRef, 0, PCI_ACCESS_TIMEOUT, TRUE); + IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClkAlign = 2\n"); + NBPtr->BrdcstSet (NBPtr, BFExitSelfRef, 1); + NBPtr->PollBitField (NBPtr, BFExitSelfRef, 0, PCI_ACCESS_TIMEOUT, TRUE); + if (NBPtr->IsSupported[SetDllShutDown]) { + NBPtr->BrdcstSet (NBPtr, BFDisDllShutdownSR, 0); + } + + // Calculate Max Latency for both channels to prepare for position training + for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { + IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct); + NBPtr->SwitchDCT (NBPtr, Dct); + if (TechPtr->FindMaxDlyForMaxRdLat (TechPtr, &ChipSel)) { + NBPtr->SetMaxLatency (NBPtr, TechPtr->MaxDlyForMaxRdLat); + } + } + return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL); +} |