AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Recovery / Mem / NB / C32 / mrnc32.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mrnc32.c
6  *
7  * Common Northbridge  functions for C32 Recovery
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Proc/Recovery/Mem)
12  * @e \$Revision: 48317 $ @e \$Date: 2011-03-07 10:38:14 -0700 (Mon, 07 Mar 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
55 #include "AGESA.h"
56 #include "amdlib.h"
57 #include "Ids.h"
58 #include "mrport.h"
59 #include "cpuFamRegisters.h"
60 #include "cpuRegisters.h"
61 #include "cpuFamilyTranslation.h"
62 #include "mm.h"
63 #include "mn.h"
64 #include "mrnc32.h"
65 #include "heapManager.h"
66 #include "AdvancedApi.h"
67 #include "Filecode.h"
68 CODE_GROUP (G2_PEI)
69 RDATA_GROUP (G2_PEI)
70
71 #define FILECODE PROC_RECOVERY_MEM_NB_C32_MRNC32_FILECODE
72 /*----------------------------------------------------------------------------
73  *                          DEFINITIONS AND MACROS
74  *
75  *----------------------------------------------------------------------------
76  */
77 #define MAX_DIES_PER_SOCKET     2
78 #define MAX_DCTS_PER_DIE 2
79 #define SPLIT_CHANNEL   0x20000000
80 #define CHANNEL_SELECT  0x10000000
81 #define MAX_DELAYS    9   /* 8 data bytes + 1 ECC byte */
82 #define MAX_DIMMS     4   /* 4 DIMMs per channel */
83
84 /*----------------------------------------------------------------------------
85  *                           TYPEDEFS AND STRUCTURES
86  *
87  *----------------------------------------------------------------------------
88  */
89
90 /*----------------------------------------------------------------------------
91  *                        PROTOTYPES OF LOCAL FUNCTIONS
92  *
93  *----------------------------------------------------------------------------
94  */
95
96 VOID
97 STATIC
98 MemRecNInitNBRegTableC32 (
99   IN OUT   TSEFO *NBRegTable
100   );
101
102 UINT32
103 STATIC
104 MemRecNCmnGetSetFieldC32 (
105   IN OUT   MEM_NB_BLOCK *NBPtr,
106   IN       UINT8 IsSet,
107   IN       BIT_FIELD_NAME FieldName,
108   IN       UINT32 Field
109   );
110
111 UINT32
112 STATIC
113 MemRecNcmnGetSetTrainDlyC32 (
114   IN OUT   MEM_NB_BLOCK *NBPtr,
115   IN       UINT8 IsSet,
116   IN       TRN_DLY_TYPE TrnDly,
117   IN       DRBN DrbnVar,
118   IN       UINT16 Field
119   );
120
121 BOOLEAN
122 STATIC
123 MemRecNIsIdSupportedC32 (
124   IN OUT   MEM_NB_BLOCK *NBPtr,
125   IN       CPU_LOGICAL_ID *LogicalIdPtr
126   );
127
128 VOID
129 STATIC
130 MemRecNSwitchNodeC32 (
131   IN OUT   MEM_NB_BLOCK *NBPtr,
132   IN       UINT8 NodeID
133   );
134
135
136 /*----------------------------------------------------------------------------
137  *                            EXPORTED FUNCTIONS
138  *
139  *----------------------------------------------------------------------------
140  */
141 STATIC CONST UINT32 RecModeDefRegArrayC32[] = {
142   BFDramControlReg,  0x320C2A06,
143   BFDramBankAddrReg, 0x00001111,
144   BFDramMRSReg,      0x000400A4,
145   BFDramTimingLoReg, 0x000A0092,
146   BFDramTimingHiReg, 0xB6D218FF,
147   BFDramConfigLoReg, 0x00000000,
148   BFDramConfigHiReg, 0x1F48010B,
149   NULL
150 };
151
152 /* -----------------------------------------------------------------------------*/
153 /**
154  *
155  *   This function initializes the northbridge block
156  *
157  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
158  *     @param[in,out]   *MemPtr  - Pointer to the MEM_DATA_STRUCT
159  *     @param[in]       NodeID   - Node ID for this NB block
160  *
161  *     @return          TRUE  - This node is a C32 and this NB block has been initialized
162  *     @return          FALSE - This node is not a C32
163  */
164
165 BOOLEAN
166 MemRecConstructNBBlockC32 (
167   IN OUT   MEM_NB_BLOCK *NBPtr,
168   IN OUT   MEM_DATA_STRUCT *MemPtr,
169   IN       UINT8 NodeID
170   )
171 {
172   UINT8 i;
173   UINT8 Dct;
174   UINT8 Channel;
175   DIE_STRUCT *MCTPtr;
176   ALLOCATE_HEAP_PARAMS AllocHeapParams;
177
178   //
179   // Determine if this is the expected NB Type
180   //
181   GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
182   if (!MemRecNIsIdSupportedC32 (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) {
183     return FALSE;
184   }
185
186   //
187   // Allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs
188   //
189   MCTPtr = &MemPtr->DiesPerSystem[NodeID];
190   AllocHeapParams.RequestedBufferSize = MAX_DCTS_PER_NODE_C32 * (
191                                           sizeof (DCT_STRUCT) + (
192                                             MAX_CHANNELS_PER_DCT_C32 * (
193                                               sizeof (CH_DEF_STRUCT) + (
194                                                 MAX_DIMMS * MAX_DELAYS * NUMBER_OF_DELAY_TABLES
195                                               )
196                                             )
197                                           )
198                                         ) + (sizeof (TSEFO) * BFEndOfList);
199   AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DCT_STRUCT_HANDLE, NodeID, 0, 0);
200   AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
201   if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) {
202     return FALSE;
203   }
204
205   MemPtr->DieCount = MAX_DIES_PER_SOCKET;
206   MCTPtr->DctCount = MAX_DCTS_PER_NODE_C32;
207   MCTPtr->DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
208   MemPtr->DiesPerSystem[NodeID + 1].DctCount = MAX_DCTS_PER_NODE_C32;
209   MemPtr->DiesPerSystem[NodeID + 1].DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
210   AllocHeapParams.BufferPtr += MAX_DCTS_PER_NODE_C32 * sizeof (DCT_STRUCT);
211   for (Dct = 0; Dct < MAX_DCTS_PER_NODE_C32; Dct++) {
212     MCTPtr->DctData[Dct].Dct = Dct;
213     MCTPtr->DctData[Dct].ChannelCount = MAX_CHANNELS_PER_DCT_C32;
214     MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) AllocHeapParams.BufferPtr;
215     MCTPtr->DctData[Dct].ChData[0].ChannelID = (MCTPtr->DieId * 2) + Dct;
216     AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_C32 * sizeof (CH_DEF_STRUCT);
217     for (Channel = 0; Channel < MAX_CHANNELS_PER_DCT_C32; Channel++) {
218       MCTPtr->DctData[Dct].ChData[Channel].RcvEnDlys = (UINT16 *) AllocHeapParams.BufferPtr;
219       AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS) * 2;
220       MCTPtr->DctData[Dct].ChData[Channel].WrDqsDlys = AllocHeapParams.BufferPtr;
221       MCTPtr->DctData[Dct].ChData[Channel].Dct = Dct;
222       AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS);
223     }
224   }
225
226   //
227   //  Initialize NB block's variables
228   //
229   NBPtr->NBRegTable = (TSEFO *) AllocHeapParams.BufferPtr;
230   NBPtr->MemPtr = MemPtr;
231   NBPtr->RefPtr = MemPtr->ParameterListPtr;
232   NBPtr->MCTPtr = MCTPtr;
233   NBPtr->AllNodeMCTPtr = &MemPtr->DiesPerSystem[NodeID];
234   NBPtr->SPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
235   NBPtr->AllNodeSPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
236
237   NBPtr->DctCachePtr = NBPtr->DctCache;
238
239   MemRecNInitNBRegTableC32 (NBPtr->NBRegTable);
240   NBPtr->Dct = 0;
241   NBPtr->Channel = 0;
242   NBPtr->VarMtrrHiMsk = MemRecGetVarMtrrHiMsk (&(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
243
244   LibAmdMemFill (NBPtr->DctCache, 0, sizeof (NBPtr->DctCache), &NBPtr->MemPtr->StdHeader);
245   LibAmdMemFill (NBPtr->IsSupported, FALSE, sizeof (NBPtr->IsSupported), &NBPtr->MemPtr->StdHeader);
246   for (i = 0; i < NumberOfHooks; i++) {
247     NBPtr->FamilySpecificHook[i] = (BOOLEAN (*) (MEM_NB_BLOCK *, VOID *)) MemRecDefTrue;
248   }
249
250   NBPtr->InitRecovery = MemRecNMemInitNb;
251
252   NBPtr->RecModeDefRegArray = RecModeDefRegArrayC32;
253
254   NBPtr->SwitchNodeRec = MemRecNSwitchNodeC32;
255   NBPtr->SwitchDCT = MemRecNSwitchDctC32;
256   NBPtr->SwitchChannel = MemRecNSwitchChannelC32;
257   NBPtr->SetMaxLatency = MemRecNSetMaxLatencyNb;
258   NBPtr->GetSysAddrRec = MemRecNGetMCTSysAddrNb;
259   NBPtr->SendMrsCmd = MemRecNSendMrsCmdNb;
260   NBPtr->sendZQCmd = MemRecNSendZQCmdNb;
261   NBPtr->SetDramOdtRec = MemRecNSetDramOdtNb;
262
263   NBPtr->GetBitField = MemRecNGetBitFieldNb;
264   NBPtr->SetBitField = MemRecNSetBitFieldNb;
265   NBPtr->GetTrainDly = MemRecNGetTrainDlyNb;
266   NBPtr->SetTrainDly = MemRecNSetTrainDlyNb;
267
268   NBPtr->MemRecNCmnGetSetFieldNb = MemRecNCmnGetSetFieldC32;
269   NBPtr->MemRecNcmnGetSetTrainDlyNb = MemRecNcmnGetSetTrainDlyC32;
270   NBPtr->MemRecNSwitchDctNb = MemRecNSwitchDctC32;
271   NBPtr->TrainingFlow = MemNRecTrainingFlowNb;
272   NBPtr->MemRecNInitializeMctNb = MemRecNInitializeMctC32;
273   NBPtr->MemRecNFinalizeMctNb = MemRecNFinalizeMctC32;
274   NBPtr->IsSupported[DramModeAfterDimmPres] = TRUE;
275   MemRecNSwitchDctC32 (NBPtr, 0);
276
277   return TRUE;
278 }
279
280 /* -----------------------------------------------------------------------------*/
281 /**
282  *
283  *
284  *   This function sets the current die to work on.
285  *   Should be called before accessing a certain die
286  *   All data structures will be updated to point to the current node
287  *
288  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
289  *     @param[in]   NodeID - ID of the target die
290  *
291  */
292
293 VOID
294 STATIC
295 MemRecNSwitchNodeC32 (
296   IN OUT   MEM_NB_BLOCK *NBPtr,
297   IN       UINT8 NodeID
298   )
299 {
300   NBPtr->MCTPtr = &(NBPtr->AllNodeMCTPtr[NodeID]);
301   NBPtr->Node = NodeID;
302   NBPtr->MCTPtr->NodeId = NodeID;
303   MemRecNSwitchDctC32 (NBPtr, NBPtr->Dct);
304 }
305
306 /* -----------------------------------------------------------------------------*/
307 /**
308  *
309  *   This function sets the current DCT to work on.
310  *   Should be called before accessing a certain DCT
311  *   All data structures will be updated to point to the current DCT
312  *
313  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
314  *     @param[in]   Dct - ID of the target DCT
315  *
316  */
317
318 VOID
319 MemRecNSwitchDctC32 (
320   IN OUT   MEM_NB_BLOCK *NBPtr,
321   IN       UINT8 Dct
322   )
323 {
324   NBPtr->Dct = Dct & 1;
325   NBPtr->SPDPtr = &(NBPtr->AllNodeSPDPtr[(NBPtr->MCTPtr->NodeId * MAX_DCTS_PER_DIE + Dct) * MAX_DIMMS_PER_CHANNEL]);
326   NBPtr->DCTPtr = &(NBPtr->MCTPtr->DctData[NBPtr->Dct]);
327
328   MemRecNSwitchChannelC32 (NBPtr, 0);
329 }
330
331 /* -----------------------------------------------------------------------------*/
332 /**
333  *
334  *   This function sets the current channel to work on.
335  *   Should be called before accessing a certain channel
336  *   All data structures will be updated to point to the current channel
337  *
338  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
339  *     @param[in]   Channel - ID of the target channel
340  *
341  */
342
343 VOID
344 MemRecNSwitchChannelC32 (
345   IN OUT   MEM_NB_BLOCK *NBPtr,
346   IN       UINT8 Channel
347   )
348 {
349   NBPtr->Channel = 0;
350   NBPtr->ChannelPtr = &(NBPtr->DCTPtr->ChData[0]);
351 }
352
353 /*----------------------------------------------------------------------------
354  *                              LOCAL FUNCTIONS
355  *
356  *----------------------------------------------------------------------------
357  */
358
359 /* -----------------------------------------------------------------------------*/
360 /**
361  *
362  *   This function gets or set DQS timing during training.
363  *
364  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
365  *     @param[in]   TrnDly - type of delay to be set
366  *     @param[in]   DrbnVar - encoding of Dimm-Rank-Byte-Nibble to be accessed
367  *                  (use either DIMM_BYTE_ACCESS(dimm,byte) or CS_NBBL_ACCESS(cs,nibble) to use this encoding
368  *     @param[in]   Field - Value to be programmed
369  *     @param[in]   IsSet - Indicates if the function will set or get
370  *
371  *     @return      value read, if the function is used as a "get"
372  */
373
374 UINT32
375 STATIC
376 MemRecNcmnGetSetTrainDlyC32 (
377   IN OUT   MEM_NB_BLOCK *NBPtr,
378   IN       UINT8 IsSet,
379   IN       TRN_DLY_TYPE TrnDly,
380   IN       DRBN DrbnVar,
381   IN       UINT16 Field
382   )
383 {
384   UINT16 index;
385   UINT16 offset;
386   UINT32 value;
387   UINT32 address;
388   UINT8 DIMM;
389   UINT8 Rank;
390   UINT8 Byte;
391   UINT8 Nibble;
392
393   DIMM = DRBN_DIMM (DrbnVar);
394   Rank = DRBN_RANK (DrbnVar);
395   Byte = DRBN_BYTE (DrbnVar);
396   Nibble = DRBN_NBBL (DrbnVar);
397
398   switch (TrnDly) {
399   case AccessRcvEnDly:
400     index = 0x10;
401     break;
402   case AccessWrDqsDly:
403     index = 0x30;
404     break;
405   case AccessWrDatDly:
406     index = 0x01;
407     break;
408   case AccessRdDqsDly:
409     index = 0x05;
410     break;
411   case AccessPhRecDly:
412     index = 0x50;
413     break;
414   default:
415     index = 0;
416     IDS_ERROR_TRAP;
417   }
418
419   switch (TrnDly) {
420   case AccessRcvEnDly:
421   case AccessWrDqsDly:
422     index += (DIMM * 3);
423     if ((Byte & 0x04) != 0) {
424       // if byte 4,5,6,7
425       index += 0x10;
426     }
427     if ((Byte & 0x02) != 0) {
428       // if byte 2,3,6,7
429       index++;
430     }
431     if (Byte > 7) {
432       index += 2;
433     }
434     offset = 16 * (Byte % 2);
435     index |= (Rank << 8);
436     index |= (Nibble << 9);
437     break;
438
439   case AccessRdDqsDly:
440     Field &= ~ 0x0001;
441   case AccessWrDatDly:
442     index += (DIMM * 0x100);
443     if (Nibble != 0) {
444       if (Rank != 0) {
445         index += 0xA0;
446       } else {
447         index += 0x70;
448       }
449     } else if (Rank != 0) {
450       index += 0x60;
451     }
452     // break is not being used here because AccessRdDqsDly and AccessWrDatDly also need
453     // to run AccessPhRecDly sequence.
454   case AccessPhRecDly:
455     index += (Byte / 4);
456     offset = 8 * (Byte % 4);
457     break;
458   default:
459     offset = 0;
460     IDS_ERROR_TRAP;
461   }
462
463   address = index;
464   MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, address);
465   while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
466   value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
467
468   if (IsSet != 0) {
469     if (TrnDly == AccessPhRecDly) {
470       value = NBPtr->DctCachePtr->PhRecReg[index & 0x03];
471     }
472
473     value = ((UINT32)Field << offset) | (value & (~((UINT32)0xFF << offset)));
474     MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, value);
475     address |= DCT_ACCESS_WRITE;
476     MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, address);
477     while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
478
479     if (TrnDly == AccessPhRecDly) {
480       NBPtr->DctCachePtr->PhRecReg[index & 0x03] = value;
481     }
482   } else {
483     value = (value >> offset) & 0xFF;
484   }
485
486   return value;
487 }
488
489 /* -----------------------------------------------------------------------------*/
490 /**
491  *
492  *   This function gets or sets a value to a bit field in a PCI register.
493  *
494  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
495  *     @param[in]   FieldName - Name of Field to be set
496  *     @param[in]   Field - Value to be programmed
497  *     @param[in]   IsSet - Indicates if the function will set or get
498  *
499  *     @return      value read, if the function is used as a "get"
500  */
501
502 UINT32
503 STATIC
504 MemRecNCmnGetSetFieldC32 (
505   IN OUT   MEM_NB_BLOCK *NBPtr,
506   IN       UINT8 IsSet,
507   IN       BIT_FIELD_NAME FieldName,
508   IN       UINT32 Field
509   )
510 {
511   SBDFO Address;
512   PCI_ADDR PciAddr;
513   UINT8 Type;
514   UINT32 Value;
515   UINT32 Highbit;
516   UINT32 Lowbit;
517   UINT32 Mask;
518
519   Value = 0;
520   if (FieldName < BFEndOfList) {
521     Address = NBPtr->NBRegTable[FieldName];
522     if (Address != 0) {
523       Lowbit = TSEFO_END (Address);
524       Highbit = TSEFO_START (Address);
525       Type = TSEFO_TYPE (Address);
526
527       // If Fn2 and DCT1 selected, set Address to be 1xx
528       if (((Address & 0xF000) == 0x2000) && (NBPtr->Dct != 0)) {
529         Address |= 0x0100;
530       }
531       if ((Address >> 29) == ((DCT_PHY_ACCESS << 1) | 1)) {
532         // Special DCT Phy access
533         Address &= 0x0FFFFFFF;
534         Lowbit = 0;
535         Highbit = 16;
536       } else {
537         // Normal DCT Phy access
538         Address = TSEFO_OFFSET (Address);
539       }
540
541
542       if (Type == NB_ACCESS) {
543         // Address |= (((UINT32) (24 + 0)) << 15);
544         PciAddr.AddressValue = Address;
545         // Fix for MCM
546         PciAddr.Address.Device = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Device;
547         PciAddr.Address.Bus = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Bus;
548         PciAddr.Address.Segment = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Segment;
549         Address = PciAddr.AddressValue;
550         LibAmdPciRead (AccessWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
551       } else if (Type == DCT_PHY_ACCESS) {
552         MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
553         while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
554
555         Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
556       } else {
557         IDS_ERROR_TRAP;
558       }
559
560       if (IsSet != 0) {
561         // A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case
562         if ((Highbit - Lowbit) != 31) {
563           Mask = (((UINT32)1 << (Highbit - Lowbit + 1)) - 1);
564         } else {
565           Mask = (UINT32)0xFFFFFFFF;
566         }
567         Value &= ~(Mask << Lowbit);
568         Value |= (Field & Mask) << Lowbit;
569
570         if (Type == NB_ACCESS) {
571           PciAddr.AddressValue = Address;
572           LibAmdPciWrite (AccessWidth32, PciAddr , &Value, &NBPtr->MemPtr->StdHeader);
573         } else if (Type == DCT_PHY_ACCESS) {
574           MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
575           Address |= DCT_ACCESS_WRITE;
576
577           MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
578           while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
579         } else {
580           IDS_ERROR_TRAP;
581         }
582       } else {
583         Value = Value >> Lowbit;  // Shift
584         // A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case
585         if ((Highbit - Lowbit) != 31) {
586           Value &= (((UINT32)1 << (Highbit - Lowbit + 1)) - 1);
587         }
588       }
589     }
590   } else {
591     IDS_ERROR_TRAP;   // Invalid bit field index
592   }
593   return Value;
594 }
595
596
597 /* -----------------------------------------------------------------------------*/
598 /**
599  *
600  *   This function initializes bit field translation table
601  *
602 *     @param[in,out]   *NBRegTable   - Pointer to the NB Table *
603  */
604
605 VOID
606 STATIC
607 MemRecNInitNBRegTableC32 (
608   IN OUT   TSEFO *NBRegTable
609   )
610 {
611   UINT16 i;
612   for (i = 0; i <= BFEndOfList; i++) {
613     NBRegTable[i] = 0;
614   }
615
616   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x00), 31,  0, BFDevVendorIDReg);
617   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x60),  2,  0, BFNodeID);
618
619   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x40), 31, 0, BFDramBaseReg0);
620   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x44), 31, 0, BFDramLimitReg0);
621
622   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x40), 31,  0, BFCSBaseAddr0Reg);
623   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x44), 31,  0, BFCSBaseAddr1Reg);
624   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x48), 31,  0, BFCSBaseAddr2Reg);
625   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x4C), 31,  0, BFCSBaseAddr3Reg);
626   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x50), 31,  0, BFCSBaseAddr4Reg);
627   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x54), 31,  0, BFCSBaseAddr5Reg);
628   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x58), 31,  0, BFCSBaseAddr6Reg);
629   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x5C), 31,  0, BFCSBaseAddr7Reg);
630
631   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x60), 31,  0, BFCSMask0Reg);
632   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x64), 31,  0, BFCSMask1Reg);
633   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x68), 31,  0, BFCSMask2Reg);
634   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x6C), 31,  0, BFCSMask3Reg);
635
636   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 31,  0, BFDramControlReg);
637   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31,  0, BFDramInitRegReg);
638   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x80), 31,  0, BFDramBankAddrReg);
639   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 31,  0, BFDramMRSReg);
640   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84),  9,  7, BFDramTerm);
641   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 11, 10, BFDramTermDyn);
642   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x88), 31,  0, BFDramTimingLoReg);
643   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 31,  0, BFDramTimingHiReg);
644   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 31,  0, BFDramConfigLoReg);
645   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 31,  0, BFDramConfigHiReg);
646   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x98), 31,  0, BFDctAddlOffsetReg);
647   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x9C), 31,  0, BFDctAddlDataReg);
648   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x98), 31, 31, BFDctAccessDone);
649
650   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (3, 0xD4),  4,  0, BFNbFid);
651
652   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 18, 18, BFDqsRcvEnTrain);
653   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 31, 22, BFMaxLatency);
654
655   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 15,  0, BFMrsAddress);
656   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 18, 16, BFMrsBank);
657   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 22, 20, BFMrsChipSel);
658   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 26, 26, BFSendMrsCmd);
659   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 27, 27, BFDeassertMemRstX);
660   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 28, 28, BFAssertCke);
661   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 29, 29, BFSendZQCmd);
662   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 30, 30, BFSendCtrlWord);
663   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 31, BFEnDramInit);
664
665   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C),  7,  7, BFLevel);
666   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 12, 12, BFMrsQoff);
667
668   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 18, 18, BFDisAutoRefresh);
669
670   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90),  0,  0, BFInitDram);
671   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 16, 16, BFUnBuffDimm);
672
673   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94),  8,  8, BFDdr3Mode);
674   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94),  9,  9, BFLegacyBiosMode);
675   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 11, 10, BFZqcsInterval);
676   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 14, 14, BFDisDramInterface);
677
678   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8),  5,  5, BFSubMemclkRegDly);
679   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8),  6,  6, BFOdtSwizzle);
680   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 15, 8, BFCtrlWordCS);
681
682   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110),  8, 8, BFDramEnabled);
683   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 31, 0, BFDctSelBaseAddrReg);
684   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x114), 31, 0, BFDctSelBaseOffsetReg);
685
686   MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 31,  0, BFMctCfgHiReg);
687
688   MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 31,  0, BFODCControl);
689   MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x04, 31,  0, BFAddrTmgControl);
690
691   MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08,  0,  0, BFWrtLvTrEn);
692   MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08,  1,  1, BFWrtLvTrMode);
693   MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08,  5,  4, BFTrDimmSel);
694   MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 11,  8, BFWrLvOdt);
695   MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 12, 12, BFWrLvOdtEn);
696   MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 30, 30, BFDisAutoComp);
697
698 }
699
700 /*-----------------------------------------------------------------------------*/
701 /**
702  *     MemRecNIsIdSupportedC32
703  *      This function matches the CPU_LOGICAL_ID with certain criteria to
704  *      determine if it is supported by this NBBlock.
705  *
706  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
707  *     @param[in]       *LogicalIdPtr - Pointer to the CPU_LOGICAL_ID
708  *
709  *     @return          TRUE -  This node is a C32.
710  *     @return          FALSE - This node is not a C32.
711  *
712  */
713 BOOLEAN
714 STATIC
715 MemRecNIsIdSupportedC32 (
716   IN OUT   MEM_NB_BLOCK *NBPtr,
717   IN       CPU_LOGICAL_ID *LogicalIdPtr
718   )
719 {
720   if ((LogicalIdPtr->Revision & AMD_F10_C32_ALL) != 0) {
721     return TRUE;
722   } else {
723     return FALSE;
724   }
725 }