blob: 09ecd54474ae4334d87d1ef992f34de658f65510 [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * mfcsi.c
6 *
7 * Feature bank interleaving support (AKA Chip Select Interleaving )
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: (Mem/Feat/Csintlv)
12 * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
13 *
14 **/
15/*****************************************************************************
16 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080017 * Copyright (c) 2008 - 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.
zbao7d94cf92012-07-02 14:19:14 +080041 * ***************************************************************************
42 *
43 */
44
45
46/* This file contains functions for Chip Select interleaving */
47
48
49
50#include "AGESA.h"
51#include "amdlib.h"
52#include "mm.h"
53#include "mn.h"
54#include "mt.h"
55#include "mfcsi.h"
56#include "Ids.h"
57#include "GeneralServices.h"
58#include "Filecode.h"
59CODE_GROUP (G2_PEI)
60RDATA_GROUP (G2_PEI)
61
62#define FILECODE PROC_MEM_FEAT_CSINTLV_MFCSI_FILECODE
63/*----------------------------------------------------------------------------
64 * DEFINITIONS AND MACROS
65 *
66 *----------------------------------------------------------------------------
67 */
68
69/*----------------------------------------------------------------------------
70 * TYPEDEFS AND STRUCTURES
71 *
72 *----------------------------------------------------------------------------
73 */
74
75/*----------------------------------------------------------------------------
76 * PROTOTYPES OF LOCAL FUNCTIONS
77 *
78 *----------------------------------------------------------------------------
79 */
80
81BOOLEAN
82STATIC
83MemFDctInterleaveBanks (
84 IN OUT MEM_NB_BLOCK *NBPtr
85 );
86
87VOID
88STATIC
89CsIntSwap (
90 IN OUT UINT32 *BaseMaskRegPtr,
91 IN UINT8 EnChipSels,
92 IN UINT8 LoBit,
93 IN UINT8 HiBit
94 );
95
96BOOLEAN
97MemFUndoInterleaveBanks (
98 IN OUT MEM_NB_BLOCK *NBPtr
99 );
100
101/*
102 *-----------------------------------------------------------------------------
103 * EXPORTED FUNCTIONS
104 *
105 *-----------------------------------------------------------------------------
106 */
107
108/* -----------------------------------------------------------------------------*/
109/**
110 *
111 *
112 * This function Applies DIMM bank (chip-select) interleaving if enabled
113 * and if all criteria are met. Interleaves chip-selects on page boundaries.
114 * This function calls subfunctions that sets up CS interleaving on multiple Sockets
115 *
116 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
117 *
118 * @return TRUE - This feature is enabled.
119 * @return FALSE - This feature is not enabled.
120 */
121
122BOOLEAN
123MemFInterleaveBanks (
124 IN OUT MEM_NB_BLOCK *NBPtr
125 )
126{
127 UINT8 Dct;
128 BOOLEAN RetFlag;
129
130 ASSERT (NBPtr != NULL);
131
132 RetFlag = FALSE;
133 if (NBPtr->RefPtr->EnableBankIntlv) {
134 if (NBPtr->MCTPtr->NodeMemSize) {
135 for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
136 NBPtr->SwitchDCT (NBPtr, Dct);
137 RetFlag |= MemFDctInterleaveBanks (NBPtr);
138 }
139 }
140 }
141 return RetFlag;
142}
143
144/* -----------------------------------------------------------------------------*/
145/**
146 *
147 *
148 * This function checks if bank interleaving has been enabled or not. If yes, it will
149 * undo bank interleaving. Otherwise, it does nothing.
150 *
151 *
152 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
153 *
154 * @return TRUE - Bank interleaving has been enabled.
155 * @return FALSE - Bank interleaving has not been enabled.
156 */
157
158BOOLEAN
159MemFUndoInterleaveBanks (
160 IN OUT MEM_NB_BLOCK *NBPtr
161 )
162{
163 UINT8 Cs;
164 UINT8 Dct;
165 UINT32 CSMask;
166 BOOLEAN CSIntlvEnabled;
167 BOOLEAN RetFlag;
168
169 ASSERT (NBPtr != NULL);
170
171 RetFlag = FALSE;
172
173 if (NBPtr->RefPtr->EnableBankIntlv) {
174 for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
175 NBPtr->SwitchDCT (NBPtr, Dct);
176 if (NBPtr->DCTPtr->Timings.DctMemSize) {
177 CSIntlvEnabled = FALSE;
178 for (Cs = 0; Cs < MAX_CS_PER_CHANNEL; Cs++) {
179 if ((NBPtr->GetBitField (NBPtr, BFCSBaseAddr0Reg + Cs) & 1) != 0) {
180 CSMask = NBPtr->GetBitField (NBPtr, BFCSMask0Reg + (Cs / 2));
181 if (((CSMask >> 5) & 0x1FF) != 0x1FF) {
182 CSIntlvEnabled = TRUE;
183 break;
184 }
185 }
186 }
187 if (CSIntlvEnabled) {
188 MemFDctInterleaveBanks (NBPtr);
189 RetFlag = TRUE;
190 }
191 }
192 }
193 }
194 return RetFlag;
195}
196
197/*----------------------------------------------------------------------------
198 * LOCAL FUNCTIONS
199 *
200 *----------------------------------------------------------------------------
201 */
202
203/* -----------------------------------------------------------------------------*/
204/**
205 *
206 *
207 * This function Applies DIMM bank (chip-select) interleaving if enabled
208 * and if all criteria are met. Interleaves chip-selects on page boundaries.
209 * This function is run once per Socket
210 *
211 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
212 *
213 * @return TRUE - Register bits have been swapped.
214 * @return FALSE - Register bits have not been swapped.
215 *
216 */
217
218BOOLEAN
219STATIC
220MemFDctInterleaveBanks (
221 IN OUT MEM_NB_BLOCK *NBPtr
222 )
223{
224 UINT8 Cs;
225 UINT8 EnChipSels;
226 UINT8 BankEncd;
227 UINT8 BankEncd0;
228 UINT8 i;
229 UINT8 j;
230 UINT32 BankAddrReg;
231 UINT32 BaseRegS0;
232 UINT32 BaseRegS1;
233 UINT32 MaskReg;
234 UINT8 Offset;
235 UINT8 Dct;
236
237 ASSERT (NBPtr != NULL);
238
239 Dct = NBPtr->Dct;
240
241 // Check if CS interleaving can be enabled
242 EnChipSels = 0;
243 BankEncd0 = 0xFF;
244 Offset = 0;
245 for (Cs = 0; Cs < MAX_CS_PER_CHANNEL; Cs++) {
246 if ((NBPtr->GetBitField (NBPtr, BFCSBaseAddr0Reg + Cs) & 3) != 0) {
247 BankAddrReg = NBPtr->GetBitField (NBPtr, BFDramBankAddrReg);
248 BankEncd = (UINT8) ((BankAddrReg >> ((Cs / 2) * 4)) & 0xF);
249 if (BankEncd0 == 0xFF) {
250 BankEncd0 = BankEncd;
251 } else if (BankEncd0 != BankEncd) {
252 break;
253 }
254 if ((NBPtr->GetBitField (NBPtr, BFCSBaseAddr0Reg + Cs) & 1) != 0) {
255 EnChipSels++;
256 }
257 }
258 }
259
260 // Swap Dram Base/Mask Addr to enable CS interleaving
261 if ((Cs == MAX_CS_PER_CHANNEL) && ((EnChipSels == 2) || (EnChipSels == 4) || (EnChipSels == 8))) {
262 NBPtr->TechPtr->GetCSIntLvAddr (BankEncd0, &i, &j);
263 // Family specific CS interleaving low address adjustment
264 NBPtr->FamilySpecificHook[AdjustCSIntLvLowAddr] (NBPtr, &i);
265
266 if (NBPtr->MCTPtr->Status[Sb128bitmode]) {
267 i++;
268 j++;
269 }
270
271 for (Cs = 0; Cs < MAX_CS_PER_CHANNEL; Cs += 2) {
272 //
273 // LRDIMMS - Add an offset to the bit positions specified based on D18F2x[6C:60]_dct[1:0][RankDef] as follows:
274 // RankDef=0xb: 0 RankDef=10b: 1 RankDef=11b: 2
275 // Using RankMult information: Lo/HiBit <<= (Mult >> 1)
276 //
277 if (NBPtr->MCTPtr->Status[SbLrdimms]) {
278 Offset = ((NBPtr->ChannelPtr->LrDimmRankMult[Cs >> 1]) >> 1);
279 }
280 BaseRegS0 = NBPtr->GetBitField (NBPtr, BFCSBaseAddr0Reg + Cs);
281 BaseRegS1 = NBPtr->GetBitField (NBPtr, BFCSBaseAddr0Reg + Cs + 1);
282 if (((BaseRegS0 | BaseRegS1) & 1) != 0) {
283 // Swap Mask register bits
284 MaskReg = NBPtr->GetBitField (NBPtr, BFCSMask0Reg + (Cs / 2));
285 CsIntSwap (&MaskReg, EnChipSels, (i + Offset), (j + Offset));
286 NBPtr->SetBitField (NBPtr, BFCSMask0Reg + (Cs / 2), MaskReg);
287
288 // Swap Base register bits
289 CsIntSwap (&BaseRegS0, EnChipSels, (i + Offset), (j + Offset));
290 NBPtr->SetBitField (NBPtr, BFCSBaseAddr0Reg + Cs, BaseRegS0);
291 CsIntSwap (&BaseRegS1, EnChipSels, (i + Offset), (j + Offset));
292 NBPtr->SetBitField (NBPtr, BFCSBaseAddr0Reg + Cs + 1, BaseRegS1);
293 }
294 }
295 //
296 // Bank Interleaving is requested and has been enabled as well
297 //
298 NBPtr->MCTPtr->DctData[Dct].BkIntDis = FALSE;
299 return TRUE;
300 } else {
301 //
302 // Bank Interleaving is requested but cannot be enabled
303 //
304 PutEventLog (AGESA_WARNING, MEM_WARNING_BANK_INTERLEAVING_NOT_ENABLED, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
305 SetMemError (AGESA_WARNING, NBPtr->MCTPtr);
306 NBPtr->MCTPtr->DctData[Dct].BkIntDis = TRUE;
307 }
308 return FALSE;
309}
310
311/* -----------------------------------------------------------------------------*/
312/**
313 *
314 * This supporting function swaps Chip selects
315 *
316 * @param[in,out] *BaseMaskRegPtr - Pointer to the Mask Register
317 * @param[in] *EnChipSels - Chip Selects to Enable
318 * @param[in] *LoBit - Lowest Bit
319 * @param[in] *HiBit - Highest Bit
320 *
321 *
322 */
323
324VOID
325STATIC
326CsIntSwap (
327 IN OUT UINT32 *BaseMaskRegPtr,
328 IN UINT8 EnChipSels,
329 IN UINT8 LoBit,
330 IN UINT8 HiBit
331 )
332{
333 UINT8 BitDelta;
334 UINT32 TempHi;
335 UINT32 TempLo;
336 UINT32 AddrLoMask;
337 UINT32 AddrHiMask;
338
339 ASSERT (BaseMaskRegPtr != NULL);
340 ASSERT (HiBit > LoBit);
341
342 BitDelta = HiBit - LoBit;
343 AddrLoMask = (((UINT32)EnChipSels) - 1) << LoBit;
344 AddrHiMask = AddrLoMask << BitDelta;
345
346 TempHi = TempLo = *BaseMaskRegPtr;
347 TempLo &= AddrLoMask;
348 TempLo <<= BitDelta; // move lower bits to upper bit position
349 TempHi &= AddrHiMask;
350 TempHi >>= BitDelta; // move upper bits to lower bit position
351
352 *BaseMaskRegPtr &= ~AddrLoMask;
353 *BaseMaskRegPtr &= ~AddrHiMask;
354 *BaseMaskRegPtr |= TempLo | TempHi;
355}