7 * Platform specific settings for HY DDR3 unbuffered dimms
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: (Mem/Ardk)
12 * @e \$Revision: 52286 $ @e \$Date: 2011-05-04 03:48:21 -0600 (Wed, 04 May 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 * ***************************************************************************
47 /* This file contains routine that add platform specific support AM3 */
54 #include "cpuFamRegisters.h"
55 #include "OptionMemory.h"
56 #include "PlatformMemoryConfiguration.h"
62 #define FILECODE PROC_MEM_ARDK_HY_MAUHY3_FILECODE
63 /*----------------------------------------------------------------------------
64 * DEFINITIONS AND MACROS
66 *----------------------------------------------------------------------------
69 /*----------------------------------------------------------------------------
70 * TYPEDEFS AND STRUCTURES
72 *----------------------------------------------------------------------------
75 /*----------------------------------------------------------------------------
76 * PROTOTYPES OF LOCAL FUNCTIONS
78 *----------------------------------------------------------------------------
82 *-----------------------------------------------------------------------------
85 *-----------------------------------------------------------------------------
88 STATIC CONST UINT8 ROMDATA HyUDdr3CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
89 // Even chip select maps to M[B,A]_CKE[0]
90 // Odd chip select maps to M[B,A]_CKE[1]
91 STATIC CONST UINT8 ROMDATA HyUDdr3CKETri[] = {0x55, 0xAA};
92 // Bit 0: M[B,A]0_ODT[0]
93 // Bit 1: M[B,A]1_ODT[0]
94 // Bit 2: M[B,A]0_ODT[1]
95 // Bit 3: M[B,A]1_ODT[1]
96 STATIC CONST UINT8 ROMDATA HyUDdr3ODTTri2D[] = {0x01, 0x04, 0x02, 0x08};
97 // 3 dimms per channel
98 // Dimm 0: BP_MEMODTx[0]
99 // Dimm 1: BP_MEMODTx[3,1]
100 // Dimm 2: BP_MEMODTx[2]
101 STATIC CONST UINT8 ROMDATA HyUDdr3ODTTri3D[] = {0xFF, 0xFF, 0xFF, 0xFF};
102 // Bit 0: M[B,A]0_CS_H/L[0]
103 // Bit 1: M[B,A]0_CS_H/L[1]
104 // Bit 2: M[B,A]0_CS_H/L[2]
105 // Bit 3: M[B,A]0_CS_H/L[3]
106 STATIC CONST UINT8 ROMDATA HyUDdr3CSTri[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
108 /* -----------------------------------------------------------------------------*/
111 * This is function sets the platform specific settings for HY DDR3 unbuffered dimms
114 * @param[in,out] *MemData Pointer to MEM_DATA_STRUCTURE
115 * @param[in] SocketID Socket number
116 * @param[in,out] *CurrentChannel Pointer to CH_DEF_STRUCT
118 * @return AGESA_SUCCESS
119 * @return CurrentChannel->MemClkDisMap Points this pointer to HY MemClkDis table
120 * @return CurrentChannel->ChipSelTriMap Points this pointer to HY CS table
121 * @return CurrentChannel->CKETriMap Points this pointer to HY ODT table
122 * @return CurrentChannel->ODTTriMap Points this pointer to HY CKE table
123 * @return CurrentChannel->DctEccDQSLike Indicates the bytes that should be averaged for ECC
124 * @return CurrentChannel->DctEccDQSScale Indicates the scale that should be used for Averaging ECC byte
125 * @return CurrentChannel->DctAddrTmg Address Command Timing Settings for specified channel
126 * @return CurrentChannel->DctOdcCtl Drive Strength settings for specified channel
127 * @return CurrentChannel->SlowMode Slow Mode
134 IN OUT MEM_DATA_STRUCT *MemData,
136 IN OUT CH_DEF_STRUCT *CurrentChannel
139 STATIC CONST PSCFG_ENTRY PSCfg[] = {
140 {DDR800_FREQUENCY, 0xFF, 0x00390039, 0x20223323},
141 {DDR1066_FREQUENCY, 0xFF, 0x00350037, 0x20223323},
142 {DDR1333_FREQUENCY, 0xFF, 0x00000035, 0x20223323},
143 {DDR1600_FREQUENCY, 0xFF, 0x00000033, 0x20223323}
146 STATIC CONST ADV_PSCFG_ODT_ENTRY PSCfg2DIMMsODT[] = {
147 {SR_DIMM0, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 1},
148 {DR_DIMM0, 0x00000000, 0x00000000, 0x00000104, 0x00000000, 1},
149 {SR_DIMM1, 0x00000000,0x00000000,0x00020000, 0x00000000, 1},
150 {DR_DIMM1, 0x00000000,0x00000000,0x02080000, 0x00000000, 1},
151 {SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1, 0x01010202,0x00000000,0x09030603, 0x00000000, 2},
154 STATIC CONST ADV_R_PSCFG_WL_ODT_ENTRY PSCfg2DIMMsWlODT[] = {
155 {SR_DIMM0, {0x01, 0x00, 0x00, 0x00}, 1},
156 {DR_DIMM0, {0x04, 0x00, 0x00, 0x00}, 1},
157 {SR_DIMM1, {0x00, 0x02, 0x00, 0x00}, 1},
158 {DR_DIMM1, {0x00, 0x08, 0x00, 0x00}, 1},
159 {SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1, {0x03, 0x03, 0x00, 0x00}, 2}
162 STATIC CONST ADV_PSCFG_ODT_ENTRY PSCfg3DIMMsODT[] = {
163 {SR_DIMM2 + DR_DIMM2, 0x00000000, 0x00000000, 0x00000000, 0x00000404, 1},
164 //{SR_DIMM0 + DR_DIMM0, 0x00000000, 0x00000000, 0x00000101, 0x00000000, 1},
165 {SR_DIMM0 + DR_DIMM0 + SR_DIMM2 + DR_DIMM2, 0x00000404, 0x00000101, 0x00000405, 0x00000105, 2},
166 //{SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1 + SR_DIMM2 + DR_DIMM2, 0x05050606, 0x00000303, 0x0D070607, 0x00000307, 3},
169 STATIC CONST ADV_R_PSCFG_WL_ODT_ENTRY PSCfg3DIMMsWlODT[] = {
170 {SR_DIMM2 + DR_DIMM2, {0x00, 0x00, 0x04, 0x00}, 1},
171 //{SR_DIMM0 + DR_DIMM0, {0x01, 0x02, 0x00, 0x00}, 1},
172 {SR_DIMM0 + DR_DIMM0 + SR_DIMM2 + DR_DIMM2, {0x05, 0x00, 0x05, 0x00}, 2},
173 //{SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1 + SR_DIMM2 + DR_DIMM2, {0x07, 0x07, 0x07, 0x00}, 3},
183 UINT16 _DIMMRankType;
187 UINT32 PhyRODTCSHigh;
189 UINT32 PhyWODTCSHigh;
192 UINT8 PSCfgWlODTSize;
195 CONST ADV_PSCFG_ODT_ENTRY *PSCfgODTPtr;
196 CONST ADV_R_PSCFG_WL_ODT_ENTRY *PSCfgWlODTPtr;
197 UINT8 *DimmsPerChPtr;
199 ASSERT (MemData != NULL);
200 ASSERT (CurrentChannel != NULL);
213 if ((CurrentChannel->MCTPtr->LogicalCpuid.Family & AMD_FAMILY_10_HY) == 0) {
214 return AGESA_UNSUPPORTED;
216 if (CurrentChannel->TechType != DDR3_TECHNOLOGY) {
217 return AGESA_UNSUPPORTED;
219 if (CurrentChannel->RegDimmPresent) {
220 return AGESA_UNSUPPORTED;
224 DimmsPerChPtr = FindPSOverrideEntry (MemData->ParameterListPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, SocketID, CurrentChannel->ChannelID, 0, NULL, NULL);
225 if (DimmsPerChPtr != NULL) {
226 MaxDimmPerCH = *DimmsPerChPtr;
231 Loads = CurrentChannel->Loads;
232 Dimms = CurrentChannel->Dimms;
233 Speed = CurrentChannel->DCTPtr->Timings.Speed;
235 DIMMRankType = MemAGetPsRankType (CurrentChannel);
237 if ((Speed == DDR1333_FREQUENCY || Speed == DDR1600_FREQUENCY) && (Dimms == 2)) {
238 SlowMode = TRUE; // 2T
240 SlowMode = FALSE; // 1T
243 for (i = 0; i < GET_SIZE_OF (PSCfg); i++) {
244 if (Speed == PSCfg[i].Speed) {
245 if (Loads <= PSCfg[i].Loads) {
246 AddrTmgCTL = PSCfg[i].AddrTmg;
247 DctOdcCtl = PSCfg[i].Odc;
253 ASSERT (i < GET_SIZE_OF (PSCfg));
255 if (MaxDimmPerCH == 3) {
256 PSCfgODTPtr = PSCfg3DIMMsODT;
257 PSCfgWlODTPtr = PSCfg3DIMMsWlODT;
258 PSCfgODTSize = sizeof (PSCfg3DIMMsODT) / sizeof (ADV_PSCFG_ODT_ENTRY);
259 PSCfgWlODTSize = sizeof (PSCfg3DIMMsWlODT) / sizeof (ADV_R_PSCFG_WL_ODT_ENTRY);
261 PSCfgODTPtr = PSCfg2DIMMsODT;
262 PSCfgWlODTPtr = PSCfg2DIMMsWlODT;
263 PSCfgODTSize = sizeof (PSCfg2DIMMsODT) / sizeof (ADV_PSCFG_ODT_ENTRY);
264 PSCfgWlODTSize = sizeof (PSCfg2DIMMsWlODT) / sizeof (ADV_R_PSCFG_WL_ODT_ENTRY);
268 for (i = 0; i < PSCfgODTSize; i++, PSCfgODTPtr++) {
269 if (Dimms != PSCfgODTPtr->Dimms) {
273 _DIMMRankType = DIMMRankType & PSCfgODTPtr->DIMMRankType;
274 for (j = 0; j < MAX_DIMMS_PER_CHANNEL; j++) {
275 if ((_DIMMRankType & (UINT16) 0x0F << (j << 2)) != 0) {
279 if (DimmTpMatch == PSCfgODTPtr->Dimms) {
280 PhyRODTCSLow = PSCfgODTPtr->PhyRODTCSLow;
281 PhyRODTCSHigh = PSCfgODTPtr->PhyRODTCSHigh;
282 PhyWODTCSLow = PSCfgODTPtr->PhyWODTCSLow;
283 PhyWODTCSHigh = PSCfgODTPtr->PhyWODTCSHigh;
289 for (i = 0; i < PSCfgWlODTSize; i++, PSCfgWlODTPtr++) {
290 if (Dimms != PSCfgWlODTPtr->Dimms) {
294 _DIMMRankType = DIMMRankType & PSCfgWlODTPtr->DIMMRankType;
295 for (j = 0; j < MAX_DIMMS_PER_CHANNEL; j++) {
296 if ((_DIMMRankType & (UINT16) 0x0F << (j << 2)) != 0) {
300 if (DimmTpMatch == PSCfgWlODTPtr->Dimms) {
301 PhyWLODT[0] = PSCfgWlODTPtr->PhyWrLvOdt[0];
302 PhyWLODT[1] = PSCfgWlODTPtr->PhyWrLvOdt[1];
303 PhyWLODT[2] = PSCfgWlODTPtr->PhyWrLvOdt[2];
304 PhyWLODT[3] = PSCfgWlODTPtr->PhyWrLvOdt[3];
310 // Overrides and/or exceptions
314 if (Speed == DDR800_FREQUENCY) {
315 AddrTmgCTL = 0x003B0000;
316 } else if (Speed == DDR1066_FREQUENCY) {
317 AddrTmgCTL = 0x00380000;
318 } else if (Speed == DDR1333_FREQUENCY) {
319 AddrTmgCTL = 0x00360000;
321 AddrTmgCTL = 0x00340000;
327 DctOdcCtl = 0x20113222;
330 CurrentChannel->MemClkDisMap = (UINT8 *) HyUDdr3CLKDis;
331 CurrentChannel->CKETriMap = (UINT8 *) HyUDdr3CKETri;
332 CurrentChannel->ChipSelTriMap = (UINT8 *) HyUDdr3CSTri;
334 switch (MaxDimmPerCH) {
336 CurrentChannel->ODTTriMap = (UINT8 *) HyUDdr3ODTTri3D;
339 CurrentChannel->ODTTriMap = (UINT8 *) HyUDdr3ODTTri2D; // Most conservative
342 CurrentChannel->DctEccDqsLike = 0x0403;
343 CurrentChannel->DctEccDqsScale = 0x70;
344 CurrentChannel->DctAddrTmg = AddrTmgCTL;
345 CurrentChannel->DctOdcCtl = DctOdcCtl;
346 CurrentChannel->PhyRODTCSLow = PhyRODTCSLow;
347 CurrentChannel->PhyRODTCSHigh = PhyRODTCSHigh;
348 CurrentChannel->PhyWODTCSLow = PhyWODTCSLow;
349 CurrentChannel->PhyWODTCSHigh = PhyWODTCSHigh;
350 for (i = 0; i < sizeof (CurrentChannel->PhyWLODT); i++) {
351 CurrentChannel->PhyWLODT[i] = PhyWLODT[i];
353 CurrentChannel->SlowMode = SlowMode;
355 return AGESA_SUCCESS;