AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Mem / Feat / NDINTLV / mfndi.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mfndi.c
6  *
7  * Feature applies Node memory interleaving
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/Feat/Ndintlv)
12  * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
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  *                                MODULES USED
50  *
51  *----------------------------------------------------------------------------
52  */
53
54
55
56 #include "AGESA.h"
57 #include "amdlib.h"
58 #include "mm.h"
59 #include "mn.h"
60 #include "mport.h"
61 #include "mfndi.h"
62 #include "Ids.h"
63 #include "Filecode.h"
64 CODE_GROUP (G2_PEI)
65 RDATA_GROUP (G2_PEI)
66
67 #define FILECODE PROC_MEM_FEAT_NDINTLV_MFNDI_FILECODE
68 /*----------------------------------------------------------------------------
69  *                          DEFINITIONS AND MACROS
70  *
71  *----------------------------------------------------------------------------
72  */
73 #define _4GB_ (0x10000)
74
75 /*----------------------------------------------------------------------------
76  *                           TYPEDEFS AND STRUCTURES
77  *
78  *----------------------------------------------------------------------------
79  */
80
81 /*----------------------------------------------------------------------------
82  *                        PROTOTYPES OF LOCAL FUNCTIONS
83  *
84  *----------------------------------------------------------------------------
85  */
86
87 BOOLEAN
88 MemFCheckInterleaveNodes (
89   IN OUT   MEM_NB_BLOCK *NBPtr
90   );
91
92 /*----------------------------------------------------------------------------
93  *                            EXPORTED FUNCTIONS
94  *
95  *----------------------------------------------------------------------------
96  */
97
98 /* -----------------------------------------------------------------------------*/
99 /**
100  *
101  *  Perform a check to see if node interleaving can be enabled on each node.
102  *
103  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
104  *
105  *     @return          TRUE -  Node interleaving can be enabled.
106  *     @return          FALSE - Node interleaving cannot be enabled.
107  */
108
109 BOOLEAN
110 MemFCheckInterleaveNodes (
111   IN OUT   MEM_NB_BLOCK *NBPtr
112   )
113 {
114   DIE_STRUCT *MCTPtr;
115
116   ASSERT (NBPtr != NULL);
117
118   MCTPtr = NBPtr->MCTPtr;
119
120   if (MCTPtr->NodeMemSize != 0) {
121     if (!NBPtr->SharedPtr->NodeIntlv.IsValid) {
122       NBPtr->SharedPtr->NodeIntlv.NodeMemSize = MCTPtr->NodeMemSize;
123       NBPtr->SharedPtr->NodeIntlv.Dct0MemSize = MCTPtr->DctData[0].Timings.DctMemSize;
124       NBPtr->SharedPtr->NodeIntlv.IsValid = TRUE;
125     } else {
126       if ((NBPtr->SharedPtr->NodeIntlv.NodeMemSize != MCTPtr->NodeMemSize) ||
127           (NBPtr->SharedPtr->NodeIntlv.Dct0MemSize != MCTPtr->DctData[0].Timings.DctMemSize)) {
128         return FALSE;
129       }
130     }
131   }
132   return TRUE;
133 }
134
135 /* -----------------------------------------------------------------------------*/
136 /**
137  *
138  *  Applies Node memory interleaving for each node.
139  *
140  *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
141  *
142  *     @return          TRUE -  This feature is enabled.
143  *     @return          FALSE - This feature is not enabled.
144  */
145
146 BOOLEAN
147 MemFInterleaveNodes (
148   IN OUT   MEM_NB_BLOCK *NBPtr
149   )
150 {
151   UINT8 NodeCnt;
152   UINT8 BitShift;
153   UINT32 MemSize;
154   UINT32 Dct0MemSize;
155   UINT32 NodeSysBase;
156   UINT32 NodeSysLimit;
157   UINT32 HoleBase;
158   UINT32 HoleSize;
159   UINT32 HoleOffset;
160   S_UINT64 SMsr;
161   MEM_PARAMETER_STRUCT *RefPtr;
162   DIE_STRUCT *MCTPtr;
163
164   ASSERT (NBPtr != NULL);
165
166   RefPtr = NBPtr->RefPtr;
167   MCTPtr = NBPtr->MCTPtr;
168   if (RefPtr->GStatus[GsbSoftHole] || RefPtr->GStatus[GsbHWHole]) {
169     HoleBase = RefPtr->HoleBase;
170     HoleSize = _4GB_ - HoleBase;
171   } else {
172     HoleBase = 0;
173     HoleSize = 0;
174   }
175
176   NodeCnt = NBPtr->SharedPtr->NodeIntlv.NodeCnt;
177   Dct0MemSize = NBPtr->SharedPtr->NodeIntlv.Dct0MemSize;
178   MemSize = NBPtr->SharedPtr->NodeIntlv.NodeMemSize;
179
180   BitShift = LibAmdBitScanForward (NodeCnt);
181   Dct0MemSize <<= BitShift;
182   if (HoleSize != 0) {
183     RefPtr->GStatus[GsbHWHole] = TRUE;
184     HoleOffset = HoleSize;
185     if (Dct0MemSize >= HoleBase) {
186       Dct0MemSize += HoleSize;
187     } else {
188       HoleOffset += Dct0MemSize;
189     }
190   } else {
191     HoleOffset = 0;
192   }
193
194   MemSize = (MemSize << BitShift) + HoleSize;
195
196   MCTPtr->NodeSysBase = 0;
197   MCTPtr->NodeSysLimit = MemSize - 1;
198   RefPtr->SysLimit = MemSize - 1;
199
200   // When node interleaving is enabled with larger than 1012GB memory,
201   // system memory limit will be lowered to fill in HT reserved region.
202   // TOP_MEM2 was set in CpuMemTyping and needs to be updated as well.
203   if (RefPtr->SysLimit >= HT_REGION_BASE_RJ16) {
204     if (RefPtr->LimitMemoryToBelow1Tb) {
205       SMsr.hi = HT_REGION_BASE_RJ16 >> (32 - 16);
206       SMsr.lo = HT_REGION_BASE_RJ16 << 16;
207     } else {
208       SMsr.hi = MemSize >> (32 - 16);
209       SMsr.lo = MemSize << 16;
210     }
211     LibAmdMsrWrite (TOP_MEM2, (UINT64 *)&SMsr, &(NBPtr->MemPtr->StdHeader));
212     IDS_HDT_CONSOLE (MEM_FLOW, "TOP_MEM2: %08x0000\n", MemSize);
213     RefPtr->Sub1THoleBase =  HT_REGION_BASE_RJ16;
214     RefPtr->SysLimit = HT_REGION_BASE_RJ16 - 1;
215   } else {
216     RefPtr->Sub1THoleBase =  RefPtr->SysLimit + 1;
217   }
218
219   NBPtr->SetBitField (NBPtr, BFDramIntlvSel, NBPtr->SharedPtr->NodeIntlv.NodeIntlvSel);
220   NBPtr->SetBitField (NBPtr, BFDramBaseAddr, 0);
221   NBPtr->SetBitField (NBPtr, BFDramIntlvEn, NodeCnt - 1);
222   NBPtr->SetBitField (NBPtr, BFDramLimitAddr, (MemSize - 1) >> (27 - 16));
223
224   if (HoleSize != 0) {
225     MCTPtr->Status[SbHWHole] = TRUE;
226     // DramHoleBase will be set when sync address map to other nodes.
227     NBPtr->SetBitField (NBPtr, BFDramHoleOffset, HoleOffset >> (23 - 16));
228     NBPtr->SetBitField (NBPtr, BFDramHoleValid, 1);
229   }
230
231   if ((MCTPtr->DctData[1].Timings.DctMemSize != 0) && (!NBPtr->Ganged)) {
232     NBPtr->SetBitField (NBPtr, BFDctSelBaseAddr, Dct0MemSize >> (27 - 16));
233     NBPtr->SetBitField (NBPtr, BFDctSelBaseOffset, Dct0MemSize >> (26 - 16));
234   }
235
236   NodeSysBase = NodeCnt - 1;
237   NodeSysLimit = ((MemSize - 1)& 0xFFFFFF00) | NBPtr->SharedPtr->NodeIntlv.NodeIntlvSel;
238   NBPtr->SharedPtr->NodeMap[NBPtr->Node].IsValid = TRUE;
239   NBPtr->SharedPtr->NodeMap[NBPtr->Node].SysBase = NodeSysBase;
240   NBPtr->SharedPtr->NodeMap[NBPtr->Node].SysLimit = NodeSysLimit;
241
242   NBPtr->SharedPtr->NodeIntlv.NodeIntlvSel++;
243   return TRUE;
244 }