AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Mem / Ps / mprtt.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mprtt.c
6  *
7  * A sub-engine which extracts RttNom and RttWr (Dram Term and Dynamic Dram Term) value.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/Ps)
12  * @e \$Revision: 52286 $ @e \$Date: 2011-05-04 03:48:21 -0600 (Wed, 04 May 2011) $
13  *
14  **/
15 /*****************************************************************************
16 *
17 * Copyright (C) 2012 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 "AdvancedApi.h"
56 #include "amdlib.h"
57 #include "Ids.h"
58 #include "cpuFamRegisters.h"
59 #include "cpuRegisters.h"
60 #include "OptionMemory.h"
61 #include "PlatformMemoryConfiguration.h"
62 #include "mu.h"
63 #include "ma.h"
64 #include "mp.h"
65 #include "merrhdl.h"
66 #include "GeneralServices.h"
67 #include "Filecode.h"
68 CODE_GROUP (G2_PEI)
69 RDATA_GROUP (G2_PEI)
70
71 #define FILECODE PROC_MEM_PS_MPRTT_FILECODE
72
73
74 /*----------------------------------------------------------------------------
75  *                          DEFINITIONS AND MACROS
76  *
77  *----------------------------------------------------------------------------
78  */
79 #define _DONT_CARE 0xFF
80
81 /*----------------------------------------------------------------------------
82  *                           TYPEDEFS AND STRUCTURES
83  *
84  *----------------------------------------------------------------------------
85  */
86 /*----------------------------------------------------------------------------
87  *                        PROTOTYPES OF LOCAL FUNCTIONS
88  *
89  *----------------------------------------------------------------------------
90  */
91 BOOLEAN
92 MemPGetRttNomWr (
93   IN OUT   MEM_NB_BLOCK *NBPtr,
94   IN       MEM_PSC_TABLE_BLOCK *EntryOfTables
95   );
96
97 /*----------------------------------------------------------------------------
98  *                            EXPORTED FUNCTIONS
99  *
100  *----------------------------------------------------------------------------
101  */
102 /* -----------------------------------------------------------------------------*/
103 /**
104  *
105  *    A sub-function which extracts RttNom and RttWr value from a input table and stores extracted
106  *    value to a specific address.
107  *
108  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
109  *     @param[in]       *EntryOfTables     - Pointer to MEM_PSC_TABLE_BLOCK
110  *
111  *     @return          TRUE - Table values can be extracted for all present dimms/ranks
112  *     @return          FALSE - Table values cannot be extracted for all present dimms/ranks
113  *
114  */
115 BOOLEAN
116 MemPGetRttNomWr (
117   IN OUT   MEM_NB_BLOCK *NBPtr,
118   IN       MEM_PSC_TABLE_BLOCK *EntryOfTables
119   )
120 {
121   UINT8 i;
122   UINT8 MaxDimmPerCh;
123   UINT8 NOD;
124   UINT8 TableSize;
125   UINT32 CurDDRrate;
126   UINT8 DDR3Voltage;
127   UINT16 RankTypeOfPopulatedDimm;
128   UINT16 RankTypeInTable;
129   DIMM_TYPE DimmType;
130   CPU_LOGICAL_ID LogicalCpuid;
131   UINT8 PackageType;
132   UINT8 TgtDimmType;
133   UINT8 TgtRank;
134   UINT8 Chipsel;
135   UINT8 PsoCsMaskRtt;
136   UINT16 PsoCsMaskRtt16;
137   UINT8 NoEntryCsMask;
138   PSCFG_RTT_ENTRY *TblPtr;
139   PSCFG_RTT_ENTRY *OrgTblPtr;
140   CH_DEF_STRUCT *CurrentChannel;
141
142   CurrentChannel = NBPtr->ChannelPtr;
143
144   PsoCsMaskRtt = 0;
145   NoEntryCsMask = 0;
146   TblPtr = NULL;
147   TableSize = 0;
148   PackageType = 0;
149   LogicalCpuid.Family = AMD_FAMILY_UNKNOWN;
150   MaxDimmPerCh = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
151   NOD = (UINT8) 1 << (MaxDimmPerCh - 1);
152
153   if (CurrentChannel->RegDimmPresent != 0) {
154     DimmType = RDIMM_TYPE;
155   } else if (CurrentChannel->SODimmPresent != 0) {
156     DimmType = SODIMM_TYPE;
157     if (FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_SOLDERED_DOWN_SODIMM_TYPE, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID, 0, NULL, NULL) != NULL) {
158       DimmType = SODWN_SODIMM_TYPE;
159     }
160   } else if (CurrentChannel->LrDimmPresent != 0) {
161     DimmType = LRDIMM_TYPE;
162   } else {
163     DimmType = UDIMM_TYPE;
164   }
165
166   i = 0;
167   // Obtain table pointer, table size, Logical Cpuid and PSC type according to Dimm, NB and package type.
168   while (EntryOfTables->TblEntryOfDramTerm[i] != NULL) {
169     if (((EntryOfTables->TblEntryOfDramTerm[i])->Header.DimmType & DimmType) != 0) {
170       if (((EntryOfTables->TblEntryOfDramTerm[i])->Header.NumOfDimm & NOD) != 0) {
171         //
172         // Determine if this is the expected NB Type
173         //
174         LogicalCpuid = (EntryOfTables->TblEntryOfDramTerm[i])->Header.LogicalCpuid;
175         PackageType = (EntryOfTables->TblEntryOfDramTerm[i])->Header.PackageType;
176         if (MemPIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
177           TblPtr = (PSCFG_RTT_ENTRY *) ((EntryOfTables->TblEntryOfDramTerm[i])->TBLPtr);
178           TableSize = (EntryOfTables->TblEntryOfDramTerm[i])->TableSize;
179           break;
180         }
181       }
182     }
183     i++;
184   }
185
186   // Check whether no table entry is found.
187   if (EntryOfTables->TblEntryOfDramTerm[i] == NULL) {
188     IDS_HDT_CONSOLE (MEM_FLOW, "\nNo RTT table\n");
189     return FALSE;
190   }
191
192   CurDDRrate = (UINT32) (1 << (CurrentChannel->DCTPtr->Timings.Speed / 66));
193   DDR3Voltage = (UINT8) (1 << CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage));
194   RankTypeOfPopulatedDimm = MemPGetPsRankType (CurrentChannel);
195
196   OrgTblPtr = TblPtr;
197   for (Chipsel = 0; Chipsel < MAX_CS_PER_CHANNEL; Chipsel++) {
198     TblPtr = OrgTblPtr;
199     if ((NBPtr->DCTPtr->Timings.CsPresent & (UINT16) (1 << Chipsel)) != 0) {
200       if ((CurrentChannel->DimmQrPresent & (UINT8) (1 << (Chipsel >> 1))) != 0) {
201         TgtDimmType = DIMM_QR;
202         TgtRank = (UINT8) ((Chipsel < 4) ? 1 << (Chipsel & 1) : 4 << (Chipsel & 1));
203       } else if ((CurrentChannel->DimmDrPresent & (UINT8) (1 << (Chipsel >> 1))) != 0) {
204         TgtDimmType = DIMM_DR;
205         TgtRank = (UINT8) 1 << (Chipsel & 1);
206       } else {
207         TgtDimmType = DIMM_SR;
208         TgtRank = (UINT8) 1 << (Chipsel & 1);
209       }
210
211       if (DimmType == LRDIMM_TYPE) {
212         TgtDimmType = _DONT_CARE;
213         TgtRank = _DONT_CARE;
214       }
215
216       for (i = 0; i < TableSize; i++) {
217         MemPConstructRankTypeMap ((UINT16) TblPtr->Dimm0, (UINT16) TblPtr->Dimm1, (UINT16) TblPtr->Dimm2, &RankTypeInTable);
218         if (TblPtr->DimmPerCh == MaxDimmPerCh) {
219           if ((TblPtr->DDRrate & CurDDRrate) != 0) {
220             if ((TblPtr->VDDIO & DDR3Voltage) != 0) {
221               if ((RankTypeInTable & RankTypeOfPopulatedDimm) == RankTypeOfPopulatedDimm) {
222                 if (((TblPtr->Dimm & TgtDimmType) != 0) || (TgtDimmType == _DONT_CARE)) {
223                   if (((TblPtr->Rank & TgtRank) != 0) || (TgtRank == _DONT_CARE)) {
224                     NBPtr->PsPtr->RttNom[Chipsel] = (UINT8) TblPtr->RttNom;
225                     NBPtr->PsPtr->RttWr[Chipsel] = (UINT8) TblPtr->RttWr;
226                     break;
227                   }
228                 }
229               }
230             }
231           }
232         }
233         TblPtr++;
234       }
235       // Record which Cs(s) have no entries. Later on, we will check if there are overriding values for them.
236       if ((i == TableSize) && (NBPtr->SharedPtr->VoltageMap == VDDIO_DETERMINED)) {
237         NoEntryCsMask |= (UINT8) 1 << Chipsel;
238       }
239     }
240   }
241
242   PsoCsMaskRtt16 = MemPProceedTblDrvOverride (NBPtr, NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_TBLDRV_ODT_RTTNOM);
243   PsoCsMaskRtt16 &= MemPProceedTblDrvOverride (NBPtr, NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_TBLDRV_ODT_RTTWR);
244   //
245   // Check to see if invalid entry exist ?
246   //
247   if ((PsoCsMaskRtt16 & INVALID_CONFIG_FLAG) != 0) {
248     IDS_HDT_CONSOLE (MEM_FLOW, "\nInvalid entry is found\n\n");
249     return FALSE;
250   }
251
252   //
253   // If there are no entries for certain Cs(s), we need to check if overriding values (both RttNom and RttWr) existed for them.
254   // Otherwise, return FALSE.
255   //
256   PsoCsMaskRtt = (UINT8) PsoCsMaskRtt16;
257   if (NoEntryCsMask != 0) {
258     if ((PsoCsMaskRtt & NoEntryCsMask) != NoEntryCsMask) {
259       IDS_HDT_CONSOLE (MEM_FLOW, "\nNo Rtt entries\n");
260       PutEventLog (AGESA_ERROR, MEM_ERROR_RTT_NOT_FOUND, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
261       SetMemError (AGESA_ERROR, NBPtr->MCTPtr);
262       if (!NBPtr->MemPtr->ErrorHandling (NBPtr->MCTPtr, NBPtr->Dct, EXCLUDE_ALL_CHIPSEL, &NBPtr->MemPtr->StdHeader)) {
263         ASSERT (FALSE);
264       }
265       return FALSE;
266     }
267   }
268
269   return TRUE;
270 }