blob: 00817b956c5e8b2111a30c6bc2d14d8b06922d99 [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * mndcton.c
6 *
7 * Northbridge ON DCT supporting functions
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: (Mem/NB/ON)
efdesign9884cbce22011-08-04 12:09:17 -060012 * @e \$Revision: 48511 $ @e \$Date: 2011-03-09 13:53:13 -0700 (Wed, 09 Mar 2011) $
Frank Vibrans2b4c8312011-02-14 18:30:54 +000013 *
14 **/
15/*
16 *****************************************************************************
17 *
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100020 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000021 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100028 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
Frank Vibrans2b4c8312011-02-14 18:30:54 +000030 * from this software without specific prior written permission.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100031 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000032 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100042 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000043 * ***************************************************************************
44 *
45 */
46
47
48/*
49 *----------------------------------------------------------------------------
50 * MODULES USED
51 *
52 *----------------------------------------------------------------------------
53 */
54
55
56
57#include "AGESA.h"
58#include "amdlib.h"
59#include "Ids.h"
60#include "mm.h"
61#include "mn.h"
62#include "mt.h"
63#include "mu.h"
64#include "OptionMemory.h" // need def for MEM_FEAT_BLOCK_NB
65#include "mnon.h"
66#include "merrhdl.h"
67#include "GeneralServices.h"
68#include "cpuFamilyTranslation.h"
69#include "cpuCommonF14Utilities.h"
70#include "Filecode.h"
71#define FILECODE PROC_MEM_NB_ON_MNDCTON_FILECODE
72/*----------------------------------------------------------------------------
73 * DEFINITIONS AND MACROS
74 *
75 *----------------------------------------------------------------------------
76 */
77#define UNUSED_CLK 4
78#define MAX_RD_DQS_DLY 0x1F
79
80/*----------------------------------------------------------------------------
81 * TYPEDEFS AND STRUCTURES
82 *
83 *----------------------------------------------------------------------------
84 */
85
86/*----------------------------------------------------------------------------
87 * PROTOTYPES OF LOCAL FUNCTIONS
88 *
89 *----------------------------------------------------------------------------
90 */
91
92/*----------------------------------------------------------------------------
93 * EXPORTED FUNCTIONS
94 *
95 *----------------------------------------------------------------------------
96 */
97
98extern BUILD_OPT_CFG UserOptions;
99
100/* -----------------------------------------------------------------------------*/
101/**
102 *
103 *
104 * This function programs the memory controller with configuration parameters
105 *
106 *
107 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
108 *
109 * @return TRUE - An Error value lower than AGESA_FATAL may have occurred
110 * @return FALSE - An Error value greater than or equal to AGESA_FATAL may have occurred
111 * @return NBPtr->MCTPtr->ErrCode - Contains detailed AGESA_STATUS value
112 */
113
114BOOLEAN
115MemNAutoConfigON (
116 IN OUT MEM_NB_BLOCK *NBPtr
117 )
118{
119 DIE_STRUCT *MCTPtr;
120 DCT_STRUCT *DCTPtr;
121 UINT8 PowerDownMode;
122
123 MCTPtr = NBPtr->MCTPtr;
124 DCTPtr = NBPtr->DCTPtr;
125 //======================================================================
126 // Build Dram Control Register Value (F2x78)
127 //======================================================================
128 //
129
130 //======================================================================
131 // Build Dram Config Lo Register Value
132 //======================================================================
133 //
134 MemNSetBitFieldNb (NBPtr, BFEnDispAutoPrecharge, 1);
135
136 MemNSetBitFieldNb (NBPtr, BFIdleCycInit, 3);
137
138 //======================================================================
139 // Build Dram Config Hi Register Value
140 //======================================================================
141 //
142
143 MemNSetBitFieldNb (NBPtr, BFMemClkFreq, MemNGetMemClkFreqIdClientNb (NBPtr, DCTPtr->Timings.Speed));
144
145 PowerDownMode = (UINT8) ((UserOptions.CfgPowerDownMode == POWER_DOWN_MODE_AUTO) ? POWER_DOWN_BY_CHIP_SELECT : UserOptions.CfgPowerDownMode);
146 PowerDownMode = (!NBPtr->IsSupported[ChannelPDMode]) ? PowerDownMode : 0;
147 IDS_OPTION_HOOK (IDS_POWERDOWN_MODE, &PowerDownMode, &(NBPtr->MemPtr->StdHeader));
148 if (PowerDownMode == 1) {
149 MemNSetBitFieldNb (NBPtr, BFPowerDownMode, 1);
150 }
151
efdesign9884cbce22011-08-04 12:09:17 -0600152 MemNSetBitFieldNb (NBPtr, BFPchgPDModeSel, (((MemNGetBitFieldNb (NBPtr, BFLowPowerDefault)) == 1) && (NBPtr->MemPtr->PlatFormConfig->PlatformProfile.PlatformPowerPolicy == BatteryLife)) ? 0 : 1);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000153
154 MemNSetBitFieldNb (NBPtr, BFDcqBypassMax, 0xE);
155
156 MemNSetBitFieldNb (NBPtr, BFDctSelBankSwap, 1);
157
158 //======================================================================
159 // Build Dram Config Misc Register Value
160 //======================================================================
161 //
162 // Max out Non-SPD timings
163 MemNSetBitFieldNb (NBPtr, BFNonSPD, 0x18FF);
164 MemNSetBitFieldNb (NBPtr, BFNonSPDHi, 0x2A);
165 MemNSetBitFieldNb (NBPtr, BFTwrrdSD, 0xA);
166 MemNSetBitFieldNb (NBPtr, BFTrdrdSD, 0x8);
167 MemNSetBitFieldNb (NBPtr, BFTwrwrSD, 0x9);
168
169 MemNSetBitFieldNb (NBPtr, BFWrOdtOnDuration, DEFAULT_WR_ODT_ON_ON);
170 MemNSetBitFieldNb (NBPtr, BFRdOdtOnDuration, DEFAULT_RD_ODT_ON_ON);
171 MemNSetBitFieldNb (NBPtr, BFWrOdtTrnOnDly, 0);
172
173 //======================================================================
174 // DRAM MRS Register, set ODT
175 //======================================================================
176 MemNSetBitFieldNb (NBPtr, BFBurstCtrl, 1);
177
178 // DrvImpCtrl: drive impedance control.01b(34 ohm driver; Ron34 = Rzq/7)
179 MemNSetBitFieldNb (NBPtr, BFDrvImpCtrl, 1);
180
181 return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
182}
183
184/*----------------------------------------------------------------------------
185 * LOCAL FUNCTIONS
186 *
187 *----------------------------------------------------------------------------
188 */
189
190/* -----------------------------------------------------------------------------*/
191/**
192 *
193 * This function sends an MRS command
194 *
195 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
196 *
197 */
198
199VOID
200MemNSendMrsCmdON (
201 IN OUT MEM_NB_BLOCK *NBPtr
202 )
203{
204 MemNSetASRSRTNb (NBPtr);
205 MemNSwapBitsNb (NBPtr);
206
207 IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tCS%d MR%d %04x\n",
208 (MemNGetBitFieldNb (NBPtr, BFDramInitRegReg) >> 20) & 0xF,
209 (MemNGetBitFieldNb (NBPtr, BFDramInitRegReg) >> 16) & 0xF,
210 (MemNGetBitFieldNb (NBPtr, BFDramInitRegReg) & 0xFFFF));
211
212 // 1.Set SendMrsCmd=1
213 MemNSetBitFieldNb (NBPtr, BFSendMrsCmd, 1);
214
215 // 2.Wait for SendMrsCmd=0
216 MemNPollBitFieldNb (NBPtr, BFSendMrsCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
217}
218
219/* -----------------------------------------------------------------------------*/
220/**
221 *
222 *
223 * This function combines all the memory into a contiguous map.
224 * Requires that Mask values for each bank be programmed first and that
225 * the chip-select population indicator is correctly set.
226 *
227 *
228 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
229 *
230 * @return TRUE - An Error value lower than AGESA_FATAL may have occurred
231 * @return FALSE - An Error value greater than or equal to AGESA_FATAL may have occurred
232 */
233
234BOOLEAN
235MemNStitchMemoryON (
236 IN OUT MEM_NB_BLOCK *NBPtr
237 )
238{
239 UINT32 NxtCSBase;
240 UINT32 CurCSBase;
241 UINT32 CsSize;
242 UINT32 BiggestBank;
243 UINT8 p;
244 UINT8 q;
245 UINT8 BiggestDimm;
246 DIE_STRUCT *MCTPtr;
247 DCT_STRUCT *DCTPtr;
248 MCTPtr = NBPtr->MCTPtr;
249 DCTPtr = NBPtr->DCTPtr;
250
251 DCTPtr->Timings.CsEnabled = 0;
252 NxtCSBase = 0;
253 for (p = 0; p < MAX_CS_PER_CHANNEL_ON; p++) {
254 BiggestBank = 0;
255 BiggestDimm = 0;
256 for (q = 0; q < MAX_CS_PER_CHANNEL_ON; q++) {
257 if (((DCTPtr->Timings.CsPresent & ~DCTPtr->Timings.CsTestFail) & ((UINT16)1 << q)) != 0) {
258 if ((MemNGetBitFieldNb (NBPtr, BFCSBaseAddr0Reg + q) & 7) == 0) {
259 // (CSEnable|Spare==1)bank is not enabled yet
260 CsSize = MemNGetBitFieldNb (NBPtr, BFCSMask0Reg + (q >> 1));
261 if (CsSize != 0) {
262 CsSize += ((UINT32)1 << 19);
263 CsSize &= 0xFFF80000;
264 }
265 if (CsSize > BiggestBank) {
266 BiggestBank = CsSize;
267 BiggestDimm = q;
268 }
269 }
270 }
271 }
272
273 if (BiggestBank != 0) {
274 CurCSBase = NxtCSBase;
275 CurCSBase |= ((UINT32)1 << BFCSEnable);
276 NxtCSBase += BiggestBank;
277 if ((BiggestDimm & 1) != 0) {
278 if ((DCTPtr->Timings.DimmMirrorPresent & (1 << (BiggestDimm >> 1))) != 0) {
279 CurCSBase |= ((UINT32)1 << BFOnDimmMirror);
280 }
281 }
282 MemNSetBitFieldNb (NBPtr, BFCSBaseAddr0Reg + BiggestDimm, CurCSBase);
283 DCTPtr->Timings.CsEnabled |= (1 << BiggestDimm);
284 }
285 if ((DCTPtr->Timings.CsTestFail & ((UINT16)1 << p)) != 0) {
286 MemNSetBitFieldNb (NBPtr, (BFCSBaseAddr0Reg + p), (UINT32)1 << BFTestFail);
287 }
288 }
289
290 if (NxtCSBase != 0) {
291 DCTPtr->Timings.DctMemSize = NxtCSBase >> 8; // Scale base address from [39:8] to [47:16]
292 NBPtr->MCTPtr->NodeMemSize += NBPtr->DCTPtr->Timings.DctMemSize;
293 NBPtr->MCTPtr->NodeSysLimit = NBPtr->MCTPtr->NodeMemSize - 1;
294 } else {
295 PutEventLog (AGESA_FATAL, MEM_ERROR_NO_DIMM_FOUND_ON_SYSTEM, 0, 0, 0, 0, &NBPtr->MemPtr->StdHeader);
296 SetMemError (AGESA_FATAL, MCTPtr);
297 }
298
299 return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
300}
301
302/* -----------------------------------------------------------------------------*/
303/**
304 *
305 *
306 * This function sets the maximum round-trip latency in the system from the processor to the DRAM
307 * devices and back for Ontario.
308 *
309 *
310 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
311 * @param[in] MaxRcvEnDly - Maximum receiver enable delay value
312 *
313 */
314
315VOID
316MemNSetMaxLatencyON (
317 IN OUT MEM_NB_BLOCK *NBPtr,
318 IN UINT16 MaxRcvEnDly
319 )
320{
321 UINT32 N;
322 UINT32 T;
323 UINT32 P;
324 UINT32 Px2;
325 UINT32 MemClkPeriod;
326
327 AGESA_TESTPOINT (TpProcMemRcvrCalcLatency, &(NBPtr->MemPtr->StdHeader));
328
329 N = 0x50; // init value for MaxRdLat used in training
330
331 if (MaxRcvEnDly != 0xFFFF) {
332 T = MemNTotalSyncComponentsClientNb (NBPtr);
333
334 // P = P + CEIL(MAX (total delay in DqsRcvEn + RdDqsTime))
335 P = ((MaxRcvEnDly + MAX_RD_DQS_DLY) + 31) / 32;
336
337 // P = P + 6.5
338 // T = T + 2586 ps
339 Px2 = (P * 2) + 13;
340 T += 2586;
341
342 // N = (P/(MemClkFreq * 2) + T) * NclkFreq
343 MemClkPeriod = 1000000 / NBPtr->DCTPtr->Timings.Speed;
344 N = ((((Px2 * MemClkPeriod + 3) / 4) + T) * NBPtr->NBClkFreq + 999999) / 1000000;
345 N += 2;
346 }
347
348 NBPtr->DCTPtr->Timings.MaxRdLat = (UINT16) N;
349 ASSERT (N <= 0x3FF);
350 IDS_HDT_CONSOLE (MEM_FLOW, "\t\tMaxRdLat: %03x\n", N);
351 MemNSetBitFieldNb (NBPtr, BFMaxLatency, N);
352}
353
354/* -----------------------------------------------------------------------------*/
355/**
356 *
357 *
358 * This function retrieves the Max latency parameters
359 *
360 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
361 *
362 * @param[in] *MinDlyPtr - Pointer to variable to store the Minimum Delay value
363 * @param[in] *MaxDlyPtr - Pointer to variable to store the Maximum Delay value
364 * @param[in] *DlyBiasPtr - Pointer to variable to store Delay Bias value
365 * @param[in] MaxDlyForMaxRdLat - Maximum receiver enable delay value
366 *
367 */
368
369VOID
370MemNGetMaxLatParamsClientON (
371 IN OUT MEM_NB_BLOCK *NBPtr,
372 IN UINT16 MaxDlyForMaxRdLat,
373 IN OUT UINT16 *MinDlyPtr,
374 IN OUT UINT16 *MaxDlyPtr,
375 IN OUT UINT16 *DlyBiasPtr
376 )
377{
378 UINT32 P;
379 UINT32 Px2;
380 UINT32 T;
381 UINT32 MemClkPeriod;
382
383 T = MemNTotalSyncComponentsClientNb (NBPtr);
384
385 // P = P + CEIL(MAX (total delay in DqsRcvEn + RdDqsTime))
386 P = (MaxDlyForMaxRdLat + 31) / 32;
387
388 // P = P + 6.5
389 // T = T + 2586 ps
390 Px2 = (P * 2) + 13;
391 T += 2586;
392
393 // N = (P/(MemClkFreq * 2) + T) * NclkFreq
394 MemClkPeriod = 1000000 / NBPtr->DCTPtr->Timings.Speed;
395
396 *MinDlyPtr = (UINT16) (((((Px2 * MemClkPeriod + 3) / 4) + T) * NBPtr->NBClkFreq + 999999) / 1000000);
397
398 if (NBPtr->NbFreqChgState == 1) {
399 *MinDlyPtr += 2;
400 } else {
401 *MinDlyPtr += 1;
402 }
403
404 *MaxDlyPtr = 100 + *MinDlyPtr; // 100 fixed iterations
405
406 // IF ((NCLK!=MEMCLK) && (NCLK!=MEMCLK/2))
407 // THEN TrainingOffset = 3
408 // ELSE TrainingOffset = 2
409 if ((NBPtr->NBClkFreq == NBPtr->DCTPtr->Timings.Speed) ||
410 (NBPtr->NBClkFreq == (UINT32) (NBPtr->DCTPtr->Timings.Speed / 2)) ||
411 (NBPtr->NBClkFreq == (UINT32) (NBPtr->DCTPtr->Timings.Speed / 2 + 1))) {
412 *DlyBiasPtr = 2;
413 } else {
414 *DlyBiasPtr = 3;
415 }
416
417 // Register settings required before MaxRdLat training
418 MemNSetBitFieldNb (NBPtr, BFForceCasToSlot0, 1);
419}
420
421/* -----------------------------------------------------------------------------*/
422/**
423 *
424 * This function is a wrapper to call a CPU routine to change NB P-state and
425 * update NB frequency.
426 *
427 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
428 * @param[in] *NBPstate - NB Pstate
429 *
430 * @return TRUE - Succeed
431 * @return FALSE - Fail
432 */
433BOOLEAN
434MemNChangeNbFrequencyWrapON (
435 IN OUT MEM_NB_BLOCK *NBPtr,
436 IN UINT32 NBPstate
437 )
438{
439 BOOLEAN Status;
440 UINT32 NBFreq;
441 UINT32 Memclk;
442 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
443
444 if (NBPtr->NbFreqChgState == 0) {
445 // While in state 0, report the new memclk to the
446 // CPU module to adjust the NB P-state settings.
447 Memclk = NBPtr->DCTPtr->Timings.Speed;
448 } else {
449 // We have already adjusted for target memclk.
450 // Indicate NB P-state change only.
451 Memclk = 0;
452 }
453
454 Status = F14NbPstateInit (Memclk,
455 MemNGetMemClkFreqIdClientNb (NBPtr, NBPtr->DCTPtr->Timings.Speed),
456 NBPstate,
457 &NBFreq,
458 &(NBPtr->MemPtr->StdHeader));
459 if (Status) {
460 // When NB frequency change succeeds, TSC rate may have changed.
461 // We need to update TSC rate
efdesign9884cbce22011-08-04 12:09:17 -0600462 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &NBPtr->MemPtr->StdHeader);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000463 FamilySpecificServices->GetTscRate (FamilySpecificServices, &NBPtr->MemPtr->TscRate, &NBPtr->MemPtr->StdHeader);
464 }
465 return Status;
466}
467
468/* -----------------------------------------------------------------------------*/
469/**
470 *
471 * This function sets Dqs Odt for ON
472 *
473 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
474 * @param[in,out] *OptParam - Optional parameter
475 *
476 * @return TRUE
477 */
478
479BOOLEAN
480MemNSetDqsODTON (
481 IN OUT MEM_NB_BLOCK *NBPtr,
482 IN OUT VOID *OptParam
483 )
484{
485 if ((NBPtr->DCTPtr->Timings.Speed == DDR1333_FREQUENCY) && (NBPtr->ChannelPtr->Dimms == 1)) {
486 MemNSetBitFieldNb (NBPtr, BFDQOdt03, 0x20);
487 MemNSetBitFieldNb (NBPtr, BFDQOdt47, 0x20);
488 }
489 return TRUE;
efdesign9884cbce22011-08-04 12:09:17 -0600490}
491
492/* -----------------------------------------------------------------------------*/
493/**
494 *
495 *
496 * This function sets reduceloop and trim value for DDR-1333 for C0
497 *
498 * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
499 * @param[in,out] OptParam - Optional parameter
500 *
501 * @return TRUE
502 *
503 */
504
505BOOLEAN
506MemNBeforeMemClkFreqValON (
507 IN OUT MEM_NB_BLOCK *NBPtr,
508 IN OUT VOID *OptParam
509 )
510{
511 if ((NBPtr->DCTPtr->Timings.Speed == DDR1333_FREQUENCY) && ((NBPtr->MCTPtr->LogicalCpuid.Revision & AMD_F14_ON_Cx) != 0)) {
512 MemNBrdcstSetNb (NBPtr, BFDllCSRBisaTrimDByte, 0x7000);
513 MemNBrdcstSetNb (NBPtr, BFDllCSRBisaTrimClk, 0x7000);
514 MemNBrdcstSetNb (NBPtr, BFDllCSRBisaTrimCsOdt, 0x7000);
515 MemNBrdcstSetNb (NBPtr, BFDllCSRBisaTrimAByte2, 0x7000);
516 MemNBrdcstSetNb (NBPtr, BFReduceLoop, 0x6000);
517 }
518 return TRUE;
519}