7 * Northbridge table drive support file for DR
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: (Mem/Feat/TABLE)
12 * @e \$Revision: 51024 $ @e \$Date: 2011-04-18 06:02:44 -0600 (Mon, 18 Apr 2011) $
15 /*****************************************************************************
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
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.
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.
42 * ***************************************************************************
55 #include "OptionMemory.h"
60 #define FILECODE PROC_MEM_FEAT_TABLE_MFTDS_FILECODE
61 /*----------------------------------------------------------------------------
62 * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
64 *----------------------------------------------------------------------------
67 /*-----------------------------------------------------------------------------
68 * DEFINITIONS AND MACROS
70 *-----------------------------------------------------------------------------
72 #define MAX_BYTELANES_PER_CHANNEL (8 + 1) ///< Max Bytelanes per channel
74 /*----------------------------------------------------------------------------
75 * TYPEDEFS, STRUCTURES, ENUMS
77 *----------------------------------------------------------------------------
80 /*----------------------------------------------------------------------------
83 *----------------------------------------------------------------------------
88 IN OUT MEM_NB_BLOCK *NBPtr,
89 IN MEM_TABLE_ALIAS MTPtr
94 IN OUT MEM_NB_BLOCK *NBPtr,
95 IN MEM_TABLE_ALIAS *MTPtr,
99 /*-----------------------------------------------------------------------------
101 * This function initializes bit field translation table
103 * @param[in,out] *NBPtr - Pointer to the MEM_TABLE_ALIAS structure
104 * @param[in] time - Indicate the timing for the register which is written.
107 * ----------------------------------------------------------------------------
111 IN OUT MEM_NB_BLOCK *NBPtr,
115 MEM_TABLE_ALIAS *MTPtr;
116 MEM_TABLE_ALIAS *IdsMTPtr;
118 ASSERT (NBPtr != NULL);
120 IDS_HDT_CONSOLE (MEM_FLOW, "MemFInitTableDrive [%X] Start\n", time);
121 MTPtr = (MEM_TABLE_ALIAS *) NBPtr->RefPtr->TableBasedAlterations;
123 IDS_SKIP_HOOK (IDS_GET_DRAM_TABLE, &IdsMTPtr, &(NBPtr->MemPtr->StdHeader)) {
124 IDS_OPTION_HOOK (IDS_INIT_DRAM_TABLE, NBPtr, &(NBPtr->MemPtr->StdHeader));
125 IDS_OPTION_HOOK (IDS_GET_DRAM_TABLE, &IdsMTPtr, &(NBPtr->MemPtr->StdHeader));
128 SetTableValuesLoop (NBPtr, MTPtr, time);
129 SetTableValuesLoop (NBPtr, IdsMTPtr, time);
131 IDS_OPTION_HOOK (IDS_MT_BASE + time, NBPtr, &(NBPtr->MemPtr->StdHeader));
132 IDS_HDT_CONSOLE (MEM_FLOW, "MemFInitTableDrive End\n");
135 /*-----------------------------------------------------------------------------
137 * This function initializes bit field translation table
139 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
140 * @param[in,out] *MTPtr - Pointer to the MEM_TABLE_ALIAS structure
141 * @param[in] time - Indicate the timing for the register which is written.
144 * ----------------------------------------------------------------------------
148 IN OUT MEM_NB_BLOCK *NBPtr,
149 IN MEM_TABLE_ALIAS *MTPtr,
158 for (i = 0; MTPtr[i].time != MTEnd; i++) {
159 if ((MTPtr[i].attr != MTAuto) && (MTPtr[i].time == time)) {
160 SetTableValues (NBPtr, MTPtr[i]);
163 NBPtr->SwitchDCT (NBPtr, CurDct);
167 /*-----------------------------------------------------------------------------
169 * Engine for setting Table Value.
171 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
172 * @param[in] MTPtr - Pointer to the MEM_TABLE_ALIAS structure
175 * ----------------------------------------------------------------------------
179 IN OUT MEM_NB_BLOCK *NBPtr,
180 IN MEM_TABLE_ALIAS MTPtr
198 ASSERT (MTPtr.time <= MTValidTimePointLimit);
199 ASSERT (MTPtr.attr <= MTOr);
200 ASSERT (MTPtr.node <= MTNodes);
201 ASSERT (MTPtr.dct <= MTDcts);
202 ASSERT (MTPtr.dimm <= MTDIMMs);
203 ASSERT (MTPtr.data.s.bytelane <= MTBLs);
205 for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
206 if ((MTPtr.dct == MTDcts) || (MTPtr.dct == Dct)) {
207 NBPtr->SwitchDCT (NBPtr, Dct);
208 switch (MTPtr.bfindex) {
210 AccessType = AccessRcvEnDly;
214 AccessType = AccessWrDatDly;
215 DqsSavePtr = NBPtr->ChannelPtr->WrDatDlys;
218 AccessType = AccessRdDqsDly;
219 DqsSavePtr = NBPtr->ChannelPtr->RdDqsDlys;
222 AccessType = AccessWrDqsDly;
223 DqsSavePtr = NBPtr->ChannelPtr->WrDqsDlys;
226 AccessType = AccessRdDqs__Dly;
227 DqsSavePtr = NBPtr->ChannelPtr->RdDqs__Dlys;
230 AccessType = AccessPhRecDly;
237 if (AccessType == 0xFF) {
238 if (MTPtr.attr == MTOverride) {
239 NBPtr->SetBitField (NBPtr, MTPtr.bfindex, MTPtr.data.s.value);
241 if (MTPtr.attr == MTSubtract) {
242 NBPtr->SetBitField (NBPtr, MTPtr.bfindex, NBPtr->GetBitField (NBPtr, MTPtr.bfindex) - MTPtr.data.s.value);
244 if (MTPtr.attr == MTAdd) {
245 NBPtr->SetBitField (NBPtr, MTPtr.bfindex, NBPtr->GetBitField (NBPtr, MTPtr.bfindex) + MTPtr.data.s.value);
247 if (MTPtr.attr == MTAnd) {
248 NBPtr->SetBitField (NBPtr, MTPtr.bfindex, (NBPtr->GetBitField (NBPtr, MTPtr.bfindex) & MTPtr.data.s.value));
250 if (MTPtr.attr == MTOr) {
251 NBPtr->SetBitField (NBPtr, MTPtr.bfindex, (NBPtr->GetBitField (NBPtr, MTPtr.bfindex) | MTPtr.data.s.value));
254 // Store the DQS data first
255 for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
256 if (AccessType == AccessRdDqs__Dly) {
257 for (j = 0; j < MAX_NUMBER_LANES; j++) {
258 Temp2Val[i * MAX_NUMBER_LANES + j] = NBPtr->GetTrainDly (NBPtr, AccessType, DIMM_NBBL_ACCESS (i, j));
261 for (j = 0; j < MAX_BYTELANES_PER_CHANNEL; j++) {
262 TempVal[i * MAX_BYTELANES_PER_CHANNEL + j] = NBPtr->GetTrainDly (NBPtr, AccessType, DIMM_BYTE_ACCESS (i, j));
267 // Single Value with Bytleane mask option
268 // Indicated by the vtype flag
270 if (MTPtr.vtype == VT_MSK_VALUE) {
271 // set the value which defined in Memory table.
272 for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
273 ByteLane = MTPtr.data.s.bytelane;
274 if ((MTPtr.dimm == MTDIMMs) || (MTPtr.dimm == i)) {
275 if (AccessType == AccessRdDqs__Dly) {
276 for (j = 0; j < MAX_NUMBER_LANES; j++) {
277 DqsOffset = (i * MAX_NUMBER_LANES + j);
278 if ((ByteLane & (UINT16)1) != 0) {
279 if (MTPtr.attr == MTOverride) {
280 Temp2Val[DqsOffset] = (UINT16)MTPtr.data.s.value;
282 if (MTPtr.attr == MTSubtract) {
283 Temp2Val[DqsOffset] -= (UINT16)MTPtr.data.s.value;
285 if (MTPtr.attr == MTAdd) {
286 Temp2Val[DqsOffset] += (UINT16)MTPtr.data.s.value;
288 NBPtr->SetTrainDly (NBPtr, AccessType, DIMM_NBBL_ACCESS (i, j), (UINT16)Temp2Val[DqsOffset]);
290 if (DqsSavePtr == NULL) {
291 NBPtr->ChannelPtr->RcvEnDlys[DqsOffset] = (UINT16)TempVal[DqsOffset];
293 DqsSavePtr[DqsOffset] = (UINT8)Temp2Val[DqsOffset];
297 ByteLane = ByteLane >> (UINT16)1;
300 for (j = 0; j < MAX_BYTELANES_PER_CHANNEL; j++) {
301 DqsOffset = (i * MAX_BYTELANES_PER_CHANNEL + j);
302 if ((ByteLane & (UINT16)1) != 0) {
303 if (MTPtr.attr == MTOverride) {
304 TempVal[DqsOffset] = (UINT16)MTPtr.data.s.value;
306 if (MTPtr.attr == MTSubtract) {
307 TempVal[DqsOffset] -= (UINT16)MTPtr.data.s.value;
309 if (MTPtr.attr == MTAdd) {
310 TempVal[DqsOffset] += (UINT16)MTPtr.data.s.value;
312 NBPtr->SetTrainDly (NBPtr, AccessType, DIMM_BYTE_ACCESS (i, j), (UINT16)TempVal[DqsOffset]);
314 if (DqsSavePtr == NULL) {
315 NBPtr->ChannelPtr->RcvEnDlys[DqsOffset] = (UINT16)TempVal[DqsOffset];
317 DqsSavePtr[DqsOffset] = (UINT8)TempVal[DqsOffset];
321 ByteLane = ByteLane >> (UINT16)1;
327 // Multiple values specified in a byte array
328 for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
329 if ((MTPtr.dimm == MTDIMMs) || (MTPtr.dimm == i)) {
330 if (AccessType == AccessRdDqs__Dly) {
331 for (j = 0; j < MAX_NUMBER_LANES; j++) {
332 DqsOffset = (i * MAX_NUMBER_LANES + j);
333 if (MTPtr.attr == MTOverride) {
334 Temp2Val[DqsOffset] = MTPtr.data.bytelanevalue[j];
336 if (MTPtr.attr == MTSubtract) {
337 Temp2Val[DqsOffset] -= MTPtr.data.bytelanevalue[j];
339 if (MTPtr.attr == MTAdd) {
340 Temp2Val[DqsOffset] += MTPtr.data.bytelanevalue[j];
342 NBPtr->SetTrainDly (NBPtr, AccessType, DIMM_NBBL_ACCESS (i, j), (UINT16)Temp2Val[DqsOffset]);
344 if (DqsSavePtr == NULL) {
345 NBPtr->ChannelPtr->RcvEnDlys[DqsOffset] = (UINT16)Temp2Val[DqsOffset];
347 DqsSavePtr[DqsOffset] = (UINT8)Temp2Val[DqsOffset];
352 for (j = 0; j < MAX_BYTELANES_PER_CHANNEL; j++) {
353 DqsOffset = (i * MAX_BYTELANES_PER_CHANNEL + j);
354 if (MTPtr.attr == MTOverride) {
355 TempVal[DqsOffset] = MTPtr.data.bytelanevalue[j];
357 if (MTPtr.attr == MTSubtract) {
358 TempVal[DqsOffset] -= MTPtr.data.bytelanevalue[j];
360 if (MTPtr.attr == MTAdd) {
361 TempVal[DqsOffset] += MTPtr.data.bytelanevalue[j];
363 NBPtr->SetTrainDly (NBPtr, AccessType, DIMM_BYTE_ACCESS (i, j), (UINT16)TempVal[DqsOffset]);
365 if (DqsSavePtr == NULL) {
366 NBPtr->ChannelPtr->RcvEnDlys[DqsOffset] = (UINT16)TempVal[DqsOffset];
368 DqsSavePtr[DqsOffset] = (UINT8)TempVal[DqsOffset];
376 // set the DQS value to left DIMMs.
378 while ((i != MTDIMMs) && ((++i) < MAX_DIMMS_PER_CHANNEL)) {
379 if (AccessType == AccessRdDqs__Dly) {
380 for (j = 0; j < MAX_NUMBER_LANES; j++) {
381 NBPtr->SetTrainDly (NBPtr, AccessType, DIMM_NBBL_ACCESS (i, j), (UINT16)Temp2Val[i * MAX_BYTELANES_PER_CHANNEL + j]);
384 for (j = 0; j < MAX_BYTELANES_PER_CHANNEL; j++) {
385 NBPtr->SetTrainDly (NBPtr, AccessType, DIMM_BYTE_ACCESS (i, j), (UINT16)TempVal[i * MAX_BYTELANES_PER_CHANNEL + j]);