2 * This file is part of the coreboot project.
4 * Copyright (C) 2010 Advanced Micro Devices, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 static void SetTargetFreq(struct MCTStatStruc *pMCTstat,
21 struct DCTStatStruc *pDCTstat);
22 static void AgesaHwWlPhase1(sMCTStruct *pMCTData,
23 sDCTStruct *pDCTData, u8 dimm, u8 pass);
24 static void EnableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
25 static void DisableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
26 static void PrepareC_MCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
27 static void PrepareC_DCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct);
28 static void MultiplyDelay(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct);
29 static void Restore_OnDimmMirror(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
30 static void Clear_OnDimmMirror(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
32 static void SetEccWrDQS_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
34 u8 ByteLane, DimmNum, OddByte, Addl_Index, Channel;
35 u8 EccRef1, EccRef2, EccDQSScale;
39 for (Channel = 0; Channel < 2; Channel ++) {
40 for (DimmNum = 0; DimmNum < C_MAX_DIMMS; DimmNum ++) { /* we use DimmNum instead of DimmNumx3 */
41 for (ByteLane = 0; ByteLane < 9; ByteLane ++) {
42 /* Get RxEn initial value from WrDqs */
49 else if (ByteLane < 4)
51 else if (ByteLane < 6)
53 else if (ByteLane < 8)
57 Addl_Index += DimmNum * 3;
59 val = Get_NB32_index_wait(pDCTstat->dev_dct, Channel * 0x100 + 0x98, Addl_Index);
62 /* Save WrDqs to stack for later usage */
63 pDCTstat->CH_D_B_TxDqs[Channel][DimmNum][ByteLane] = val & 0xFF;
64 EccDQSScale = pDCTstat->CH_EccDQSScale[Channel];
65 word = pDCTstat->CH_EccDQSLike[Channel];
66 if ((word & 0xFF) == ByteLane) EccRef1 = val & 0xFF;
67 if (((word >> 8) & 0xFF) == ByteLane) EccRef2 = val & 0xFF;
73 static void EnableAutoRefresh_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
77 val = Get_NB32(pDCTstat->dev_dct, 0x8C);
78 val &= ~(1 << DisAutoRefresh);
79 Set_NB32(pDCTstat->dev_dct, 0x8C, val);
81 val = Get_NB32(pDCTstat->dev_dct, 0x8C + 0x100);
82 val &= ~(1 << DisAutoRefresh);
83 Set_NB32(pDCTstat->dev_dct, 0x8C + 0x100, val);
86 static void DisableAutoRefresh_D(struct MCTStatStruc *pMCTstat,
87 struct DCTStatStruc *pDCTstat)
91 val = Get_NB32(pDCTstat->dev_dct, 0x8C);
92 val |= 1 << DisAutoRefresh;
93 Set_NB32(pDCTstat->dev_dct, 0x8C, val);
95 val = Get_NB32(pDCTstat->dev_dct, 0x8C + 0x100);
96 val |= 1 << DisAutoRefresh;
97 Set_NB32(pDCTstat->dev_dct, 0x8C + 0x100, val);
101 static void PhyWLPass1(struct MCTStatStruc *pMCTstat,
102 struct DCTStatStruc *pDCTstat, u8 dct)
110 DCTPtr = (void *)(pDCTstat->C_DCTPtr[dct]);
111 pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct];
112 pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct];
114 if (pDCTstat->GangedMode & 1)
115 pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
117 if (pDCTstat->DIMMValid) {
118 DIMMValid = pDCTstat->DIMMValid;
119 PrepareC_DCT(pMCTstat, pDCTstat, dct);
120 for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm ++) {
121 if (DIMMValid & (1 << (dimm << 1)))
122 AgesaHwWlPhase1(pDCTstat->C_MCTPtr, DCTPtr, dimm, FirstPass);
127 static void PhyWLPass2(struct MCTStatStruc *pMCTstat,
128 struct DCTStatStruc *pDCTstat, u8 dct)
136 DCTPtr = (void *)&(pDCTstat->C_DCTPtr[dct]); /* todo: */
137 pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct];
138 pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct];
140 if (pDCTstat->GangedMode & 1)
141 pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
143 if (pDCTstat->DIMMValid) {
144 DIMMValid = pDCTstat->DIMMValid;
145 PrepareC_DCT(pMCTstat, pDCTstat, dct);
146 pDCTstat->Speed = pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq;
147 pDCTstat->CASL = pDCTstat->DIMMCASL = pDCTstat->TargetCASL;
148 SPD2ndTiming(pMCTstat, pDCTstat, dct);
149 ProgDramMRSReg_D(pMCTstat, pDCTstat, dct);
150 PlatformSpec_D(pMCTstat, pDCTstat, dct);
151 fenceDynTraining_D(pMCTstat, pDCTstat, dct);
152 Restore_OnDimmMirror(pMCTstat, pDCTstat);
153 StartupDCT_D(pMCTstat, pDCTstat, dct);
154 Clear_OnDimmMirror(pMCTstat, pDCTstat);
155 SetDllSpeedUp_D(pMCTstat, pDCTstat, dct);
156 DisableAutoRefresh_D(pMCTstat, pDCTstat);
157 MultiplyDelay(pMCTstat, pDCTstat, dct);
158 for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm ++) {
159 if (DIMMValid & (1 << (dimm << 1)))
160 AgesaHwWlPhase1(pDCTstat->C_MCTPtr, pDCTstat->C_DCTPtr[dct], dimm, SecondPass);
165 static void WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
166 struct DCTStatStruc *pDCTstat)
168 pDCTstat->C_MCTPtr = &(pDCTstat->s_C_MCTPtr);
169 pDCTstat->C_DCTPtr[0] = &(pDCTstat->s_C_DCTPtr[0]);
170 pDCTstat->C_DCTPtr[1] = &(pDCTstat->s_C_DCTPtr[1]);
172 /* Disable auto refresh by configuring F2x[1, 0]8C[DisAutoRefresh] = 1 */
173 DisableAutoRefresh_D(pMCTstat, pDCTstat);
175 /* Disable ZQ calibration short command by F2x[1,0]94[ZqcsInterval]=00b */
176 DisableZQcalibration(pMCTstat, pDCTstat);
177 PrepareC_MCT(pMCTstat, pDCTstat);
179 if (pDCTstat->GangedMode & (1 << 0)) {
180 pDCTstat->DIMMValidDCT[1] = pDCTstat->DIMMValidDCT[0];
183 PhyWLPass1(pMCTstat, pDCTstat, 0);
184 PhyWLPass1(pMCTstat, pDCTstat, 1);
186 if (pDCTstat->TargetFreq > 4) {
187 /* 8.Prepare the memory subsystem for the target MEMCLK frequency.
188 * Note: BIOS must program both DCTs to the same frequency.
190 SetTargetFreq(pMCTstat, pDCTstat);
191 PhyWLPass2(pMCTstat, pDCTstat, 0);
192 PhyWLPass2(pMCTstat, pDCTstat, 1);
195 SetEccWrDQS_D(pMCTstat, pDCTstat);
196 EnableAutoRefresh_D(pMCTstat, pDCTstat);
197 EnableZQcalibration(pMCTstat, pDCTstat);
200 void mct_WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
201 struct DCTStatStruc *pDCTstatA)
205 for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
206 struct DCTStatStruc *pDCTstat;
207 pDCTstat = pDCTstatA + Node;
209 if (pDCTstat->NodePresent) {
210 mctSMBhub_Init(Node);
211 Clear_OnDimmMirror(pMCTstat, pDCTstat);
212 WriteLevelization_HW(pMCTstat, pDCTstat);
213 Restore_OnDimmMirror(pMCTstat, pDCTstat);