AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Mem / Main / mmStandardTraining.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mmStandardTraining.c
6  *
7  * Main Memory Feature implementation file for Standard Training
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/Main)
12  * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 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  *----------------------------------------------------------------------------
48  *                                MODULES USED
49  *
50  *----------------------------------------------------------------------------
51  */
52
53
54 #include "Porting.h"
55 #include "AGESA.h"
56 #include "Ids.h"
57 #include "cpuRegisters.h"
58 #include "cpuServices.h"
59 #include "OptionMemory.h"
60 #include "mm.h"
61 #include "mn.h"
62 #include "mt.h"
63 #include "ma.h"
64 #include "Filecode.h"
65 CODE_GROUP (G1_PEICC)
66 RDATA_GROUP (G2_PEI)
67
68 #define FILECODE PROC_MEM_MAIN_MMSTANDARDTRAINING_FILECODE
69 /* features */
70 #include "mftds.h"
71 /*----------------------------------------------------------------------------
72  *                        PROTOTYPES OF LOCAL FUNCTIONS
73  *
74  *----------------------------------------------------------------------------
75  */
76
77 BOOLEAN
78 MemMStandardTraining (
79   IN OUT   MEM_MAIN_DATA_BLOCK *mmPtr
80   );
81
82 BOOLEAN
83 MemMStandardTrainingUsingAdjacentDies (
84   IN OUT   MEM_MAIN_DATA_BLOCK *mmPtr
85   );
86
87 /*-----------------------------------------------------------------------------
88 *                                EXPORTED FUNCTIONS
89 *
90 *-----------------------------------------------------------------------------
91 */
92 extern MEM_FEAT_TRAIN_SEQ memTrainSequenceDDR3[];
93 /* -----------------------------------------------------------------------------*/
94 /**
95  *
96  * MemMStandardTraining
97  *
98  * This function implements standard memory training whereby training functions
99  * for all nodes are run by the BSP.
100  *
101  *
102  *     @param[in,out]   *mmPtr   - Pointer to the MEM_MAIN_DATA_BLOCK
103  *
104  *     @return          TRUE -  No fatal error occurs.
105  *     @return          FALSE - Fatal error occurs.
106  */
107 BOOLEAN
108 MemMStandardTraining (
109   IN OUT   MEM_MAIN_DATA_BLOCK *mmPtr
110   )
111 {
112   UINT8 Die;
113   //
114   // Run Northbridge-specific Standard Training feature for each die.
115   //
116   IDS_HDT_CONSOLE (MEM_STATUS, "\nStart serial training\n");
117   for (Die = 0 ; Die < mmPtr->DieCount ; Die ++ ) {
118     IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", Die);
119     AGESA_TESTPOINT (TpProcMemBeforeAnyTraining, &(mmPtr->MemPtr->StdHeader));
120     mmPtr->NBPtr[Die].BeforeDqsTraining (&mmPtr->NBPtr[Die]);
121     mmPtr->NBPtr[Die].Execute1dMaxRdLatTraining = TRUE;
122     mmPtr->NBPtr[Die].FeatPtr->Training (&mmPtr->NBPtr[Die]);
123     mmPtr->NBPtr[Die].TechPtr->TechnologySpecificHook[LrdimmSyncTrainedDlys] (mmPtr->NBPtr[Die].TechPtr, NULL);
124     mmPtr->NBPtr[Die].AfterDqsTraining (&mmPtr->NBPtr[Die]);
125     if (mmPtr->NBPtr[Die].MCTPtr->ErrCode == AGESA_FATAL) {
126       break;
127     }
128   }
129   return (BOOLEAN) (Die == mmPtr->DieCount);
130 }
131
132 /* -----------------------------------------------------------------------------*/
133 /**
134  *
135  * MemMStandardTrainingUsingAdjacentDies
136  *
137  * This function implements standard memory training whereby training functions
138  * for all nodes are run by the BSP while enabling other dies to eable argressor channel
139  *
140  *
141  *     @param[in,out]   *mmPtr   - Pointer to the MEM_MAIN_DATA_BLOCK
142  *
143  *     @return          TRUE -  No fatal error occurs.
144  *     @return          FALSE - Fatal error occurs.
145  */
146 BOOLEAN
147 MemMStandardTrainingUsingAdjacentDies (
148   IN OUT   MEM_MAIN_DATA_BLOCK *mmPtr
149   )
150 {
151   UINT8 Die;
152   UINT8 AdjacentDie;
153   UINT32 AdjacentSocketNum;
154   UINT32 TargetSocketNum;
155   UINT32 ModuleNum;
156   UINT8 i;
157   UINT8 Dct;
158   UINT8 ChipSel;
159   BOOLEAN FirstCsFound;
160   //
161   // Run Northbridge-specific Standard Training feature for each die.
162   //
163   IDS_HDT_CONSOLE (MEM_STATUS, "\nStart standard serial training\n");
164   for (Die = 0 ; Die < mmPtr->DieCount ; Die ++ ) {
165     IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", Die);
166     AGESA_TESTPOINT (TpProcMemBeforeAnyTraining, &(mmPtr->MemPtr->StdHeader));
167     mmPtr->NBPtr[Die].BeforeDqsTraining (&mmPtr->NBPtr[Die]);
168     mmPtr->NBPtr[Die].Execute1dMaxRdLatTraining = FALSE;
169     mmPtr->NBPtr[Die].FeatPtr->Training (&mmPtr->NBPtr[Die]);
170     if (mmPtr->NBPtr[Die].MCTPtr->ErrCode == AGESA_FATAL) {
171       break;
172     }
173   }
174   IDS_HDT_CONSOLE (MEM_STATUS, "\nStart training with agressors\n");
175   for (Die = 0 ; Die < mmPtr->DieCount ; Die ++ ) {
176     IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", Die);
177     AGESA_TESTPOINT (TpProcMemBeforeAnyTraining, &(mmPtr->MemPtr->StdHeader));
178     GetSocketModuleOfNode (Die, &TargetSocketNum, &ModuleNum, &(mmPtr->MemPtr->StdHeader));
179     for (AdjacentDie = 0; AdjacentDie < mmPtr->DieCount; AdjacentDie++) {
180       mmPtr->NBPtr[Die].DieEnabled[AdjacentDie] = FALSE;
181       GetSocketModuleOfNode (AdjacentDie, &AdjacentSocketNum, &ModuleNum, &(mmPtr->MemPtr->StdHeader));
182       if (TargetSocketNum == AdjacentSocketNum) {
183         if (AdjacentDie != Die) {
184           if (mmPtr->NBPtr[AdjacentDie].MCTPtr->NodeMemSize != 0) {
185             mmPtr->NBPtr[Die].AdjacentDieNBPtr = &mmPtr->NBPtr[AdjacentDie];
186             mmPtr->NBPtr[Die].DieEnabled[AdjacentDie] = TRUE;
187           }
188         } else {
189           if (mmPtr->NBPtr[Die].MCTPtr->NodeMemSize != 0) {
190             mmPtr->NBPtr[Die].DieEnabled[Die] = TRUE;
191           }
192         }
193         // Determine the initial target CS, Max Dimms and max CS number for all DCTs (potential aggressors)
194         if (mmPtr->NBPtr[AdjacentDie].MCTPtr->NodeMemSize != 0) {
195           for (Dct = 0; Dct < mmPtr->NBPtr[AdjacentDie].DctCount; Dct++) {
196             FirstCsFound = FALSE;
197             mmPtr->NBPtr[AdjacentDie].SwitchDCT (&mmPtr->NBPtr[AdjacentDie], Dct);
198             for (ChipSel = 0; ChipSel < mmPtr->NBPtr[AdjacentDie].CSPerChannel (&mmPtr->NBPtr[AdjacentDie]); ChipSel = ChipSel + mmPtr->NBPtr[AdjacentDie].CSPerDelay (&mmPtr->NBPtr[AdjacentDie]) ) {
199               if ((mmPtr->NBPtr[AdjacentDie].DCTPtr->Timings.CsEnabled & ((UINT16) 1 << ChipSel)) != 0) {
200                 if (FirstCsFound == FALSE) {
201                   // Set Initial CS value for Current Aggressor CS
202                   mmPtr->NBPtr[AdjacentDie].InitialAggressorCSTarget[Dct] = ChipSel;
203                   mmPtr->NBPtr[AdjacentDie].CurrentAggressorCSTarget[Dct] = mmPtr->NBPtr[AdjacentDie].InitialAggressorCSTarget[Dct];
204                   FirstCsFound = TRUE;
205                 }
206                 mmPtr->NBPtr[AdjacentDie].MaxAggressorCSEnabled[Dct] = ChipSel;
207                 mmPtr->NBPtr[AdjacentDie].MaxAggressorDimms[Dct]++;
208               }
209             }
210           }
211         }
212       }
213     }
214     if (mmPtr->NBPtr[Die].MCTPtr->NodeMemSize != 0) {
215       //Execute Technology specific training features
216       i = 0;
217       while (memTrainSequenceDDR3[i].TrainingSequenceEnabled != 0) {
218         if (memTrainSequenceDDR3[i].TrainingSequenceEnabled (&mmPtr->NBPtr[Die])) {
219           mmPtr->NBPtr[Die].TrainingSequenceIndex = i;
220           // Execute RdDqs Training
221           memTrainSequenceDDR3[i].MemTechFeatBlock->RdDqs__Training (mmPtr->NBPtr[Die].TechPtr);
222           // Execute MaxRdLat Training After training
223           do {
224             if (memTrainSequenceDDR3[i].MemTechFeatBlock->MaxRdLatencyTraining (mmPtr->NBPtr[Die].TechPtr)) {
225               MemFInitTableDrive (&mmPtr->NBPtr[Die], MTAfterMaxRdLatTrn);
226             }
227           } while (mmPtr->NBPtr->ChangeNbFrequency (&mmPtr->NBPtr[Die]));
228           break;
229         }
230         i++;
231       }
232     }
233     mmPtr->NBPtr[Die].TechPtr->TechnologySpecificHook[LrdimmSyncTrainedDlys] (mmPtr->NBPtr[Die].TechPtr, NULL);
234     mmPtr->NBPtr[Die].AfterDqsTraining (&mmPtr->NBPtr[Die]);
235     if (mmPtr->NBPtr[Die].MCTPtr->ErrCode == AGESA_FATAL) {
236       break;
237     }
238   }
239   return (BOOLEAN) (Die == mmPtr->DieCount);
240 }
241