blob: 559abcd2dbade365bb51e6367f0c93aab9d2a259 [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * mfecc.c
6 *
7 * Feature ECC initialization functions
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: (Mem/Feat/ECC)
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#include "AGESA.h"
46#include "amdlib.h"
47#include "Ids.h"
48#include "mm.h"
49#include "mn.h"
50#include "mfecc.h"
51#include "Filecode.h"
52#include "mfmemclr.h"
53#include "GeneralServices.h"
54CODE_GROUP (G2_PEI)
55RDATA_GROUP (G2_PEI)
56
57#define FILECODE PROC_MEM_FEAT_ECC_MFECC_FILECODE
58/*----------------------------------------------------------------------------
59 * DEFINITIONS AND MACROS
60 *
61 *----------------------------------------------------------------------------
62 */
63
64/*----------------------------------------------------------------------------
65 * TYPEDEFS AND STRUCTURES
66 *
67 *----------------------------------------------------------------------------
68 */
69
70/*----------------------------------------------------------------------------
71 * PROTOTYPES OF LOCAL FUNCTIONS
72 *
73 *----------------------------------------------------------------------------
74 */
75
76VOID
77STATIC
78InitECCOverriedeStruct (
79 IN OUT MEM_NB_BLOCK *NBPtr,
80 IN OUT ECC_OVERRIDE_STRUCT *pecc_override_struct
81 );
82
83BOOLEAN
84MemFCheckECC (
85 IN OUT MEM_NB_BLOCK *NBPtr
86 );
87
88/*
89 *-----------------------------------------------------------------------------
90 * EXPORTED FUNCTIONS
91 *
92 *-----------------------------------------------------------------------------
93 */
94
95extern BUILD_OPT_CFG UserOptions;
96
97/* -----------------------------------------------------------------------------*/
98/**
99 *
100 *
101 * This function checks to see if ECC can be enabled on all nodes
102 *
103 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
104 *
105 * @return TRUE - This feature is enabled.
106 * @return FALSE - This feature is not enabled.
107 */
108
109BOOLEAN
110MemFCheckECC (
111 IN OUT MEM_NB_BLOCK *NBPtr
112 )
113{
114 DIE_STRUCT *MCTPtr;
115 MEM_SHARED_DATA *SharedPtr;
116 BOOLEAN ErrorRecovery;
117
118 ASSERT (NBPtr != NULL);
119
120 MCTPtr = NBPtr->MCTPtr;
121 SharedPtr = NBPtr->SharedPtr;
122
123 ErrorRecovery = TRUE;
124 IDS_OPTION_HOOK (IDS_MEM_ERROR_RECOVERY, &ErrorRecovery, &NBPtr->MemPtr->StdHeader);
125
126 if (MCTPtr->NodeMemSize != 0) {
127 if (SharedPtr->AllECC && MCTPtr->Status[SbEccDimms] && (ErrorRecovery || (MCTPtr->ErrCode < AGESA_ERROR))) {
128 // Clear all MCA reports before using scrubber
129 // to initialize ECC check bits
130 //
131 NBPtr->McaNbCtlReg = NBPtr->GetBitField (NBPtr, BFMcaNbCtlReg);
132 NBPtr->SetBitField (NBPtr, BFMcaNbCtlReg, 0);
133 NBPtr->SetBitField (NBPtr, BFSyncOnUcEccEn, 0);
134 // In unganged mode, set DctDctIntlv
135 if (!NBPtr->Ganged) {
136 NBPtr->SetBitField (NBPtr, BFDctDatIntLv, 1);
137 }
138 //
139 // Set Ecc Symbol Size
140 //
141 NBPtr->SetEccSymbolSize (NBPtr);
142 // If ECC can be enabled on this node,
143 // set the master ECCen bit (according to setup)
144 //
145 NBPtr->SetBitField (NBPtr, BFDramEccEn, 1);
146 // Do mem clear on current node
147 MemFMctMemClr_Init (NBPtr);
148 return TRUE;
149 } else {
150 if (SharedPtr->AllECC) {
151 SharedPtr->AllECC = FALSE;
152 }
153 // ECC requested but cannot be enabled
154 MCTPtr->Status[SbEccDimms] = FALSE;
155 MCTPtr->ErrStatus[EsbDramECCDis] = TRUE;
156 PutEventLog (AGESA_WARNING, MEM_WARNING_ECC_DIS, NBPtr->Node, 0, 0, 0, &NBPtr->MemPtr->StdHeader);
157 SetMemError (AGESA_WARNING, MCTPtr);
158 }
159 }
160 return FALSE;
161}
162
163 /* -----------------------------------------------------------------------------*/
164/**
165 *
166 *
167 * This function initializes the ECC on all nodes
168 *
169 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
170 *
171 * @return TRUE - This feature is enabled.
172 * @return FALSE - This feature is not enabled.
173 */
174
175BOOLEAN
176MemFInitECC (
177 IN OUT MEM_NB_BLOCK *NBPtr
178 )
179{
180 UINT8 Node;
181 UINT32 ScrubAddrRJ16;
182 DIE_STRUCT *MCTPtr;
183 MEM_SHARED_DATA *SharedPtr;
184 ECC_OVERRIDE_STRUCT ecc_override_struct;
185 BOOLEAN Flag;
186
187 InitECCOverriedeStruct (NBPtr, &ecc_override_struct);
188 IDS_OPTION_HOOK (IDS_ECC, &ecc_override_struct, &(NBPtr->MemPtr->StdHeader));
189
190 ASSERT (NBPtr != NULL);
191
192 MCTPtr = NBPtr->MCTPtr;
193 Node = MCTPtr->NodeId;
194 SharedPtr = NBPtr->SharedPtr;
195 Flag = TRUE;
196
197 NBPtr->FamilySpecificHook[ScrubberErratum] (NBPtr, (VOID *) &Flag);
198
199 if ((MCTPtr->Status[SbEccDimms]) && (SharedPtr->AllECC)) {
200 // Check if the input dram scrub rate is supported or not
201 ASSERT (ecc_override_struct.CfgScrubDramRate <= 0x16);
202 if (ecc_override_struct.CfgScrubDramRate != 0) {
203 // Program scrub address,
204 // let the scrub Addr be the Base of this Node
205 // Only enable Dram scrubber when there is memory on current node
206 //
207 NBPtr->SetBitField (NBPtr, BFScrubReDirEn, 0);
208 ScrubAddrRJ16 = (NBPtr->GetBitField (NBPtr, BFDramBaseReg0 + Node) & 0xFFFF0000) >> 8;
209 ScrubAddrRJ16 |= NBPtr->GetBitField (NBPtr, BFDramBaseHiReg0 + Node) << 24;
210 NBPtr->SetBitField (NBPtr, BFScrubAddrLoReg, ScrubAddrRJ16 << 16);
211 NBPtr->SetBitField (NBPtr, BFScrubAddrHiReg, ScrubAddrRJ16 >> 16);
212 NBPtr->SetBitField (NBPtr, BFDramScrub, ecc_override_struct.CfgScrubDramRate);
213 }
214 }
215 // Scrub CTL for Dcache, L2, L3
216 // Check if the input L2 scrub rate is supported or not
217 ASSERT (ecc_override_struct.CfgScrubL2Rate <= 0x16);
218 NBPtr->SetBitField (NBPtr, BFL2Scrub, ecc_override_struct.CfgScrubL2Rate);
219 // Check if the input Dcache scrub rate is supported or not
220 ASSERT (ecc_override_struct.CfgScrubDcRate <= 0x16);
221 NBPtr->SetBitField (NBPtr, BFDcacheScrub, ecc_override_struct.CfgScrubDcRate);
222 // Do not enable L3 Scrub if F3xE8[L3Capable] is 0 or F3x188[DisableL3] is 1
223 if ((NBPtr->GetBitField (NBPtr, BFL3Capable) == 1) && (NBPtr->GetBitField (NBPtr, BFDisableL3) == 0)) {
224 // Check if input L3 scrub rate is supported or not
225 ASSERT (ecc_override_struct.CfgScrubL3Rate <= 0x16);
226 NBPtr->SetBitField (NBPtr, BFL3Scrub, ecc_override_struct.CfgScrubL3Rate);
227 }
228
229 // Check if Dcache scrubber or L2 scrubber is enabled
230 if ((ecc_override_struct.CfgScrubL2Rate != 0) || (ecc_override_struct.CfgScrubDcRate!= 0)) {
231 // If ClkDivisor is deeper than divide-by-16
232 if (NBPtr->GetBitField (NBPtr, BFC1ClkDivisor) > 4) {
233 // Set it to divide-by-16
234 NBPtr->SetBitField (NBPtr, BFC1ClkDivisor, 4);
235 }
236 }
237
238 NBPtr->SetBitField (NBPtr, BFScrubReDirEn, ecc_override_struct.CfgEccRedirection);
239 NBPtr->SetBitField (NBPtr, BFSyncOnUcEccEn, ecc_override_struct.CfgEccSyncFlood);
240 // Restore MCA reports after scrubber is done
241 // with initializing ECC check bits
242 NBPtr->SetBitField (NBPtr, BFMcaNbCtlReg, NBPtr->McaNbCtlReg);
243
244 Flag = FALSE;
245 NBPtr->FamilySpecificHook[ScrubberErratum] (NBPtr, (VOID *) &Flag);
246
247 return TRUE;
248}
249
250VOID
251STATIC
252InitECCOverriedeStruct (
253 IN OUT MEM_NB_BLOCK *NBPtr,
254 IN OUT ECC_OVERRIDE_STRUCT *pecc_override_struct
255 )
256{
257 //
258 // If (D18F3x44[DramEccEn]==1) THEN 1 ELSE 0 ENDIF
259 //
260 if (NBPtr->GetBitField (NBPtr, BFDramEccEn) == 1) {
261 pecc_override_struct->CfgEccRedirection = 1;
262 } else {
263 pecc_override_struct->CfgEccRedirection = 0;
264 }
265
266 pecc_override_struct->CfgEccSyncFlood = UserOptions.CfgEccSyncFlood;
267 pecc_override_struct->CfgScrubDcRate = UserOptions.CfgScrubDcRate;
268
269 if (UserOptions.CfgScrubDramRate != 0xFF) {
270 pecc_override_struct->CfgScrubDramRate = UserOptions.CfgScrubDramRate;
271 } else {
272 if (NBPtr->MCTPtr->NodeMemSize <= 0x4000) {
273 pecc_override_struct->CfgScrubDramRate = 0x12; // 1 ~ 1 GB
274 } else if (NBPtr->MCTPtr->NodeMemSize <= 0x8000) {
275 pecc_override_struct->CfgScrubDramRate = 0x11; // 1 GB + 1 ~ 2 GB
276 } else if (NBPtr->MCTPtr->NodeMemSize <= 0x10000) {
277 pecc_override_struct->CfgScrubDramRate = 0x10; // 2 GB + 1 ~ 4 GB
278 } else if (NBPtr->MCTPtr->NodeMemSize <= 0x20000) {
279 pecc_override_struct->CfgScrubDramRate = 0x0F; // 4 GB + 1 ~ 8 GB
280 } else if (NBPtr->MCTPtr->NodeMemSize <= 0x40000) {
281 pecc_override_struct->CfgScrubDramRate = 0x0E; // 8 GB + 1 ~ 16 GB
282 } else {
283 pecc_override_struct->CfgScrubDramRate = 0x0D; //16 GB + 1 above
284 }
285 }
286
287 pecc_override_struct->CfgScrubL2Rate = UserOptions.CfgScrubL2Rate;
288 pecc_override_struct->CfgScrubL3Rate = UserOptions.CfgScrubL3Rate;
289}