AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Mem / NB / mnS3.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mnS3.c
6  *
7  * Common Northbridge S3
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/NB)
12  * @e \$Revision: 51373 $ @e \$Date: 2011-04-21 13:10:59 -0600 (Thu, 21 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  *                                MODULES USED
49  *
50  *----------------------------------------------------------------------------
51  */
52
53 #include "AGESA.h"
54 #include "AdvancedApi.h"
55 #include "amdlib.h"
56 #include "Ids.h"
57 #include "OptionMemory.h"
58 #include "mm.h"
59 #include "mn.h"
60 #include "S3.h"
61 #include "mfs3.h"
62 #include "cpuFamilyTranslation.h"
63 #include "heapManager.h"
64 #include "Filecode.h"
65 CODE_GROUP (G3_DXE)
66 RDATA_GROUP (G3_DXE)
67
68 #define FILECODE PROC_MEM_NB_MNS3_FILECODE
69 /*----------------------------------------------------------------------------
70  *                          DEFINITIONS AND MACROS
71  *
72  *----------------------------------------------------------------------------
73  */
74
75 /*----------------------------------------------------------------------------
76  *                           TYPEDEFS AND STRUCTURES
77  *
78  *----------------------------------------------------------------------------
79  */
80
81 /*----------------------------------------------------------------------------
82  *                        PROTOTYPES OF LOCAL FUNCTIONS
83  *
84  *----------------------------------------------------------------------------
85  */
86 VOID
87 STATIC
88 MemNS3GetSetBitField (
89   IN       ACCESS_WIDTH AccessWidth,
90   IN       PCI_ADDR Address,
91   IN       BOOLEAN IsSet,
92   IN OUT   VOID *Value,
93   IN OUT   VOID *ConfigPtr
94   );
95
96 BOOLEAN
97 STATIC
98 MemNS3GetDummyReadAddr (
99   IN OUT   MEM_NB_BLOCK *NBPtr,
100      OUT   UINT64 *TestAddr
101   );
102 /*----------------------------------------------------------------------------
103  *                            EXPORTED FUNCTIONS
104  *
105  *----------------------------------------------------------------------------
106  */
107
108 /* -----------------------------------------------------------------------------*/
109 /**
110  *
111  *
112  *   This function executes the S3 resume for a node
113  *
114  *     @param[in,out]   *S3NBPtr - Pointer to the S3_MEM_NB_BLOCK
115  *     @param[in]       NodeID - The Node id of the target die
116  *
117  *     @return         BOOLEAN
118  *                         TRUE - This is the correct constructor for the targeted node.
119  *                         FALSE - This isn't the correct constructor for the targeted node.
120  */
121
122 BOOLEAN
123 MemNS3ResumeNb (
124   IN OUT   S3_MEM_NB_BLOCK *S3NBPtr,
125   IN       UINT8 NodeID
126   )
127 {
128   UINT8 DCT;
129   BOOLEAN GangedEn;
130   UINT64 TestAddr;
131   MEM_NB_BLOCK *NBPtr;
132   MEM_DATA_STRUCT *MemPtr;
133
134   NBPtr = S3NBPtr->NBPtr;
135   MemPtr = NBPtr->MemPtr;
136   GangedEn = (MemNGetBitFieldNb (NBPtr, BFDctGangEn) == 1) ? TRUE : FALSE;
137
138   // Errata before S3 resume sequence
139
140   // Resume Sequence
141   // 1. Program F2x[1,0]9C_x08[DisAutoComp]=1
142   MemNSwitchDCTNb (NBPtr, 0);
143   MemNSetBitFieldNb (NBPtr, BFDisAutoComp, 1);
144
145   // Program F2x[1, 0]94[MemClkFreqVal] = 1.
146   // 2. Wait for F2x[1,0]94[FreqChgInPrg]=0
147   for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
148     MemNSwitchDCTNb (NBPtr, DCT);
149     if ((MemNGetBitFieldNb (NBPtr, BFDisDramInterface) == 0) && !((DCT == 1) && GangedEn)) {
150       MemNSetBitFieldNb (NBPtr, BFMemClkFreqVal, 1);
151       while (MemNGetBitFieldNb (NBPtr, BFFreqChgInProg) != 0) {}
152     }
153   }
154
155   // Program F2x9C_x08[DisAutoComp]=0
156   MemNSwitchDCTNb (NBPtr, 0);
157   MemNSetBitFieldNb (NBPtr, BFDisAutoComp, 0);
158   //    BIOS must wait 750 us for the phy compensation engine
159   //    to reinitialize.
160   MemFS3Wait10ns (75000, NBPtr->MemPtr);
161
162   // 3. Restore F2x[1,0]90_x00, F2x9C_x0A, and F2x[1,0]9C_x0C
163   // 4. Restore F2x[1,0]9C_x04
164   // Get the register value from the heap.
165   S3NBPtr->MemS3ExitSelfRefReg (NBPtr, &MemPtr->StdHeader);
166
167   // Add a hook here
168   AGESA_TESTPOINT (TpProcMemBeforeAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
169   if (AgesaHookBeforeExitSelfRefresh (0, MemPtr) == AGESA_SUCCESS) {
170   }
171   AGESA_TESTPOINT (TpProcMemAfterAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
172
173   // 5. Set F2x[1,0]90[ExitSelfRef]
174   // 6. Wait for F2x[1,0]90[ExitSelfRef]=0
175   for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
176     MemNSwitchDCTNb (NBPtr, DCT);
177     if ((MemNGetBitFieldNb (NBPtr, BFDisDramInterface) == 0) && !((DCT == 1) && GangedEn)) {
178       MemNSetBitFieldNb (NBPtr, BFExitSelfRef, 1);
179       while (MemNGetBitFieldNb (NBPtr, BFExitSelfRef) != 0) {}
180     }
181     if ((MemNGetBitFieldNb (NBPtr, BFMemClkFreq) == DDR1333_FREQUENCY) && (NBPtr->IsSupported[CheckDllSpeedUp])) {
182       MemNSetBitFieldNb (NBPtr, BFPhy0x0D080F11, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D080F11) | 0x2000));
183       MemNSetBitFieldNb (NBPtr, BFPhy0x0D080F10, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D080F10) | 0x2000));
184       MemNSetBitFieldNb (NBPtr, BFPhy0x0D088F30, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D088F30) | 0x2000));
185       MemNSetBitFieldNb (NBPtr, BFPhy0x0D08C030, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D08C030) | 0x2000));
186       if (DCT == 0) {
187         MemNSetBitFieldNb (NBPtr, BFPhy0x0D082F30, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D082F30) | 0x2000));
188       }
189       // NOTE: wait 512 clocks for DLL-relock
190       MemFS3Wait10ns (50000, NBPtr->MemPtr);  // wait 500us
191     }
192   }
193
194   // Errata After S3 resume sequence
195   // Errata 350
196   for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
197     MemNSwitchDCTNb (NBPtr, DCT);
198     if (MemNGetBitFieldNb (NBPtr, BFDisDramInterface) == 0) {
199       if (!((DCT == 1) && GangedEn)) {
200         if (MemNS3GetDummyReadAddr (NBPtr, &TestAddr)) {
201           // Do dummy read
202           Read64Mem8 (TestAddr);
203           // Flush the cache line
204           LibAmdCLFlush (TestAddr, 1);
205         }
206       }
207       MemNSetBitFieldNb (NBPtr, BFErr350, 0x8000);
208       MemFS3Wait10ns (60, NBPtr->MemPtr);   // Wait 300ns
209       MemNSetBitFieldNb (NBPtr, BFErr350, 0x0000);
210       MemFS3Wait10ns (400, NBPtr->MemPtr);  // Wait 2us
211     }
212   }
213
214   return TRUE;
215 }
216
217 /* -----------------------------------------------------------------------------*/
218 /**
219  *
220  *
221  *   This function executes the S3 resume for a node on a client NB
222  *
223  *     @param[in,out]   *S3NBPtr - Pointer to the S3_MEM_NB_BLOCK
224  *     @param[in]       NodeID - The Node id of the target die
225  *
226  *     @return         BOOLEAN
227  *                         TRUE - This is the correct constructor for the targeted node.
228  *                         FALSE - This isn't the correct constructor for the targeted node.
229  */
230 BOOLEAN
231 MemNS3ResumeClientNb (
232   IN OUT   S3_MEM_NB_BLOCK *S3NBPtr,
233   IN       UINT8 NodeID
234   )
235 {
236   UINT8 DCT;
237   MEM_NB_BLOCK *NBPtr;
238   MEM_DATA_STRUCT *MemPtr;
239
240   NBPtr = S3NBPtr->NBPtr;
241   MemPtr = NBPtr->MemPtr;
242
243   // Errata before S3 resume sequence
244
245   // Add a hook here
246   AGESA_TESTPOINT (TpProcMemBeforeAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
247   if (AgesaHookBeforeExitSelfRefresh (0, MemPtr) == AGESA_SUCCESS) {
248   }
249   AGESA_TESTPOINT (TpProcMemAfterAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
250
251   NBPtr->ChangeNbFrequencyWrap (NBPtr, 0);
252   //Override the NB Pstate if needed
253   IDS_OPTION_HOOK (IDS_NB_PSTATE_DIDVID, S3NBPtr->NBPtr, &MemPtr->StdHeader);
254   // Set F2x[1,0]90[ExitSelfRef]
255   // Wait for F2x[1,0]90[ExitSelfRef]=0
256   for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
257     MemNSwitchDCTNb (NBPtr, DCT);
258     if (MemNGetBitFieldNb (NBPtr, BFDisDramInterface) == 0) {
259       MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 1);
260       MemNSetBitFieldNb (NBPtr, BFExitSelfRef, 1);
261       while (MemNGetBitFieldNb (NBPtr, BFExitSelfRef) != 0) {}
262       MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 0);
263     }
264   }
265
266   // Errata After S3 resume sequence
267   return TRUE;
268 }
269 /* -----------------------------------------------------------------------------*/
270 /**
271  *
272  *
273  *   This function executes the S3 resume for a node on a UNB
274  *
275  *     @param[in,out]   *S3NBPtr - Pointer to the S3_MEM_NB_BLOCK
276  *     @param[in]       NodeID - The Node id of the target die
277  *
278  *     @return         BOOLEAN
279  *                         TRUE - This is the correct constructor for the targeted node.
280  *                         FALSE - This isn't the correct constructor for the targeted node.
281  */
282 BOOLEAN
283 MemNS3ResumeUNb (
284   IN OUT   S3_MEM_NB_BLOCK *S3NBPtr,
285   IN       UINT8 NodeID
286   )
287 {
288   UINT8 DCT;
289   MEM_NB_BLOCK *NBPtr;
290   MEM_DATA_STRUCT *MemPtr;
291
292   NBPtr = S3NBPtr->NBPtr;
293   MemPtr = NBPtr->MemPtr;
294
295   // Errata before S3 resume sequence
296
297   // Add a hook here
298   AGESA_TESTPOINT (TpProcMemBeforeAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
299   if (AgesaHookBeforeExitSelfRefresh (0, MemPtr) == AGESA_SUCCESS) {
300   }
301   AGESA_TESTPOINT (TpProcMemAfterAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
302
303   //Override the NB Pstate if needed
304   IDS_OPTION_HOOK (IDS_NB_PSTATE_DIDVID, S3NBPtr->NBPtr, &MemPtr->StdHeader);
305   // Set F2x[1,0]90[ExitSelfRef]
306   // Wait for F2x[1,0]90[ExitSelfRef]=0
307   for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
308     MemNSwitchDCTNb (NBPtr, DCT);
309     if (MemNGetBitFieldNb (NBPtr, BFDisDramInterface) == 0) {
310       MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 1);
311       MemNSetBitFieldNb (NBPtr, BFExitSelfRef, 1);
312       while (MemNGetBitFieldNb (NBPtr, BFExitSelfRef) != 0) {}
313       if (NBPtr->IsSupported[SetDllShutDown]) {
314         MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 0);
315       }
316     }
317   }
318
319   // Errata After S3 resume sequence
320   return TRUE;
321 }
322
323 /* -----------------------------------------------------------------------------*/
324 /**
325  *
326  *
327  *   This function returns the conditional PCI device mask
328  *
329  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
330  *     @param[in, out]  *DescriptPtr - Pointer to DESCRIPTOR_GROUP
331  *      @return         none
332  */
333 VOID
334 MemNS3GetConPCIMaskNb (
335   IN OUT   MEM_NB_BLOCK *NBPtr,
336   IN OUT   DESCRIPTOR_GROUP *DescriptPtr
337   )
338 {
339   BIT_FIELD_NAME bitfield;
340   UINT32 RegVal;
341   UINT8 DCT;
342   UINT8 DimmMask;
343   UINT8 BadDimmMask;
344   UINT8 DctGangEn;
345   BOOLEAN IsDDR3;
346
347   IsDDR3 = FALSE;
348   DimmMask = 0;
349   BadDimmMask = 0;
350   for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
351     NBPtr->SwitchDCT (NBPtr, DCT);
352     if (MemNGetBitFieldNb (NBPtr, BFMemClkFreqVal)) {
353       if (MemNGetBitFieldNb (NBPtr, BFDdr3Mode) == 1) {
354         IsDDR3 = TRUE;
355       }
356       for (bitfield = BFCSBaseAddr0Reg; bitfield <= BFCSBaseAddr7Reg; bitfield ++) {
357         RegVal = MemNGetBitFieldNb (NBPtr, bitfield);
358         if (RegVal & 0x3) {
359           DimmMask |= (UINT8) (1 << ((((bitfield - BFCSBaseAddr0Reg) >> 1) << 1) + DCT));
360         } else if (RegVal & 0x4) {
361           BadDimmMask |= (UINT8) (1 << ((((bitfield - BFCSBaseAddr0Reg) >> 1) << 1) + DCT));
362         }
363       }
364     }
365   }
366
367   NBPtr->SwitchDCT (NBPtr, 0);
368   DctGangEn = (UINT8) MemNGetBitFieldNb (NBPtr, BFDctGangEn);
369   // Set channel mask
370   DescriptPtr->CPCIDevice[PRESELFREF].Mask1 = 0;
371   DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 = 0;
372   for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
373     if (DimmMask & (0x55 << DCT)) {
374       // Set mask before exit self refresh
375       DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= 1 << DCT;
376       // Set mask after exit self refresh
377       DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= 1 << DCT;
378       // Set DDR3 mask if Dimms present are DDR3
379       if (IsDDR3) {
380         DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= (DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 << 4);
381       }
382     } else if (BadDimmMask & (0x55 << DCT)) {
383       // Need to save function 2 registers for bad dimm
384       DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= 1 << DCT;
385     }
386   }
387
388   // Set dimm mask
389   DescriptPtr->CPCIDevice[PRESELFREF].Mask2 = DimmMask;
390   DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 = DimmMask;
391   if (DctGangEn) {
392     // Need to set channel mask bit to 1 on DCT1 in ganged mode as some registers
393     // need to be restored on both channels in ganged mode
394     DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= 2;
395     DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= 2;
396     if (IsDDR3) {
397       DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= (2 << 4);
398       DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= (2 << 4);
399     }
400     // Before exit self refresh, do not copy dimm mask to DCT1 as registers restored
401     // in that time frame don't care about individual dimm population. We want to
402     // skip registers that are not needed to be restored for DCT1 in ganged mode.
403     //
404     // After exit self refresh, training registers will be restored and will only be
405     // restored for slots which have dimms on it. So dimm mask needs to be copied to DCT1.
406     //
407     DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 |= DimmMask << 1;
408   }
409
410   // Adjust the mask if there is no dimm on the node
411   if ((DescriptPtr->CPCIDevice[PRESELFREF].Mask2 == 0) &&
412     (DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 == 0)) {
413     DescriptPtr->CPCIDevice[PRESELFREF].Mask1 = DescriptPtr->CPCIDevice[PRESELFREF].Mask2 = NODE_WITHOUT_DIMM_MASK;
414     DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 = DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 = NODE_WITHOUT_DIMM_MASK;
415   }
416 }
417
418 /* -----------------------------------------------------------------------------*/
419 /**
420  *
421  *
422  *   This function returns the conditional PCI device mask
423  *
424  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
425  *     @param[in, out]  *DescriptPtr - Pointer to DESCRIPTOR_GROUP
426  *      @return         none
427  */
428 VOID
429 MemNS3GetConPCIMaskUnb (
430   IN OUT   MEM_NB_BLOCK *NBPtr,
431   IN OUT   DESCRIPTOR_GROUP *DescriptPtr
432   )
433 {
434   BIT_FIELD_NAME bitfield;
435   UINT32 RegVal;
436   UINT8 DCT;
437   UINT8 DimmMask;
438   UINT8 BadDimmMask;
439   UINT8 NbPsCap;
440
441   DimmMask = 0;
442   BadDimmMask = 0;
443   for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
444     MemNSwitchDCTNb (NBPtr, DCT);
445     if (MemNGetBitFieldNb (NBPtr, BFMemClkFreqVal)) {
446       for (bitfield = BFCSBaseAddr0Reg; bitfield <= BFCSBaseAddr7Reg; bitfield ++) {
447         RegVal = MemNGetBitFieldNb (NBPtr, bitfield);
448         if (RegVal & 0x1) {
449           DimmMask |= (UINT8) (1 << ((((bitfield - BFCSBaseAddr0Reg) >> 1) << 1) + DCT));
450         } else if (RegVal & 0x4) {
451           BadDimmMask |= (UINT8) (1 << ((((bitfield - BFCSBaseAddr0Reg) >> 1) << 1) + DCT));
452         }
453       }
454     }
455   }
456   // Check if the system is capable of doing NB Pstate change
457   NbPsCap = (UINT8) MemNGetBitFieldNb (NBPtr, BFNbPstateDis);
458
459   MemNSwitchDCTNb (NBPtr, 0);
460   // Set channel mask
461   DescriptPtr->CPCIDevice[PRESELFREF].Mask1 = 0;
462   DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 = 0;
463   for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
464     if (DimmMask & (0x55 << DCT)) {
465       // Set mask before exit self refresh
466       DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= ((NbPsCap == 0) ? 5 : 1) << DCT;
467       // Set mask after exit self refresh
468       DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= 1 << DCT;
469       // Set DDR3 mask if Dimms present are DDR3
470       DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= (DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 << 4);
471     } else if (BadDimmMask & (0x55 << DCT)) {
472       // Need to save function 2 registers for bad dimm
473       DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= 1 << DCT;
474     }
475   }
476
477   // Set dimm mask
478   DescriptPtr->CPCIDevice[PRESELFREF].Mask2 = DimmMask;
479   DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 = DimmMask;
480
481   // Adjust the mask if there is no dimm on the node
482   if ((DescriptPtr->CPCIDevice[PRESELFREF].Mask2 == 0) &&
483     (DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 == 0)) {
484     DescriptPtr->CPCIDevice[PRESELFREF].Mask1 = DescriptPtr->CPCIDevice[PRESELFREF].Mask2 = NODE_WITHOUT_DIMM_MASK;
485     DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 = DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 = NODE_WITHOUT_DIMM_MASK;
486   }
487 }
488
489 /* -----------------------------------------------------------------------------*/
490 /**
491  *
492  *
493  *   This function read the value of CSR register.
494  *
495  *     @param[in]   AccessWidth - Access width of the register
496  *     @param[in]   Address - address of the CSR register in PCI_ADDR format.
497  *     @param[in]  *Value - Pointer to the value be read.
498  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
499  *     @return         none
500  */
501 VOID
502 MemNS3GetCSRNb (
503   IN       ACCESS_WIDTH AccessWidth,
504   IN       PCI_ADDR Address,
505   IN       VOID *Value,
506   IN OUT   VOID *ConfigPtr
507   )
508 {
509   UINT32 ExtendOffset;
510   UINT32 ValueRead;
511   UINT8 DataPort;
512
513   ValueRead = 0;
514   ExtendOffset = Address.Address.Register;
515   if (ExtendOffset & 0x800) {
516     Address.Address.Register = 0xF0;
517     DataPort = 0xF4;
518   } else {
519     Address.Address.Register = 0x98;
520     DataPort = 0x9C;
521   }
522   if (ExtendOffset & 0x400) {
523     Address.Address.Register |= 0x100;
524   }
525   ExtendOffset &= 0x3FF;
526   LibAmdPciWrite (AccessS3SaveWidth32, Address, &ExtendOffset, ConfigPtr);
527   while (((ValueRead >> 31) & 1) == 0) {
528     LibAmdPciRead (AccessS3SaveWidth32, Address, &ValueRead, ConfigPtr);
529   }
530   Address.Address.Register = (Address.Address.Register & 0xF00) | DataPort;
531   LibAmdPciRead (AccessWidth, Address, Value, ConfigPtr);
532 }
533
534
535 /* -----------------------------------------------------------------------------*/
536 /**
537  *
538  *
539  *   This function write to a CSR register
540  *
541  *     @param[in]   AccessWidth - Access width of the register
542  *     @param[in]   Address - address of the CSR register in PCI_ADDR format.
543  *     @param[in, out]  *Value - Pointer to the value be read.
544  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
545  *     @return         none
546  */
547 VOID
548 MemNS3SetCSRNb (
549   IN       ACCESS_WIDTH AccessWidth,
550   IN       PCI_ADDR Address,
551   IN OUT   VOID *Value,
552   IN OUT   VOID *ConfigPtr
553   )
554 {
555   UINT32 ExtendOffset;
556   UINT32 ValueRead;
557   UINT32 ValueWrite;
558   UINT8 DataOffset;
559
560   ValueRead = 0;
561   ExtendOffset = Address.Address.Register;
562   // Check the flag and see the type of the access
563   if (ExtendOffset & 0x800) {
564     Address.Address.Register = 0xF4;
565     DataOffset = 0xF0;
566   } else {
567     Address.Address.Register = 0x9C;
568     DataOffset = 0x98;
569   }
570   if (ExtendOffset & 0x400) {
571     Address.Address.Register |= 0x100;
572   }
573   ExtendOffset &= 0x3FF;
574   ExtendOffset |= 0x40000000;
575   switch (AccessWidth) {
576   case AccessS3SaveWidth8:
577     ValueWrite = *(UINT8 *) Value;
578     break;
579   case AccessS3SaveWidth16:
580     ValueWrite = *(UINT16 *) Value;
581     break;
582   case AccessS3SaveWidth32:
583     ValueWrite = *(UINT32 *) Value;
584     break;
585   default:
586     ASSERT (FALSE);
587   }
588   LibAmdPciWrite (AccessS3SaveWidth32, Address, &ValueWrite, ConfigPtr);
589   Address.Address.Register = (Address.Address.Register & 0xF00) | DataOffset;
590   LibAmdPciWrite (AccessS3SaveWidth32, Address, &ExtendOffset, ConfigPtr);
591   while (((ValueRead >> 31) & 1) == 0) {
592     LibAmdPciRead (AccessS3SaveWidth32, Address, &ValueRead, ConfigPtr);
593   }
594 }
595
596 /* -----------------------------------------------------------------------------*/
597 /**
598  *
599  *
600  *   This function reads register bitfield
601  *
602  *     @param[in]   AccessWidth - Access width of the register
603  *     @param[in]   Address - address of the CSR register in PCI_ADDR format.
604  *     @param[in, out]  *Value - Pointer to the value be read.
605  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
606  *     @return         none
607  */
608 VOID
609 MemNS3GetBitFieldNb (
610   IN       ACCESS_WIDTH AccessWidth,
611   IN       PCI_ADDR Address,
612   IN OUT   VOID *Value,
613   IN OUT   VOID *ConfigPtr
614   )
615 {
616   MemNS3GetSetBitField (AccessWidth, Address, FALSE, Value, ConfigPtr);
617 }
618
619 /* -----------------------------------------------------------------------------*/
620 /**
621  *
622  *
623  *   This function writes register bitfield
624  *
625  *     @param[in]   AccessWidth - Access width of the register
626  *     @param[in]   Address - address of the CSR register in PCI_ADDR format.
627  *     @param[in, out]  *Value - Pointer to the value to be written.
628  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
629  *     @return         none
630  */
631 VOID
632 MemNS3SetBitFieldNb (
633   IN       ACCESS_WIDTH AccessWidth,
634   IN       PCI_ADDR Address,
635   IN OUT   VOID *Value,
636   IN OUT   VOID *ConfigPtr
637   )
638 {
639   MemNS3GetSetBitField (AccessWidth, Address, TRUE, Value, ConfigPtr);
640 }
641
642 /* -----------------------------------------------------------------------------*/
643 /**
644  *
645  *
646  *   This function restores scrubber base register
647  *
648  *     @param[in,out]   *NBPtr - Pointer to the MEM_NB_BLOCK
649  *     @param[in]       Node - The Node id of the target die
650  *
651  */
652 VOID
653 MemNS3RestoreScrubNb (
654   IN OUT   MEM_NB_BLOCK *NBPtr,
655   IN       UINT8 Node
656   )
657 {
658   UINT32 ScrubAddrRJ16;
659
660   ScrubAddrRJ16 = (MemNGetBitFieldNb (NBPtr, BFDramBaseReg0 + Node) & 0xFFFF0000) >> 8;
661   ScrubAddrRJ16 |= MemNGetBitFieldNb (NBPtr, BFDramBaseHiReg0 + Node) << 24;
662   MemNSetBitFieldNb (NBPtr, BFScrubAddrLoReg, ScrubAddrRJ16 << 16);
663   MemNSetBitFieldNb (NBPtr, BFScrubAddrHiReg, ScrubAddrRJ16 >> 16);
664 }
665
666 /* -----------------------------------------------------------------------------*/
667 /**
668  *
669  *
670  *   This function disable NB Pstate Debug.
671  *
672  *     @param[in]   AccessWidth - Access width of the register.
673  *     @param[in]   Address - address in PCI_ADDR format.
674  *     @param[in, out]  *Value - Pointer to the value to be written.
675  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
676  *     @return         none
677  */
678 VOID
679 MemNS3DisNbPsDbgNb (
680   IN       ACCESS_WIDTH AccessWidth,
681   IN       PCI_ADDR Address,
682   IN OUT   VOID *Value,
683   IN OUT   VOID *ConfigPtr
684   )
685 {
686   UINT32 RegValue;
687
688   LibAmdPciRead (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
689   // Clear NbPsDbgEn and NbPsCsrAccSel
690   if ((RegValue & 0xC0000000) != 0) {
691     RegValue &= 0x3FFFFFFF;
692     LibAmdPciWrite (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
693   }
694 }
695
696 /* -----------------------------------------------------------------------------*/
697 /**
698  *
699  *
700  *   This function that enable NB Pstate debug register to allow access to NB Pstate
701  *   1 registers without actually changing NB Pstate.
702  *
703  *     @param[in]   AccessWidth - Access width of the register.
704  *     @param[in]   Address - address in PCI_ADDR format.
705  *     @param[in, out]  *Value - Pointer to the value to be written.
706  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
707  *     @return         none
708  */
709 VOID
710 MemNS3EnNbPsDbg1Nb (
711   IN       ACCESS_WIDTH AccessWidth,
712   IN       PCI_ADDR Address,
713   IN OUT   VOID *Value,
714   IN OUT   VOID *ConfigPtr
715   )
716 {
717   UINT32 RegValue;
718
719   LibAmdPciRead (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
720   // Set NbPsDbgEn to 1 and NbPsCsrAccSel to 1
721   if ((RegValue & 0xC0000000) != 0xC0000000) {
722     RegValue = (*(UINT32 *)Value & 0x3FFFFFFF) | 0xC0000000;
723     LibAmdPciWrite (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
724   }
725 }
726
727 /* -----------------------------------------------------------------------------*/
728 /**
729  *
730  *
731  *   This function sets bit 31 [DynModeChange] of F2x9C_xB
732  *
733  *     @param[in]   AccessWidth - Access width of the register.
734  *     @param[in]   Address - address in PCI_ADDR format.
735  *     @param[in, out]  *Value - Pointer to the value to be written.
736  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
737  *     @return         none
738  */
739 VOID
740 MemNS3SetDynModeChangeNb (
741   IN       ACCESS_WIDTH AccessWidth,
742   IN       PCI_ADDR Address,
743   IN OUT   VOID *Value,
744   IN OUT   VOID *ConfigPtr
745   )
746 {
747   UINT32 RegValue;
748
749   RegValue = 0x80000000;
750   IDS_SKIP_HOOK (IDS_BEFORE_S3_SPECIAL, &Address, ConfigPtr) {
751     MemNS3SetCSRNb (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
752   }
753 }
754
755 /* -----------------------------------------------------------------------------*/
756 /**
757  *
758  *
759  *   This function does the channel disable sequence
760  *
761  *     @param[in]   AccessWidth - Access width of the register.
762  *     @param[in]   Address - address in PCI_ADDR format.
763  *     @param[in, out]  *Value - Pointer to the value to be written.
764  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
765  *     @return         none
766  */
767 VOID
768 MemNS3DisableChannelNb (
769   IN       ACCESS_WIDTH AccessWidth,
770   IN       PCI_ADDR Address,
771   IN OUT   VOID *Value,
772   IN OUT   VOID *ConfigPtr
773   )
774 {
775   MEM_NB_BLOCK *NBPtr;
776   LOCATE_HEAP_PTR LocateBufferPtr;
777   S3_MEM_NB_BLOCK *S3NBPtr;
778   UINT32 RegValue;
779   UINT8 Die;
780
781   // See which Node should be accessed
782   Die = (UINT8) (Address.Address.Device - 24);
783
784   LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
785   if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
786     S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
787     NBPtr = S3NBPtr[Die].NBPtr;
788
789     // Function field contains the DCT number
790     NBPtr->SwitchDCT (NBPtr, (UINT8) Address.Address.Function);
791     RegValue = MemNGetBitFieldNb (NBPtr, BFCKETri);
792     // if CKETri is 0b11, this channel is disabled
793     if (RegValue == 3) {
794       //Wait for 24 MEMCLKs, which is 60ns under 400MHz
795       MemFS3Wait10ns (6, NBPtr->MemPtr);
796       MemNSetBitFieldNb (NBPtr, BFMemClkDis, 0xFF);
797       MemNSetBitFieldNb (NBPtr, BFDisDramInterface, 1);
798       MemNSetBitFieldNb (NBPtr, BFDramPhyStatusReg, 0x80800000);
799     }
800   }
801 }
802
803 /* -----------------------------------------------------------------------------*/
804 /**
805  *
806  *
807  *   This function disables auto compensation.
808  *
809  *     @param[in]   AccessWidth - Access width of the register.
810  *     @param[in]   Address - address in PCI_ADDR format.
811  *     @param[in, out]  *Value - Pointer to the value to be written.
812  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
813  *     @return         none
814  */
815 VOID
816 MemNS3SetDisAutoCompUnb (
817   IN       ACCESS_WIDTH AccessWidth,
818   IN       PCI_ADDR Address,
819   IN OUT   VOID *Value,
820   IN OUT   VOID *ConfigPtr
821   )
822 {
823   UINT16 RegValue;
824
825   MemNS3GetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
826   RegValue = 0x6000 | RegValue;
827   MemNS3SetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
828 }
829
830 /* -----------------------------------------------------------------------------*/
831 /**
832  *
833  *
834  *   This function retores Pre Driver Calibration with pre driver calibration code
835  *   code valid bit set.
836  *
837  *     @param[in]   AccessWidth - Access width of the register.
838  *     @param[in]   Address - address in PCI_ADDR format.
839  *     @param[in, out]  *Value - Pointer to the value to be written.
840  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
841  *     @return         none
842  */
843 VOID
844 MemNS3SetPreDriverCalUnb (
845   IN       ACCESS_WIDTH AccessWidth,
846   IN       PCI_ADDR Address,
847   IN OUT   VOID *Value,
848   IN OUT   VOID *ConfigPtr
849   )
850 {
851   UINT16 RegValue;
852
853   RegValue = 0x8000 | *(UINT16 *) Value;
854   MemNS3SetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
855 }
856
857 /* -----------------------------------------------------------------------------*/
858 /**
859  *
860  *     This function is used by families that use a separate DctCfgSel bit to
861  *     select the current DCT which will be accessed by function 2.
862  *     NOTE:  This function must be called BEFORE the NBPtr->Dct variable is
863  *     updated.
864  *
865  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
866  *     @param[in]       *Dct     - Pointer to ID of the target DCT
867  *
868  */
869
870 BOOLEAN
871 MemNS3DctCfgSelectUnb (
872   IN OUT   MEM_NB_BLOCK *NBPtr,
873   IN       VOID *Dct
874   )
875 {
876   // Set the DctCfgSel to new DCT
877   //
878   MemNSetBitFieldNb (NBPtr, BFDctCfgSel, *(UINT8*)Dct);
879
880   return TRUE;
881 }
882
883 /* -----------------------------------------------------------------------------*/
884 /**
885  *
886  *
887  *   This function write to a register that has one copy for each NB Pstate
888  *
889  *     @param[in]   AccessWidth - Access width of the register
890  *     @param[in]   Address - address of the CSR register in PCI_ADDR format.
891  *     @param[in, out]  *Value - Pointer to the value be read.
892  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
893  *     @return         none
894  */
895 VOID
896 MemNS3GetNBPStateDepRegUnb (
897   IN       ACCESS_WIDTH AccessWidth,
898   IN       PCI_ADDR Address,
899   IN OUT   VOID *Value,
900   IN OUT   VOID *ConfigPtr
901   )
902 {
903   UINT8 NBPstate;
904   UINT8 TempValue;
905   UINT8 Dct;
906   UINT32 Temp;
907
908   Temp = Address.Address.Register;
909   NBPstate = (UINT8) (Temp >> 10);
910   Dct = (UINT8) Address.Address.Function;
911   Temp &= 0x3FF;
912
913   // Switch Dct
914   // Function field contains DCT value
915   Address.Address.Function = FUNC_1;
916   Address.Address.Register = 0x10C;
917   LibAmdPciRead (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
918   TempValue = (TempValue & 0xCE) | ((NBPstate << 4) | Dct);
919   LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
920
921   Address.Address.Function = FUNC_2;
922   Address.Address.Register = Temp;
923   LibAmdPciRead (AccessWidth, Address, Value, ConfigPtr);
924
925   Address.Address.Function = FUNC_1;
926   Address.Address.Register = 0x10C;
927   TempValue = 0;
928   LibAmdPciWrite (AccessS3SaveWidth32, Address, &TempValue, ConfigPtr);
929 }
930
931 /* -----------------------------------------------------------------------------*/
932 /**
933  *
934  *
935  *   This function write to a register that has one copy for each NB Pstate
936  *
937  *     @param[in]   AccessWidth - Access width of the register
938  *     @param[in]   Address - address of the CSR register in PCI_ADDR format.
939  *     @param[in, out]  *Value - Pointer to the value be read.
940  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
941  *     @return         none
942  */
943 VOID
944 MemNS3SetNBPStateDepRegUnb (
945   IN       ACCESS_WIDTH AccessWidth,
946   IN       PCI_ADDR Address,
947   IN OUT   VOID *Value,
948   IN OUT   VOID *ConfigPtr
949   )
950 {
951   UINT8 NBPstate;
952   UINT8 TempValue;
953   UINT8 Dct;
954   UINT32 Temp;
955
956   Temp = Address.Address.Register;
957   NBPstate = (UINT8) (Temp >> 10);
958   Dct = (UINT8) Address.Address.Function;
959   Temp &= 0x3FF;
960
961   // Switch Dct
962   // Function field contains DCT value
963   Address.Address.Function = FUNC_1;
964   Address.Address.Register = 0x10C;
965   LibAmdPciRead (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
966   TempValue = (TempValue & 0xCE) | ((NBPstate << 4) | Dct);
967   LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
968
969   Address.Address.Function = FUNC_2;
970   Address.Address.Register = Temp;
971   LibAmdPciWrite (AccessWidth, Address, Value, ConfigPtr);
972
973   Address.Address.Function = FUNC_1;
974   Address.Address.Register = 0x10C;
975   TempValue = 0;
976   LibAmdPciWrite (AccessS3SaveWidth32, Address, &TempValue, ConfigPtr);
977 }
978
979 /* -----------------------------------------------------------------------------*/
980 /**
981  *
982  *
983  *   This function read the value of Function 2 PCI register.
984  *
985  *     @param[in]   AccessWidth - Access width of the register
986  *     @param[in]   Address - address of the NB register in PCI_ADDR format.
987  *     @param[in]  *Value - Pointer to the value be read.
988  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
989  *     @return         none
990  */
991 VOID
992 MemNS3SaveNBRegiserUnb (
993   IN       ACCESS_WIDTH AccessWidth,
994   IN       PCI_ADDR Address,
995   IN OUT   VOID *Value,
996   IN OUT   VOID *ConfigPtr
997   )
998 {
999   UINT8 TempValue;
1000   UINT8 Dct;
1001   UINT32 Temp;
1002
1003   Temp = Address.Address.Register;
1004   Dct = (UINT8) Address.Address.Function;
1005
1006   // Switch Dct
1007   // Function field contains DCT value
1008   Address.Address.Function = FUNC_1;
1009   Address.Address.Register = 0x10C;
1010   LibAmdPciRead (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
1011   TempValue = (TempValue & 0xFE) | Dct;
1012   LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
1013
1014   Address.Address.Register = Temp;
1015   Address.Address.Function = FUNC_2;
1016   LibAmdPciRead (AccessWidth, Address, Value, ConfigPtr);
1017 }
1018
1019 /* -----------------------------------------------------------------------------*/
1020 /**
1021  *
1022  *
1023  *   This function set the value of Function 2 PCI register.
1024  *
1025  *     @param[in]   AccessWidth - Access width of the register
1026  *     @param[in]   Address - address of the NB register in PCI_ADDR format.
1027  *     @param[in]  *Value - Pointer to the value be write.
1028  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
1029  *     @return         none
1030  */
1031 VOID
1032 MemNS3RestoreNBRegiserUnb (
1033   IN       ACCESS_WIDTH AccessWidth,
1034   IN       PCI_ADDR Address,
1035   IN OUT   VOID *Value,
1036   IN OUT   VOID *ConfigPtr
1037   )
1038 {
1039   UINT8 TempValue;
1040   UINT8 Dct;
1041   UINT32 Temp;
1042
1043   Temp = Address.Address.Register;
1044   Dct = (UINT8) Address.Address.Function;
1045
1046   // Switch Dct
1047   // Function field contains DCT value
1048   Address.Address.Function = FUNC_1;
1049   Address.Address.Register = 0x10C;
1050   LibAmdPciRead (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
1051   TempValue = (TempValue & 0xFE) | Dct;
1052   LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
1053
1054   Address.Address.Register = Temp;
1055   Address.Address.Function = FUNC_2;
1056   LibAmdPciWrite (AccessWidth, Address, Value, ConfigPtr);
1057 }
1058
1059 /*----------------------------------------------------------------------------
1060  *                              LOCAL FUNCTIONS
1061  *
1062  *----------------------------------------------------------------------------*/
1063
1064 /* -----------------------------------------------------------------------------*/
1065 /**
1066  *
1067  *
1068  *   This function reads and writes register bitfield
1069  *
1070  *     @param[in]   AccessWidth - Access width of the register
1071  *     @param[in]   Address - address of the CSR register in PCI_ADDR format.
1072  *     @param[in]   IsSet - if this is a register read or write
1073  *     @param[in, out]  *Value - Pointer to the value be read or  written.
1074  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
1075  *     @return         none
1076  */
1077 VOID
1078 STATIC
1079 MemNS3GetSetBitField (
1080   IN       ACCESS_WIDTH AccessWidth,
1081   IN       PCI_ADDR Address,
1082   IN       BOOLEAN IsSet,
1083   IN OUT   VOID *Value,
1084   IN OUT   VOID *ConfigPtr
1085   )
1086 {
1087   BIT_FIELD_NAME BitField;
1088   MEM_NB_BLOCK *NBPtr;
1089   LOCATE_HEAP_PTR LocateBufferPtr;
1090   S3_MEM_NB_BLOCK *S3NBPtr;
1091   UINT32 RegValue;
1092   UINT8 Die;
1093
1094   RegValue = 0;
1095   // See which Node should be accessed
1096   Die = (UINT8) (Address.Address.Device - 24);
1097
1098   LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
1099   if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
1100     S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
1101     NBPtr = S3NBPtr[Die].NBPtr;
1102
1103     // Function field contains the DCT number
1104     NBPtr->SwitchDCT (NBPtr, (UINT8) Address.Address.Function);
1105
1106     // Get the bitfield name to be accessed
1107     // Register field contains the bitfield name
1108     BitField = (BIT_FIELD_NAME) Address.Address.Register;
1109
1110     if (IsSet) {
1111       switch (AccessWidth) {
1112       case AccessS3SaveWidth8:
1113         RegValue = *(UINT8 *) Value;
1114         break;
1115       case AccessS3SaveWidth16:
1116         RegValue = *(UINT16 *) Value;
1117         break;
1118       case AccessS3SaveWidth32:
1119         RegValue = *(UINT32 *) Value;
1120         break;
1121       default:
1122         ASSERT (FALSE);
1123       }
1124       MemNSetBitFieldNb (NBPtr, BitField, RegValue);
1125     } else {
1126       RegValue = MemNGetBitFieldNb (NBPtr, BitField);
1127
1128       switch (AccessWidth) {
1129       case AccessS3SaveWidth8:
1130         *(UINT8 *) Value = (UINT8) RegValue;
1131         break;
1132       case AccessS3SaveWidth16:
1133         *(UINT16 *) Value = (UINT16) RegValue;
1134         break;
1135       case AccessS3SaveWidth32:
1136         *(UINT32 *) Value = RegValue;
1137         break;
1138       default:
1139         ASSERT (FALSE);
1140       }
1141     }
1142   } else {
1143     ASSERT (FALSE);
1144   }
1145 }
1146
1147 /* -----------------------------------------------------------------------------*/
1148 /**
1149  *
1150  *
1151  *   This function gets the dummy read address for a channel of a node.
1152  *
1153  *     @param[in, out]  *NBPtr - Pointer to northbridge block
1154  *     @param[out]      *TestAddr - Pointer to the test address
1155  *
1156  *     @retval           TRUE - Dummy read address can be found
1157  *     @retval           FALSE - Dummy read address cannot be found
1158  *
1159  */
1160 BOOLEAN
1161 STATIC
1162 MemNS3GetDummyReadAddr (
1163   IN OUT   MEM_NB_BLOCK *NBPtr,
1164      OUT   UINT64 *TestAddr
1165   )
1166 {
1167   BOOLEAN DctSelIntlvEn;
1168   UINT8 DramIntlvEn;
1169   UINT8 DctSelIntlvAddr;
1170   UINT8 IntLvRgnBaseAddr;
1171   UINT8 IntLvRgnLmtAddr;
1172   UINT8 IntLvRgnSize;
1173   UINT32 DctSelBaseAddr;
1174   UINT64 TOM;
1175   BOOLEAN AddrFound;
1176
1177   AddrFound = TRUE;
1178   // Check if Node interleaving is enabled
1179   DramIntlvEn = (UINT8) MemNGetBitFieldNb (NBPtr, BFDramIntlvEn);
1180   if (DramIntlvEn != 0) {
1181     // Set the address bits that identify the node
1182     *TestAddr = (UINT64) MemNGetBitFieldNb (NBPtr, BFDramIntlvSel) << 12;
1183   } else {
1184     *TestAddr = (UINT64) MemNGetBitFieldNb (NBPtr, BFDramBaseAddr) << 27;
1185   }
1186
1187   // Check if channel interleaving is enabled
1188   DctSelIntlvEn = (BOOLEAN) MemNGetBitFieldNb (NBPtr, BFDctSelIntLvEn);
1189   DctSelBaseAddr = MemNGetBitFieldNb (NBPtr, BFDctSelBaseAddr);
1190   if (!DctSelIntlvEn) {
1191     if ((NBPtr->Dct == 1) && ((UINT8) MemNGetBitFieldNb (NBPtr, BFDctSelHi) == 1)) {
1192       *TestAddr = ((UINT64) DctSelBaseAddr << 27) | (*TestAddr & 0xFFFFFFF);
1193     }
1194   } else {
1195     DctSelIntlvAddr = (UINT8) MemNGetBitFieldNb (NBPtr, BFDctSelIntLvAddr);
1196     // Set the address bits that identify the channel
1197     if ((DctSelIntlvAddr == 0) || (DctSelIntlvAddr == 2)) {
1198       *TestAddr |= (UINT64) NBPtr->Dct << 6;
1199     } else if (DctSelIntlvAddr == 1) {
1200       *TestAddr |= (UINT64) NBPtr->Dct << (12 + LibAmdBitScanReverse (DramIntlvEn + 1));
1201     } else if (DctSelIntlvAddr == 3) {
1202       *TestAddr |= (UINT64) NBPtr->Dct << 9;
1203     }
1204   }
1205   // Adding 2M to avoid conflict
1206   *TestAddr += 0x200000;
1207
1208   // If memory hoisting is disabled, the address can fall into MMIO area
1209   // Need to find an address out of MMIO area but belongs to the channel
1210   // If the whole channel is in MMIO, then do not do dummy read.
1211   //
1212   LibAmdMsrRead (TOP_MEM, &TOM, &NBPtr->MemPtr->StdHeader);
1213   if ((*TestAddr >= TOM) && (*TestAddr < ((UINT64) _4GB_RJ16 << 16))) {
1214     if ((NBPtr->Dct == 1) && ((UINT8) MemNGetBitFieldNb (NBPtr, BFDctSelHi) == 1)) {
1215       // This is the DCT that goes to high address range
1216       if (DctSelBaseAddr >= (_4GB_RJ16 >> (27 - 16))) {
1217         // When DctSelBaseAddr is higher than 4G, choose DctSelBaseAddr as the dummy read addr
1218         if (DctSelIntlvEn) {
1219           *TestAddr = ((UINT64) DctSelBaseAddr << 27) | (*TestAddr & 0xFFFFFFF);
1220         }
1221       } else if (MemNGetBitFieldNb (NBPtr, BFDramLimitAddr) > (UINT32) (_4GB_RJ16 >> (27 - 16))) {
1222         // if DctSelBase is smaller than 4G, but Dram limit is larger than 4G, then choose 4G as
1223         // dummy read address
1224         *TestAddr =  ((UINT64) _4GB_RJ16 << 16) | (*TestAddr & 0xFFFFFF);
1225       } else {
1226         AddrFound = FALSE;
1227       }
1228     } else {
1229       // This is the DCT that only goes to low address range
1230       if (DctSelBaseAddr > (_4GB_RJ16 >> (27 - 16))) {
1231         // When DctSelBaseAddr is larger than 4G, choose 4G as the dummy read address
1232         // Keep the lower bits for node and channel selection
1233         *TestAddr = ((UINT64) _4GB_RJ16 << 16) | (*TestAddr & 0xFFFFFF);
1234       } else {
1235         AddrFound = FALSE;
1236       }
1237     }
1238   }
1239
1240   // Interleaved Swap Region handling
1241   if ((BOOLEAN) MemNGetBitFieldNb (NBPtr, BFIntLvRgnSwapEn)) {
1242     IntLvRgnBaseAddr = (UINT8) MemNGetBitFieldNb (NBPtr, BFIntLvRgnBaseAddr);
1243     IntLvRgnLmtAddr = (UINT8) MemNGetBitFieldNb (NBPtr, BFIntLvRgnLmtAddr);
1244     IntLvRgnSize = (UINT8) MemNGetBitFieldNb (NBPtr, BFIntLvRgnSize);
1245     ASSERT (IntLvRgnSize == (IntLvRgnLmtAddr - IntLvRgnBaseAddr + 1));
1246     if (((*TestAddr >> 34) == 0) &&
1247       ((((*TestAddr >> 27) >= IntLvRgnBaseAddr) && ((*TestAddr >> 27) <= IntLvRgnLmtAddr))
1248        || ((*TestAddr >> 27) < IntLvRgnSize))) {
1249       *TestAddr ^= (UINT64) IntLvRgnBaseAddr << 27;
1250     }
1251   }
1252
1253   return AddrFound;
1254 }
1255
1256 /* -----------------------------------------------------------------------------*/
1257 /**
1258  *
1259  *
1260  *   This function sets bit 7 [MemClkFreqVal] of F2x94_dct[1:0]
1261  *
1262  *     @param[in]   AccessWidth - Access width of the register.
1263  *     @param[in]   Address - address in PCI_ADDR format.
1264  *     @param[in, out]  *Value - Pointer to the value to be written.
1265  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
1266  *     @return         none
1267  */
1268 VOID
1269 MemNS3SetMemClkFreqValUnb (
1270   IN       ACCESS_WIDTH AccessWidth,
1271   IN       PCI_ADDR Address,
1272   IN OUT   VOID *Value,
1273   IN OUT   VOID *ConfigPtr
1274   )
1275 {
1276   UINT32 TempValue;
1277
1278   // 1. Program F2x94_dct[1:0][MemClkFreqVal] = 1
1279   MemNS3SaveNBRegiserUnb (AccessWidth, Address, &TempValue, ConfigPtr);
1280   TempValue |= 0x80;
1281   MemNS3RestoreNBRegiserUnb (AccessWidth, Address, &TempValue, ConfigPtr);
1282
1283   // 2. Wait for F2x94_dct[1:0][FreqChgInPrg] = 0
1284   MemNS3SaveNBRegiserUnb (AccessWidth, Address, &TempValue, ConfigPtr);
1285   while ((TempValue & 0x200000) != 0) {
1286     MemNS3SaveNBRegiserUnb (AccessWidth, Address, &TempValue, ConfigPtr);
1287   }
1288 }
1289
1290 /* -----------------------------------------------------------------------------*/
1291 /**
1292  *
1293  *
1294  *     This function changes memory Pstate context
1295  *
1296  *     @param[in]   AccessWidth - Access width of the register.
1297  *     @param[in]   Address - address in PCI_ADDR format. Target MemPState is in
1298  *                            Address.Address.Register.
1299  *     @param[in, out]  *Value - Pointer to the value to be written.
1300  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
1301  *     @return         none
1302  *
1303  *     @return    TRUE
1304  * ----------------------------------------------------------------------------
1305  */
1306 VOID
1307 MemNS3ChangeMemPStateContextNb (
1308   IN       ACCESS_WIDTH AccessWidth,
1309   IN       PCI_ADDR Address,
1310   IN OUT   VOID *Value,
1311   IN OUT   VOID *ConfigPtr
1312   )
1313 {
1314   MEM_NB_BLOCK *NBPtr;
1315   LOCATE_HEAP_PTR LocateBufferPtr;
1316   S3_MEM_NB_BLOCK *S3NBPtr;
1317   UINT8 Die;
1318
1319   // See which Node should be accessed
1320   Die = (UINT8) (Address.Address.Device - 24);
1321
1322   LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
1323   if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
1324     S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
1325     NBPtr = S3NBPtr[Die].NBPtr;
1326     MemNChangeMemPStateContextNb (NBPtr, Address.Address.Register);
1327   }
1328 }
1329
1330 /* -----------------------------------------------------------------------------*/
1331 /**
1332  *
1333  *
1334  *   This function retores Phy Clk DLL fine delay
1335  *
1336  *     @param[in]   AccessWidth - Access width of the register.
1337  *     @param[in]   Address - address in PCI_ADDR format.
1338  *     @param[in, out]  *Value - Pointer to the value to be written.
1339  *     @param[in, out]  *ConfigPtr - Pointer to Config handle.
1340  *     @return         none
1341  */
1342 VOID
1343 MemNS3SetPhyClkDllFineClientNb (
1344   IN       ACCESS_WIDTH AccessWidth,
1345   IN       PCI_ADDR Address,
1346   IN OUT   VOID *Value,
1347   IN OUT   VOID *ConfigPtr
1348   )
1349 {
1350   UINT16 RegValue;
1351
1352   RegValue = 0x4000 | *(UINT16 *) Value;
1353   MemNS3SetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
1354   RegValue = 0xBFFF & *(UINT16 *) Value;
1355   MemNS3SetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
1356 }