Siyuan Wang | affe85f | 2013-07-25 15:14:15 +0800 | [diff] [blame] | 1 | /* $NoKeywords:$ */ |
| 2 | /** |
| 3 | * @file |
| 4 | * |
| 5 | * mt3.c |
| 6 | * |
| 7 | * Common Technology functions for DDR3 |
| 8 | * |
| 9 | * @xrefitem bom "File Content Label" "Release Content" |
| 10 | * @e project: AGESA |
| 11 | * @e sub-project: (Mem/Tech/DDR3) |
| 12 | * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $ |
| 13 | * |
| 14 | **/ |
| 15 | /***************************************************************************** |
| 16 | * |
| 17 | * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc. |
| 18 | * All rights reserved. |
| 19 | * |
| 20 | * Redistribution and use in source and binary forms, with or without |
| 21 | * modification, are permitted provided that the following conditions are met: |
| 22 | * * Redistributions of source code must retain the above copyright |
| 23 | * notice, this list of conditions and the following disclaimer. |
| 24 | * * Redistributions in binary form must reproduce the above copyright |
| 25 | * notice, this list of conditions and the following disclaimer in the |
| 26 | * documentation and/or other materials provided with the distribution. |
| 27 | * * Neither the name of Advanced Micro Devices, Inc. nor the names of |
| 28 | * its contributors may be used to endorse or promote products derived |
| 29 | * from this software without specific prior written permission. |
| 30 | * |
| 31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 32 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 33 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 34 | * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY |
| 35 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 36 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 37 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 38 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 40 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 41 | * *************************************************************************** |
| 42 | * |
| 43 | */ |
| 44 | |
| 45 | /* |
| 46 | *---------------------------------------------------------------------------- |
| 47 | * MODULES USED |
| 48 | * |
| 49 | *---------------------------------------------------------------------------- |
| 50 | */ |
| 51 | |
| 52 | |
| 53 | |
| 54 | #include "AGESA.h" |
| 55 | #include "Ids.h" |
| 56 | #include "mm.h" |
| 57 | #include "mn.h" |
| 58 | #include "mu.h" |
| 59 | #include "mt.h" |
| 60 | #include "mt3.h" |
| 61 | #include "mtspd3.h" |
| 62 | #include "mtot3.h" |
| 63 | #include "OptionMemory.h" |
| 64 | #include "PlatformMemoryConfiguration.h" |
| 65 | #include "Filecode.h" |
| 66 | CODE_GROUP (G1_PEICC) |
| 67 | RDATA_GROUP (G1_PEICC) |
| 68 | |
| 69 | /* features */ |
| 70 | #define FILECODE PROC_MEM_TECH_DDR3_MT3_FILECODE |
| 71 | /*---------------------------------------------------------------------------- |
| 72 | * DEFINITIONS AND MACROS |
| 73 | * |
| 74 | *---------------------------------------------------------------------------- |
| 75 | */ |
| 76 | |
| 77 | /*---------------------------------------------------------------------------- |
| 78 | * TYPEDEFS AND STRUCTURES |
| 79 | * |
| 80 | *---------------------------------------------------------------------------- |
| 81 | */ |
| 82 | |
| 83 | /*---------------------------------------------------------------------------- |
| 84 | * PROTOTYPES OF LOCAL FUNCTIONS |
| 85 | * |
| 86 | *---------------------------------------------------------------------------- |
| 87 | */ |
| 88 | |
| 89 | /*---------------------------------------------------------------------------- |
| 90 | * EXPORTED FUNCTIONS |
| 91 | * |
| 92 | *---------------------------------------------------------------------------- |
| 93 | */ |
| 94 | /* -----------------------------------------------------------------------------*/ |
| 95 | /** |
| 96 | * |
| 97 | * This function Constructs the technology block |
| 98 | * |
| 99 | * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK |
| 100 | * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK |
| 101 | * |
| 102 | */ |
| 103 | |
| 104 | BOOLEAN |
| 105 | MemConstructTechBlock3 ( |
| 106 | IN OUT MEM_TECH_BLOCK *TechPtr, |
| 107 | IN OUT MEM_NB_BLOCK *NBPtr |
| 108 | ) |
| 109 | { |
| 110 | TECHNOLOGY_TYPE *TechTypePtr; |
| 111 | UINT8 Dct; |
| 112 | UINT8 Channel; |
| 113 | UINT8 i; |
| 114 | DIE_STRUCT *MCTPtr; |
| 115 | DCT_STRUCT *DCTPtr; |
| 116 | CH_DEF_STRUCT *ChannelPtr; |
| 117 | UINT8 DimmSlots; |
| 118 | |
| 119 | |
| 120 | TechTypePtr = (TECHNOLOGY_TYPE *) FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MEM_TECH, NBPtr->MCTPtr->SocketId, 0, 0, NULL, NULL); |
| 121 | if (TechTypePtr != NULL) { |
| 122 | // Ensure the platform override value is valid |
| 123 | ASSERT ((*TechTypePtr == DDR3_TECHNOLOGY) || (*TechTypePtr == DDR2_TECHNOLOGY)); |
| 124 | if (*TechTypePtr != DDR3_TECHNOLOGY) { |
| 125 | return FALSE; |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | TechPtr->NBPtr = NBPtr; |
| 130 | TechPtr->RefPtr = NBPtr->RefPtr; |
| 131 | MCTPtr = NBPtr->MCTPtr; |
| 132 | |
| 133 | TechPtr->SendAllMRCmds = MemTSendAllMRCmds3; |
| 134 | TechPtr->FreqChgCtrlWrd = FreqChgCtrlWrd3; |
| 135 | TechPtr->SetDramMode = MemTSetDramMode3; |
| 136 | TechPtr->DimmPresence = MemTDIMMPresence3; |
| 137 | TechPtr->SpdCalcWidth = MemTSPDCalcWidth3; |
| 138 | TechPtr->SpdGetTargetSpeed = MemTSPDGetTargetSpeed3; |
| 139 | TechPtr->AutoCycTiming = MemTAutoCycTiming3; |
| 140 | TechPtr->SpdSetBanks = MemTSPDSetBanks3; |
| 141 | TechPtr->SetDqsEccTmgs = MemTSetDQSEccTmgs; |
| 142 | TechPtr->GetCSIntLvAddr = MemTGetCSIntLvAddr3; |
| 143 | TechPtr->AdjustTwrwr = MemTAdjustTwrwr3; |
| 144 | TechPtr->AdjustTwrrd = MemTAdjustTwrrd3; |
| 145 | TechPtr->GetDimmSpdBuffer = MemTGetDimmSpdBuffer3; |
| 146 | TechPtr->GetLD = MemTGetLD3; |
| 147 | TechPtr->MaxFilterDly = 0; |
| 148 | |
| 149 | // |
| 150 | // Map the Logical Dimms on this channel to the SPD that should be used for that logical DIMM. |
| 151 | // The pointers to the DIMM SPD information is as follows (2 Dimm/Ch and 3 Dimm/Ch examples). |
| 152 | // |
| 153 | // DIMM Spd Buffer Current Channel DimmSpdPtr[MAX_DIMMS_PER_CHANNEL] array |
| 154 | // (Number of dimms varies by platform) (Array size is determined in AGESA.H) Dimm operations loop |
| 155 | // on this array only) |
| 156 | // 2 DIMMS PER CHANNEL |
| 157 | // |
| 158 | // Socket N Channel N Dimm 0 SR/DR DIMM <--------------DimmSpdPtr[0] |
| 159 | // Dimm 1 SR/DR DIMM <--------------DimmSpdPtr[1] |
| 160 | // DimmSpdPtr[2]------->NULL |
| 161 | // DimmSpdPtr[3]------->NULL |
| 162 | // |
| 163 | // Socket N Channel N Dimm 0 SR/DR DIMM <--------------DimmSpdPtr[0] |
| 164 | // Dimm 1 QR DIMM <---------+----DimmSpdPtr[1] |
| 165 | // | DimmSpdPtr[2]------->NULL |
| 166 | // +----DimmSpdPtr[3] |
| 167 | // |
| 168 | // Socket N Channel N Dimm 0 QR DIMM <-----+--------DimmSpdPtr[0] |
| 169 | // Dimm 1 QR DIMM <-----|---+----DimmSpdPtr[1] |
| 170 | // +-- | ---DimmSpdPtr[2] |
| 171 | // +----DimmSpdPtr[3] |
| 172 | // |
| 173 | // 3 DIMMS PER CHANNEL |
| 174 | // |
| 175 | // Socket N Channel N Dimm 0 SR/DR DIMM <--------------DimmSpdPtr[0] |
| 176 | // Dimm 1 SR/DR DIMM <--------------DimmSpdPtr[1] |
| 177 | // Dimm 3 SR/DR DIMM <--------------DimmSpdPtr[2] |
| 178 | // DimmSpdPtr[3]------->NULL |
| 179 | // |
| 180 | // Socket N Channel N Dimm 0 SR/DR DIMM <--------------DimmSpdPtr[0] |
| 181 | // Dimm 1 QR DIMM <---------+----DimmSpdPtr[1] |
| 182 | // Dimm 3 SR/DR DIMM <-------- | ---DimmSpdPtr[2] |
| 183 | // +----DimmSpdPtr[3] |
| 184 | // |
| 185 | // |
| 186 | // FOR LRDIMMS |
| 187 | // |
| 188 | // This code will assign SPD pointers on the basis of Physical ranks, even though |
| 189 | // an LRDIMM may only use one or two logical ranks, that determination will have to |
| 190 | // be made from downstream code. An LRDIMM with greater than 2 Physical ranks will have |
| 191 | // its DimmSpdPtr[] mapped as if it were a QR in the above diagrams. |
| 192 | |
| 193 | for (Dct = 0; Dct < NBPtr->DctCount; Dct++) { |
| 194 | NBPtr->SwitchDCT (NBPtr, Dct); |
| 195 | DCTPtr = NBPtr->DCTPtr; |
| 196 | for (Channel = 0; Channel < NBPtr->ChannelCount; Channel++) { |
| 197 | NBPtr->SwitchChannel (NBPtr, Channel); |
| 198 | ChannelPtr = NBPtr->ChannelPtr; |
| 199 | ChannelPtr->TechType = DDR3_TECHNOLOGY; |
| 200 | ChannelPtr->MCTPtr = MCTPtr; |
| 201 | ChannelPtr->DCTPtr = DCTPtr; |
| 202 | |
| 203 | DimmSlots = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, |
| 204 | MCTPtr->SocketId, |
| 205 | NBPtr->GetSocketRelativeChannel (NBPtr, Dct, Channel) |
| 206 | ); |
| 207 | // |
| 208 | // Initialize the SPD pointers for each Dimm |
| 209 | // |
| 210 | for (i = 0 ; i < (sizeof (ChannelPtr->DimmSpdPtr) / sizeof (ChannelPtr->DimmSpdPtr[0])) ; i++) { |
| 211 | ChannelPtr->DimmSpdPtr[i] = NULL; |
| 212 | } |
| 213 | for (i = 0 ; i < DimmSlots; i++) { |
| 214 | ChannelPtr->DimmSpdPtr[i] = &(ChannelPtr->SpdPtr[i]); |
| 215 | if ( (i + 2) < (sizeof (ChannelPtr->DimmSpdPtr) / sizeof (ChannelPtr->DimmSpdPtr[0]))) { |
| 216 | if (ChannelPtr->DimmSpdPtr[i]->DimmPresent) { |
| 217 | if ((((ChannelPtr->DimmSpdPtr[i]->Data[SPD_RANKS] >> 3) & 0x07) + 1) > 2) { |
| 218 | ChannelPtr->DimmSpdPtr[i + 2] = &(ChannelPtr->SpdPtr[i]); |
| 219 | } |
| 220 | } |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | } |
| 225 | // Initialize Common technology functions |
| 226 | MemTCommonTechInit (TechPtr); |
| 227 | |
| 228 | return TRUE; |
| 229 | } |
| 230 | |
| 231 | /*---------------------------------------------------------------------------- |
| 232 | * LOCAL FUNCTIONS |
| 233 | * |
| 234 | *---------------------------------------------------------------------------- |
| 235 | */ |