blob: fe0653e04e55d05e7e25f0af52aef9f9a3796c72 [file] [log] [blame]
Zheng Baoeb75f652010-04-23 17:32:48 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2010 Advanced Micro Devices, Inc.
Timothy Pearsonb8a355d2015-09-05 17:55:58 -05005 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Zheng Baoeb75f652010-04-23 17:32:48 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Zheng Baoeb75f652010-04-23 17:32:48 +000015 */
16
17static void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat,
18 struct DCTStatStruc *pDCTstat);
19
20
21static void AgesaDelay(u32 msec)
22{
23 mct_Wait(msec*10);
24}
25
26void PrepareC_MCT(struct MCTStatStruc *pMCTstat,
27 struct DCTStatStruc *pDCTstat)
28{
29 pDCTstat->C_MCTPtr->AgesaDelay = AgesaDelay;
30 pDCTstat->C_MCTPtr->PlatMaxTotalDimms = mctGet_NVbits(NV_MAX_DIMMS);
31 pDCTstat->C_MCTPtr->PlatMaxDimmsDct = pDCTstat->C_MCTPtr->PlatMaxTotalDimms >> 1;
32}
33
34void PrepareC_DCT(struct MCTStatStruc *pMCTstat,
35 struct DCTStatStruc *pDCTstat, u8 dct)
36{
37 u8 dimm;
38 u16 DimmValid;
39 u16 Dimmx8Present;
40
41 dct &= 1;
42
43 pDCTstat->C_DCTPtr[dct]->DctTrain = dct;
44
45 if (dct == 1) {
46 Dimmx8Present = pDCTstat->Dimmx8Present >> 1;
47 } else
48 Dimmx8Present = pDCTstat->Dimmx8Present;
49 Dimmx8Present &= 0x55;
50
51 pDCTstat->C_DCTPtr[dct]->MaxDimmsInstalled = pDCTstat->MAdimms[dct];
52 DimmValid = pDCTstat->DIMMValidDCT[dct];
53
54 pDCTstat->C_DCTPtr[dct]->NodeId = pDCTstat->Node_ID;
55 pDCTstat->C_DCTPtr[dct]->LogicalCPUID = pDCTstat->LogicalCPUID;
56
57 for (dimm = 0; dimm < MAX_DIMMS; dimm++) {
Timothy Pearsonb8a355d2015-09-05 17:55:58 -050058 if (DimmValid & (1 << (dimm << 1)))
Zheng Baoeb75f652010-04-23 17:32:48 +000059 pDCTstat->C_DCTPtr[dct]->DimmPresent[dimm] = 1;
Timothy Pearsonb8a355d2015-09-05 17:55:58 -050060 if (Dimmx8Present & (1 << (dimm << 1)))
Zheng Baoeb75f652010-04-23 17:32:48 +000061 pDCTstat->C_DCTPtr[dct]->DimmX8Present[dimm] = 1;
62 }
63
64 if (pDCTstat->GangedMode & (1 << 0))
65 pDCTstat->C_DCTPtr[dct]->CurrDct = 0;
66 else
67 pDCTstat->C_DCTPtr[dct]->CurrDct = dct;
68
69 pDCTstat->C_DCTPtr[dct]->DctCSPresent = pDCTstat->CSPresent_DCT[dct];
70 if (!(pDCTstat->GangedMode & (1 << 0)) && (dct == 1))
71 pDCTstat->C_DCTPtr[dct]->DctCSPresent = pDCTstat->CSPresent_DCT[0];
72
73 if (pDCTstat->Status & (1 << SB_Registered)) {
74 pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_REGISTERED] = 1;
75 pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_OnDimmMirror] = 0;
76 } else {
77 if (pDCTstat->MirrPresU_NumRegR > 0)
78 pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_OnDimmMirror] = 1;
79 pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_REGISTERED] = 0;
80 }
81
Timothy Pearson730a0432015-10-16 13:51:51 -050082 if (pDCTstat->Status & (1 << SB_LoadReduced)) {
83 pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_LOAD_REDUCED] = 1;
84 } else {
85 pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_LOAD_REDUCED] = 0;
86 }
87
Zheng Baoeb75f652010-04-23 17:32:48 +000088 pDCTstat->C_DCTPtr[dct]->RegMan1Present = pDCTstat->RegMan1Present;
89
90 for (dimm = 0; dimm < MAX_TOTAL_DIMMS; dimm++) {
91 u8 DimmRanks;
Kerry She99cfa1e2010-08-30 07:31:31 +000092 if (DimmValid & (1 << (dimm << 1))) {
Zheng Baoeb75f652010-04-23 17:32:48 +000093 DimmRanks = 1;
Timothy Pearsonb8a355d2015-09-05 17:55:58 -050094 if (pDCTstat->DimmDRPresent & (1 << ((dimm << 1) + dct)))
Zheng Baoeb75f652010-04-23 17:32:48 +000095 DimmRanks = 2;
Timothy Pearsonb8a355d2015-09-05 17:55:58 -050096 else if (pDCTstat->DimmQRPresent & (1 << ((dimm << 1) + dct)))
Zheng Baoeb75f652010-04-23 17:32:48 +000097 DimmRanks = 4;
98 } else
99 DimmRanks = 0;
100 pDCTstat->C_DCTPtr[dct]->DimmRanks[dimm] = DimmRanks;
101 }
102}
103
104void EnableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
105{
106 u32 val;
107
Timothy Pearson730a0432015-10-16 13:51:51 -0500108 val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
Zheng Baoeb75f652010-04-23 17:32:48 +0000109 val |= 1 << 11;
Timothy Pearson730a0432015-10-16 13:51:51 -0500110 Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val);
Zheng Baoeb75f652010-04-23 17:32:48 +0000111
Timothy Pearson730a0432015-10-16 13:51:51 -0500112 val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
Zheng Baoeb75f652010-04-23 17:32:48 +0000113 val |= 1 << 11;
Timothy Pearson730a0432015-10-16 13:51:51 -0500114 Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val);
Zheng Baoeb75f652010-04-23 17:32:48 +0000115}
116
117void DisableZQcalibration(struct MCTStatStruc *pMCTstat,
118 struct DCTStatStruc *pDCTstat)
119{
120 u32 val;
121
Timothy Pearson730a0432015-10-16 13:51:51 -0500122 val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
Zheng Baoeb75f652010-04-23 17:32:48 +0000123 val &= ~(1 << 11);
124 val &= ~(1 << 10);
Timothy Pearson730a0432015-10-16 13:51:51 -0500125 Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val);
Zheng Baoeb75f652010-04-23 17:32:48 +0000126
Timothy Pearson730a0432015-10-16 13:51:51 -0500127 val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
Zheng Baoeb75f652010-04-23 17:32:48 +0000128 val &= ~(1 << 11);
129 val &= ~(1 << 10);
Timothy Pearson730a0432015-10-16 13:51:51 -0500130 Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val);
Zheng Baoeb75f652010-04-23 17:32:48 +0000131}
132
133static void EnterSelfRefresh(struct MCTStatStruc *pMCTstat,
134 struct DCTStatStruc *pDCTstat)
135{
136 u8 DCT0Present, DCT1Present;
137 u32 val;
138
139 DCT0Present = pDCTstat->DIMMValidDCT[0];
140 if (pDCTstat->GangedMode)
141 DCT1Present = 0;
142 else
143 DCT1Present = pDCTstat->DIMMValidDCT[1];
144
145 /* Program F2x[1, 0]90[EnterSelfRefresh]=1. */
146 if (DCT0Present) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500147 val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
Zheng Baoeb75f652010-04-23 17:32:48 +0000148 val |= 1 << EnterSelfRef;
Timothy Pearson730a0432015-10-16 13:51:51 -0500149 Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val);
Zheng Baoeb75f652010-04-23 17:32:48 +0000150 }
151 if (DCT1Present) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500152 val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
Zheng Baoeb75f652010-04-23 17:32:48 +0000153 val |= 1 << EnterSelfRef;
Timothy Pearson730a0432015-10-16 13:51:51 -0500154 Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val);
Zheng Baoeb75f652010-04-23 17:32:48 +0000155 }
156 /* Wait until the hardware resets F2x[1, 0]90[EnterSelfRefresh]=0. */
157 if (DCT0Present)
158 do {
Timothy Pearson730a0432015-10-16 13:51:51 -0500159 val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
Zheng Baoeb75f652010-04-23 17:32:48 +0000160 } while (val & (1 <<EnterSelfRef));
161 if (DCT1Present)
162 do {
Timothy Pearson730a0432015-10-16 13:51:51 -0500163 val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
Zheng Baoeb75f652010-04-23 17:32:48 +0000164 } while (val & (1 <<EnterSelfRef));
165}
166
167/*
168 * Change memclk for write levelization pass 2
169 */
170static void ChangeMemClk(struct MCTStatStruc *pMCTstat,
171 struct DCTStatStruc *pDCTstat)
172{
Timothy Pearson730a0432015-10-16 13:51:51 -0500173 uint8_t DCT0Present;
174 uint8_t DCT1Present;
175 uint32_t dword;
176 uint32_t mask;
177 uint32_t offset;
Zheng Baoeb75f652010-04-23 17:32:48 +0000178
179 DCT0Present = pDCTstat->DIMMValidDCT[0];
180 if (pDCTstat->GangedMode)
181 DCT1Present = 0;
182 else
183 DCT1Present = pDCTstat->DIMMValidDCT[1];
184
Timothy Pearson730a0432015-10-16 13:51:51 -0500185 if (is_fam15h()) {
186 /* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0x190 */
187 if (DCT0Present) {
188 dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006);
189 dword &= ~(0x0000ffff);
190 dword |= 0x00000190;
191 Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006, dword);
192 }
193 if (DCT1Present) {
194 dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006);
195 dword &= ~(0x0000ffff);
196 dword |= 0x00000190;
197 Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006, dword);
198 }
199 } else {
200 /* Program F2x[1, 0]9C[DisAutoComp]=1. */
201 if (DCT0Present) {
202 dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8);
203 dword |= 1 << DisAutoComp;
204 Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8, dword);
205 mct_Wait(100); /* Wait for 5us */
206 }
207 if (DCT1Present) {
208 dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8);
209 dword |= 1 << DisAutoComp;
210 Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8, dword);
211 mct_Wait(100); /* Wait for 5us */
212 }
Zheng Baoeb75f652010-04-23 17:32:48 +0000213 }
214
215 /* Program F2x[1, 0]94[MemClkFreqVal] = 0. */
216 if (DCT0Present) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500217 dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
218 dword &= ~(1 << MemClkFreqVal);
219 Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword);
Zheng Baoeb75f652010-04-23 17:32:48 +0000220 }
221 if (DCT1Present) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500222 dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
223 dword &= ~(1 << MemClkFreqVal);
224 Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword);
Zheng Baoeb75f652010-04-23 17:32:48 +0000225 }
226
227 /* Program F2x[1, 0]94[MemClkFreq] to specify the target MEMCLK frequency. */
Timothy Pearson730a0432015-10-16 13:51:51 -0500228 if (is_fam15h()) {
229 offset = 0x0;
230 mask = 0x1f;
231 } else {
232 offset = 0x1;
233 mask = 0x7;
234 }
Zheng Baoeb75f652010-04-23 17:32:48 +0000235 if (DCT0Present) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500236 dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
237 dword &= ~mask;
238 dword |= (pDCTstat->TargetFreq - offset) & mask;
239 Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword);
Zheng Baoeb75f652010-04-23 17:32:48 +0000240 }
241 if (DCT1Present) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500242 dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
243 dword &= ~mask;
244 dword |= (pDCTstat->TargetFreq - offset) & mask;
245 Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword);
246 }
247
248 if (is_fam15h()) {
249 if (DCT0Present) {
250 mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 0);
251 set_2t_configuration(pMCTstat, pDCTstat, 0);
252 mct_BeforePlatformSpec(pMCTstat, pDCTstat, 0);
253 mct_PlatformSpec(pMCTstat, pDCTstat, 0);
254 }
255 if (DCT1Present) {
256 mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1);
257 set_2t_configuration(pMCTstat, pDCTstat, 1);
258 mct_BeforePlatformSpec(pMCTstat, pDCTstat, 1);
259 mct_PlatformSpec(pMCTstat, pDCTstat, 1);
260 }
Zheng Baoeb75f652010-04-23 17:32:48 +0000261 }
262
263 /* Program F2x[1, 0]94[MemClkFreqVal] = 1. */
264 if (DCT0Present) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500265 dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
266 dword |= 1 << MemClkFreqVal;
267 Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword);
Zheng Baoeb75f652010-04-23 17:32:48 +0000268 }
269 if (DCT1Present) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500270 dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
271 dword |= 1 << MemClkFreqVal;
272 Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword);
Zheng Baoeb75f652010-04-23 17:32:48 +0000273 }
274
275 /* Wait until F2x[1, 0]94[FreqChgInProg]=0. */
276 if (DCT0Present)
277 do {
Timothy Pearson730a0432015-10-16 13:51:51 -0500278 dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
279 } while (dword & (1 << FreqChgInProg));
Zheng Baoeb75f652010-04-23 17:32:48 +0000280 if (DCT1Present)
281 do {
Timothy Pearson730a0432015-10-16 13:51:51 -0500282 dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
283 } while (dword & (1 << FreqChgInProg));
Zheng Baoeb75f652010-04-23 17:32:48 +0000284
Timothy Pearson730a0432015-10-16 13:51:51 -0500285 if (is_fam15h()) {
286 /* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0xf */
287 if (DCT0Present) {
288 dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006);
289 dword &= ~(0x0000ffff);
290 dword |= 0x0000000f;
291 Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006, dword);
292 }
293 if (DCT1Present) {
294 dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006);
295 dword &= ~(0x0000ffff);
296 dword |= 0x0000000f;
297 Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006, dword);
298 }
299 } else {
300 /* Program F2x[1, 0]9C[DisAutoComp] = 0. */
301 if (DCT0Present) {
302 dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8);
303 dword &= ~(1 << DisAutoComp);
304 Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8, dword);
305 mct_Wait(15000); /* Wait for 750us */
306 }
307 if (DCT1Present) {
308 dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8);
309 dword &= ~(1 << DisAutoComp);
310 Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8, dword);
311 mct_Wait(15000); /* Wait for 750us */
312 }
Zheng Baoeb75f652010-04-23 17:32:48 +0000313 }
314}
315
Zheng Baoeb75f652010-04-23 17:32:48 +0000316/*
317 * the DRAM controller to bring the DRAMs out of self refresh mode.
318 */
319static void ExitSelfRefresh(struct MCTStatStruc *pMCTstat,
320 struct DCTStatStruc *pDCTstat)
321{
322 u8 DCT0Present, DCT1Present;
323 u32 val;
324
325 DCT0Present = pDCTstat->DIMMValidDCT[0];
326 if (pDCTstat->GangedMode)
327 DCT1Present = 0;
328 else
329 DCT1Present = pDCTstat->DIMMValidDCT[1];
330
331 /* Program F2x[1, 0]90[ExitSelfRef]=1 for both DCTs. */
332 if (DCT0Present) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500333 val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
Zheng Baoeb75f652010-04-23 17:32:48 +0000334 val |= 1 << ExitSelfRef;
Timothy Pearson730a0432015-10-16 13:51:51 -0500335 Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val);
Zheng Baoeb75f652010-04-23 17:32:48 +0000336 }
337 if (DCT1Present) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500338 val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
Zheng Baoeb75f652010-04-23 17:32:48 +0000339 val |= 1 << ExitSelfRef;
Timothy Pearson730a0432015-10-16 13:51:51 -0500340 Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val);
Zheng Baoeb75f652010-04-23 17:32:48 +0000341 }
342 /* Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0. */
343 if (DCT0Present)
344 do {
Timothy Pearson730a0432015-10-16 13:51:51 -0500345 val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
Zheng Baoeb75f652010-04-23 17:32:48 +0000346 } while (val & (1 << ExitSelfRef));
347 if (DCT1Present)
348 do {
Timothy Pearson730a0432015-10-16 13:51:51 -0500349 val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
Zheng Baoeb75f652010-04-23 17:32:48 +0000350 } while (val & (1 << ExitSelfRef));
351}
352
353void SetTargetFreq(struct MCTStatStruc *pMCTstat,
354 struct DCTStatStruc *pDCTstat)
355{
Timothy Pearson730a0432015-10-16 13:51:51 -0500356 uint32_t dword;
357 uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
358
359 if (is_fam15h()) {
360 /* Program F2x[1, 0]90[DisDllShutDownSR]=1. */
361 if (pDCTstat->DIMMValidDCT[0]) {
362 dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
363 dword |= (0x1 << 27);
364 Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, dword);
365 }
366 if (pDCTstat->DIMMValidDCT[1]) {
367 dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
368 dword |= (0x1 << 27);
369 Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, dword);
370 }
371 }
372
Zheng Baoeb75f652010-04-23 17:32:48 +0000373 /* Program F2x[1,0]90[EnterSelfRefresh]=1.
374 * Wait until the hardware resets F2x[1,0]90[EnterSelfRefresh]=0.
375 */
376 EnterSelfRefresh(pMCTstat, pDCTstat);
377
378 /*
379 * Program F2x[1,0]9C_x08[DisAutoComp]=1
380 * Program F2x[1,0]94[MemClkFreqVal] = 0.
381 * Program F2x[1,0]94[MemClkFreq] to specify the target MEMCLK frequency.
382 * Program F2x[1,0]94[MemClkFreqVal] = 1.
383 * Wait until F2x[1,0]94[FreqChgInProg]=0.
384 * Program F2x[1,0]9C_x08[DisAutoComp]=0
385 */
386 ChangeMemClk(pMCTstat, pDCTstat);
387
Timothy Pearson730a0432015-10-16 13:51:51 -0500388 if (is_fam15h()) {
389 uint8_t dct;
390 for (dct = 0; dct < 2; dct++) {
391 if (pDCTstat->DIMMValidDCT[dct]) {
392 phyAssistedMemFnceTraining(pMCTstat, pDCTstat);
393 InitPhyCompensation(pMCTstat, pDCTstat, dct);
394 }
395 }
396 }
397
Zheng Baoeb75f652010-04-23 17:32:48 +0000398 /* Program F2x[1,0]90[ExitSelfRef]=1 for both DCTs.
399 * Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0.
400 */
401 ExitSelfRefresh(pMCTstat, pDCTstat);
402
Timothy Pearson730a0432015-10-16 13:51:51 -0500403 if (is_fam15h()) {
404 if ((package_type == PT_C3) || (package_type == PT_GR)) {
405 /* Socket C32 or G34 */
406 /* Program F2x[1, 0]90[DisDllShutDownSR]=0. */
407 if (pDCTstat->DIMMValidDCT[0]) {
408 dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
409 dword &= ~(0x1 << 27);
410 Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, dword);
411 }
412 if (pDCTstat->DIMMValidDCT[1]) {
413 dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
414 dword &= ~(0x1 << 27);
415 Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, dword);
416 }
417 }
418 }
419
Zheng Baoeb75f652010-04-23 17:32:48 +0000420 /* wait for 500 MCLKs after ExitSelfRef, 500*2.5ns=1250ns */
421 mct_Wait(250);
422
423 if (pDCTstat->Status & (1 << SB_Registered)) {
Zheng Baoa7296e72011-01-17 02:20:33 +0000424 u8 DCT0Present, DCT1Present;
425
426 DCT0Present = pDCTstat->DIMMValidDCT[0];
427 if (pDCTstat->GangedMode)
428 DCT1Present = 0;
429 else
430 DCT1Present = pDCTstat->DIMMValidDCT[1];
431
432 if (!DCT1Present)
433 pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
Timothy Pearsonb8a355d2015-09-05 17:55:58 -0500434 else if (pDCTstat->GangedMode)
Zheng Baoa7296e72011-01-17 02:20:33 +0000435 pDCTstat->CSPresent = 0;
Timothy Pearsonb8a355d2015-09-05 17:55:58 -0500436 else
Zheng Baoa7296e72011-01-17 02:20:33 +0000437 pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[1];
438
Zheng Baoeb75f652010-04-23 17:32:48 +0000439 FreqChgCtrlWrd(pMCTstat, pDCTstat);
440 }
441}
442
443static void Modify_OnDimmMirror(struct DCTStatStruc *pDCTstat, u8 dct, u8 set)
444{
445 u32 val;
Timothy Pearson730a0432015-10-16 13:51:51 -0500446 u32 reg = 0x44;
447 while (reg < 0x60) {
448 val = Get_NB32_DCT(pDCTstat->dev_dct, dct, reg);
Zheng Baoeb75f652010-04-23 17:32:48 +0000449 if (val & (1 << CSEnable))
450 set ? (val |= 1 << onDimmMirror) : (val &= ~(1<<onDimmMirror));
Timothy Pearson730a0432015-10-16 13:51:51 -0500451 Set_NB32_DCT(pDCTstat->dev_dct, dct, reg, val);
452 reg += 8;
Zheng Baoeb75f652010-04-23 17:32:48 +0000453 }
454}
455
456void Restore_OnDimmMirror(struct MCTStatStruc *pMCTstat,
457 struct DCTStatStruc *pDCTstat)
458{
459 if (pDCTstat->LogicalCPUID & (AMD_DR_Bx /* | AMD_RB_C0 */)) { /* We dont support RB-C0 now */
460 if (pDCTstat->MirrPresU_NumRegR & 0x55)
461 Modify_OnDimmMirror(pDCTstat, 0, 1); /* dct=0, set */
462 if (pDCTstat->MirrPresU_NumRegR & 0xAA)
463 Modify_OnDimmMirror(pDCTstat, 1, 1); /* dct=1, set */
464 }
465}
466void Clear_OnDimmMirror(struct MCTStatStruc *pMCTstat,
467 struct DCTStatStruc *pDCTstat)
468{
469 if (pDCTstat->LogicalCPUID & (AMD_DR_Bx /* | AMD_RB_C0 */)) { /* We dont support RB-C0 now */
470 if (pDCTstat->MirrPresU_NumRegR & 0x55)
471 Modify_OnDimmMirror(pDCTstat, 0, 0); /* dct=0, clear */
472 if (pDCTstat->MirrPresU_NumRegR & 0xAA)
473 Modify_OnDimmMirror(pDCTstat, 1, 0); /* dct=1, clear */
474 }
475}