AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Mem / Feat / PARTRN / mfParallelTraining.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mfParallelTraining.c
6  *
7  * This is the parallel training feature
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/Feat/PARTRN)
12  * @e \$Revision: 50871 $ @e \$Date: 2011-04-14 15:39:51 -0600 (Thu, 14 Apr 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
49 #include "AGESA.h"
50 #include "amdlib.h"
51 #include "OptionMemory.h"
52 #include "mm.h"
53 #include "mn.h"
54 #include "Ids.h"
55 #include "cpuRegisters.h"
56 #include "cpuApicUtilities.h"
57 #include "mfParallelTraining.h"
58 #include "heapManager.h"
59 #include "GeneralServices.h"
60 #include "Filecode.h"
61 CODE_GROUP (G2_PEI)
62 RDATA_GROUP (G2_PEI)
63
64 #define FILECODE PROC_MEM_FEAT_PARTRN_MFPARALLELTRAINING_FILECODE
65
66 /*-----------------------------------------------------------------------------
67  *                                EXPORTED FUNCTIONS
68  *
69  *-----------------------------------------------------------------------------
70  */
71 extern MEM_TECH_CONSTRUCTOR* memTechInstalled[];
72
73 /* -----------------------------------------------------------------------------*/
74 /**
75  *
76  *
77  *    This is the main function to perform parallel training on all nodes.
78  *    This is the routine which will run on the remote AP.
79  *
80  *     @param[in,out]   *EnvPtr   - Pointer to the Training Environment Data
81  *     @param[in,out]   *StdHeader   - Pointer to the Standard Header of the AP
82  *
83  *     @return          TRUE -  This feature is enabled.
84  *     @return          FALSE - This feature is not enabled.
85  */
86 BOOLEAN
87 MemFParallelTraining (
88   IN OUT   REMOTE_TRAINING_ENV *EnvPtr,
89   IN OUT   AMD_CONFIG_PARAMS *StdHeader
90   )
91 {
92   MEM_PARAMETER_STRUCT ParameterList;
93   MEM_NB_BLOCK NB;
94   MEM_TECH_BLOCK TB;
95   ALLOCATE_HEAP_PARAMS AllocHeapParams;
96   MEM_DATA_STRUCT *MemPtr;
97   DIE_STRUCT *MCTPtr;
98   UINT8 p;
99   UINT8 i;
100   UINT8 Dct;
101   UINT8 Channel;
102   UINT8 *BufferPtr;
103   UINT8 DctCount;
104   UINT8 ChannelCount;
105   UINT8 RowCount;
106   UINT8 ColumnCount;
107   UINT16 SizeOfNewBuffer;
108   AP_DATA_TRANSFER ReturnData;
109
110   //
111   // Initialize Parameters
112   //
113   ReturnData.DataPtr = NULL;
114   ReturnData.DataSizeInDwords = 0;
115   ReturnData.DataTransferFlags = 0;
116
117   ASSERT (EnvPtr != NULL);
118   //
119   // Replace Standard header of a AP
120   //
121   LibAmdMemCopy (StdHeader, &(EnvPtr->StdHeader), sizeof (AMD_CONFIG_PARAMS), &(EnvPtr->StdHeader));
122
123
124   //
125   //  Allocate buffer for training data
126   //
127   BufferPtr = (UINT8 *) (&EnvPtr->DieStruct);
128   DctCount = EnvPtr->DieStruct.DctCount;
129   BufferPtr += sizeof (DIE_STRUCT);
130   ChannelCount = ((DCT_STRUCT *) BufferPtr)->ChannelCount;
131   BufferPtr += DctCount * sizeof (DCT_STRUCT);
132   RowCount = ((CH_DEF_STRUCT *) BufferPtr)->RowCount;
133   ColumnCount = ((CH_DEF_STRUCT *) BufferPtr)->ColumnCount;
134
135   SizeOfNewBuffer = sizeof (DIE_STRUCT) +
136                     DctCount * (
137                       sizeof (DCT_STRUCT) + (
138                         ChannelCount * (
139                           sizeof (CH_DEF_STRUCT) + sizeof (MEM_PS_BLOCK) + (
140                             RowCount * ColumnCount * NUMBER_OF_DELAY_TABLES +
141                             (MAX_BYTELANES_PER_CHANNEL * MAX_CS_PER_CHANNEL * NUMBER_OF_FAILURE_MASK_TABLES) +
142                             (MAX_DIMMS_PER_CHANNEL * MAX_NUMBER_LANES)
143                           )
144                         )
145                       )
146                     );
147   AllocHeapParams.RequestedBufferSize = SizeOfNewBuffer;
148   AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_PAR_TRN_HANDLE, 0, 0, 0);
149   AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
150   if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
151     BufferPtr = AllocHeapParams.BufferPtr;
152     LibAmdMemCopy ( BufferPtr,
153                     &(EnvPtr->DieStruct),
154                     sizeof (DIE_STRUCT) + DctCount * (sizeof (DCT_STRUCT) + ChannelCount * (sizeof (CH_DEF_STRUCT) + sizeof (MEM_PS_BLOCK))),
155                     StdHeader
156                   );
157
158     //
159     //  Fix up pointers
160     //
161     MCTPtr = (DIE_STRUCT *) BufferPtr;
162     BufferPtr += sizeof (DIE_STRUCT);
163     MCTPtr->DctData = (DCT_STRUCT *) BufferPtr;
164     BufferPtr += MCTPtr->DctCount * sizeof (DCT_STRUCT);
165     for (Dct = 0; Dct < MCTPtr->DctCount; Dct++) {
166       MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) BufferPtr;
167       BufferPtr += MCTPtr->DctData[Dct].ChannelCount * sizeof (CH_DEF_STRUCT);
168       for (Channel = 0; Channel < MCTPtr->DctData[Dct].ChannelCount; Channel++) {
169         MCTPtr->DctData[Dct].ChData[Channel].MCTPtr = MCTPtr;
170         MCTPtr->DctData[Dct].ChData[Channel].DCTPtr = &MCTPtr->DctData[Dct];
171       }
172     }
173     NB.PSBlock = (MEM_PS_BLOCK *) BufferPtr;
174     BufferPtr += DctCount * ChannelCount * sizeof (MEM_PS_BLOCK);
175
176     ReturnData.DataPtr = AllocHeapParams.BufferPtr;
177     ReturnData.DataSizeInDwords = (SizeOfNewBuffer + 3) / 4;
178     ReturnData.DataTransferFlags = 0;
179
180     //
181     // Allocate Memory for the MEM_DATA_STRUCT we will use
182     //
183     AllocHeapParams.RequestedBufferSize = sizeof (MEM_DATA_STRUCT);
184     AllocHeapParams.BufferHandle = AMD_MEM_DATA_HANDLE;
185     AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
186     if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
187       MemPtr = (MEM_DATA_STRUCT *)AllocHeapParams.BufferPtr;
188
189       LibAmdMemCopy (&(MemPtr->StdHeader), &(EnvPtr->StdHeader), sizeof (AMD_CONFIG_PARAMS), StdHeader);
190
191       //
192       // Copy Parameters from environment
193       //
194       ParameterList.HoleBase = EnvPtr->HoleBase;
195       ParameterList.BottomIo = EnvPtr->BottomIo;
196       ParameterList.UmaSize = EnvPtr->UmaSize;
197       ParameterList.SysLimit = EnvPtr->SysLimit;
198       ParameterList.TableBasedAlterations = EnvPtr->TableBasedAlterations;
199       ParameterList.PlatformMemoryConfiguration = EnvPtr->PlatformMemoryConfiguration;
200       MemPtr->ParameterListPtr = &ParameterList;
201
202       for (p = 0; p < MAX_PLATFORM_TYPES; p++) {
203         MemPtr->GetPlatformCfg[p] = EnvPtr->GetPlatformCfg[p];
204       }
205
206       MemPtr->ErrorHandling = EnvPtr->ErrorHandling;
207       //
208       // Create Local NBBlock and Tech Block
209       //
210       EnvPtr->NBBlockCtor (&NB, MCTPtr, EnvPtr->FeatPtr);
211       NB.RefPtr = &ParameterList;
212       NB.MemPtr = MemPtr;
213       i = 0;
214       while (memTechInstalled[i] != NULL) {
215         if (memTechInstalled[i] (&TB, &NB)) {
216           break;
217         }
218         i++;
219       }
220       NB.TechPtr = &TB;
221       NB.TechBlockSwitch (&NB);
222
223       //
224       // Setup CPU Mem Type MSRs on the AP
225       //
226       NB.CpuMemTyping (&NB);
227
228       IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", NB.Node);
229       //
230       // Call Technology Specific Training routine
231       //
232       NB.TrainingFlow (&NB);
233       //
234       // Copy training data to ReturnData buffer
235       //
236       LibAmdMemCopy ( BufferPtr,
237                       MCTPtr->DctData[0].ChData[0].RcvEnDlys,
238                       ((DctCount * ChannelCount) * (
239                          (RowCount * ColumnCount * NUMBER_OF_DELAY_TABLES) +
240                          (MAX_BYTELANES_PER_CHANNEL * MAX_CS_PER_CHANNEL * NUMBER_OF_FAILURE_MASK_TABLES) +
241                          (MAX_DIMMS_PER_CHANNEL * MAX_NUMBER_LANES)
242                         )
243                       ),
244                       StdHeader);
245
246       HeapDeallocateBuffer (AMD_MEM_DATA_HANDLE, StdHeader);
247       //
248       // Restore pointers
249       //
250       for (Dct = 0; Dct < MCTPtr->DctCount; Dct++) {
251         for (Channel = 0; Channel < MCTPtr->DctData[Dct].ChannelCount; Channel++) {
252           MCTPtr->DctData[Dct].ChData[Channel].MCTPtr = &EnvPtr->DieStruct;
253           MCTPtr->DctData[Dct].ChData[Channel].DCTPtr = &EnvPtr->DieStruct.DctData[Dct];
254
255           MCTPtr->DctData[Dct].ChData[Channel].RcvEnDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RcvEnDlys;
256           MCTPtr->DctData[Dct].ChData[Channel].WrDqsDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].WrDqsDlys;
257           MCTPtr->DctData[Dct].ChData[Channel].RdDqsDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RdDqsDlys;
258           MCTPtr->DctData[Dct].ChData[Channel].RdDqsDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RdDqsDlys;
259           MCTPtr->DctData[Dct].ChData[Channel].WrDatDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].WrDatDlys;
260           MCTPtr->DctData[Dct].ChData[Channel].RdDqs__Dlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RdDqs__Dlys;
261           MCTPtr->DctData[Dct].ChData[Channel].RdDqsMinDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RdDqsMinDlys;
262           MCTPtr->DctData[Dct].ChData[Channel].RdDqsMaxDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].RdDqsMaxDlys;
263           MCTPtr->DctData[Dct].ChData[Channel].WrDatMinDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].WrDatMinDlys;
264           MCTPtr->DctData[Dct].ChData[Channel].WrDatMaxDlys = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].WrDatMaxDlys;
265           MCTPtr->DctData[Dct].ChData[Channel].FailingBitMask = EnvPtr->DieStruct.DctData[Dct].ChData[Channel].FailingBitMask;
266         }
267         MCTPtr->DctData[Dct].ChData = EnvPtr->DieStruct.DctData[Dct].ChData;
268       }
269       MCTPtr->DctData = EnvPtr->DieStruct.DctData;
270     }
271
272     //
273     // Signal to BSP that training is complete and Send Results
274     //
275     ASSERT (ReturnData.DataPtr != NULL);
276     ApUtilTransmitBuffer (EnvPtr->BspSocket, EnvPtr->BspCore, &ReturnData, StdHeader);
277
278     //
279     // Clean up and exit.
280     //
281     HeapDeallocateBuffer (GENERATE_MEM_HANDLE (ALLOC_PAR_TRN_HANDLE, 0, 0, 0), StdHeader);
282   } else {
283     MCTPtr = &EnvPtr->DieStruct;
284     PutEventLog (AGESA_FATAL, MEM_ERROR_HEAP_ALLOCATE_FOR_TRAINING_DATA, MCTPtr->NodeId, 0, 0, 0, StdHeader);
285     SetMemError (AGESA_FATAL, MCTPtr);
286     ASSERT(FALSE); // Could not allocate heap for buffer for parallel training data
287   }
288   return TRUE;
289 }