blob: 48ab8007ab4790847f80859087027369da329a7c [file] [log] [blame]
Marc Jones8ae8c882007-12-19 01:32:08 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Marc Jones8ae8c882007-12-19 01:32:08 +00003 *
Timothy Pearson3c206782015-02-14 03:32:21 -06004 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Marc Jones (marc.jonese3aeb932008-04-11 03:20:28 +00005 * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
Marc Jones8ae8c882007-12-19 01:32:08 +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.
Marc Jones8ae8c882007-12-19 01:32:08 +000015 */
16
17/* Call-backs */
Marco Schmidta7741922009-06-06 11:33:58 +000018#include <delay.h>
Stefan Reinauer6f57b512010-07-08 16:41:05 +000019
Timothy Pearson068ca9c2015-02-14 16:40:20 -060020#define NVRAM_DDR2_800 0
21#define NVRAM_DDR2_667 1
22#define NVRAM_DDR2_533 2
23#define NVRAM_DDR2_400 3
24
25#define NVRAM_DDR3_1600 0
26#define NVRAM_DDR3_1333 1
27#define NVRAM_DDR3_1066 2
28#define NVRAM_DDR3_800 3
29
Timothy Pearsonbbd26472015-06-04 13:34:23 -050030/* The recommended maximum GFX Upper Memory Area
31 * size is 256M, however, to be on the safe side
32 * move TOM down by 512M.
33 */
34#define MAXIMUM_GFXUMA_SIZE 0x20000000
35
36/* Do not allow less than 16M of DRAM in 32-bit space.
37 * This number is not hardware constrained and can be
38 * changed as needed.
39 */
40#define MINIMUM_DRAM_BELOW_4G 0x1000000
41
Timothy Pearson068ca9c2015-02-14 16:40:20 -060042static const uint16_t ddr2_limits[4] = {400, 333, 266, 200};
Timothy Pearson730a0432015-10-16 13:51:51 -050043static const uint16_t ddr3_limits[16] = {933, 800, 666, 533, 400, 333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Timothy Pearson068ca9c2015-02-14 16:40:20 -060044
Myles Watson075fbe82010-04-15 05:19:29 +000045static u16 mctGet_NVbits(u8 index)
Marc Jones8ae8c882007-12-19 01:32:08 +000046{
47 u16 val = 0;
Timothy Pearson068ca9c2015-02-14 16:40:20 -060048 int nvram;
Marc Jones8ae8c882007-12-19 01:32:08 +000049
50 switch (index) {
51 case NV_PACK_TYPE:
Zheng Baodb8b4112009-07-01 07:01:32 +000052#if CONFIG_CPU_SOCKET_TYPE == 0x10 /* Socket F */
Marc Jones8ae8c882007-12-19 01:32:08 +000053 val = 0;
Zheng Baoeb75f652010-04-23 17:32:48 +000054#elif CONFIG_CPU_SOCKET_TYPE == 0x11 /* AM3 */
Marc Jones8ae8c882007-12-19 01:32:08 +000055 val = 1;
Zheng Baoeb75f652010-04-23 17:32:48 +000056#elif CONFIG_CPU_SOCKET_TYPE == 0x13 /* ASB2 */
57 val = 4;
Timothy Pearsonb8a355d2015-09-05 17:55:58 -050058#elif CONFIG_CPU_SOCKET_TYPE == 0x14 /* C32 */
59 val = 5;
60#elif CONFIG_CPU_SOCKET_TYPE == 0x15 /* G34 */
61 val = 3;
Marc Jones8ae8c882007-12-19 01:32:08 +000062//#elif SYSTEM_TYPE == MOBILE
63// val = 2;
64#endif
65 break;
66 case NV_MAX_NODES:
67 val = MAX_NODES_SUPPORTED;
68 break;
69 case NV_MAX_DIMMS:
Kerry She99cfa1e2010-08-30 07:31:31 +000070 val = MAX_DIMMS_SUPPORTED;
71 //val = 8;
Marc Jones8ae8c882007-12-19 01:32:08 +000072 break;
73 case NV_MAX_MEMCLK:
74 /* Maximum platform supported memclk */
Timothy Pearson068ca9c2015-02-14 16:40:20 -060075 val = MEM_MAX_LOAD_FREQ;
76
77 if (get_option(&nvram, "max_mem_clock") == CB_SUCCESS) {
78 int limit = val;
79 if (IS_ENABLED(CONFIG_DIMM_DDR3))
Timothy Pearson730a0432015-10-16 13:51:51 -050080 limit = ddr3_limits[nvram & 0xf];
Timothy Pearson068ca9c2015-02-14 16:40:20 -060081 else if (IS_ENABLED(CONFIG_DIMM_DDR2))
Timothy Pearson730a0432015-10-16 13:51:51 -050082 limit = ddr2_limits[nvram & 0x3];
Timothy Pearson068ca9c2015-02-14 16:40:20 -060083 val = min(limit, val);
84 }
Marc Jones8ae8c882007-12-19 01:32:08 +000085 break;
Timothy Pearson730a0432015-10-16 13:51:51 -050086 case NV_MIN_MEMCLK:
87 /* Minimum platform supported memclk */
88 if (is_fam15h())
89 val = MEM_MIN_PLATFORM_FREQ_FAM15;
90 else
91 val = MEM_MIN_PLATFORM_FREQ_FAM10;
92 break;
Marc Jones8ae8c882007-12-19 01:32:08 +000093 case NV_ECC_CAP:
94#if SYSTEM_TYPE == SERVER
95 val = 1; /* memory bus ECC capable */
96#else
97 val = 0; /* memory bus ECC not capable */
98#endif
99 break;
100 case NV_4RANKType:
101 /* Quad Rank DIMM slot type */
102 val = 0; /* normal */
103 //val = 1; /* R4 (registered DIMMs in AMD server configuration) */
104 //val = 2; /* S4 (Unbuffered SO-DIMMS) */
105 break;
106 case NV_BYPMAX:
Patrick Georgie1667822012-05-05 15:29:32 +0200107#if !CONFIG_GFXUMA
Marc Jones8ae8c882007-12-19 01:32:08 +0000108 val = 4;
Patrick Georgif8f00622012-05-05 15:50:17 +0200109#elif CONFIG_GFXUMA
Marc Jones8ae8c882007-12-19 01:32:08 +0000110 val = 7;
111#endif
112 break;
113 case NV_RDWRQBYP:
Patrick Georgie1667822012-05-05 15:29:32 +0200114#if !CONFIG_GFXUMA
Marc Jones8ae8c882007-12-19 01:32:08 +0000115 val = 2;
Patrick Georgif8f00622012-05-05 15:50:17 +0200116#elif CONFIG_GFXUMA
Marc Jones8ae8c882007-12-19 01:32:08 +0000117 val = 3;
118#endif
119 break;
120 case NV_MCTUSRTMGMODE:
121 val = 0; /* Automatic (recommended) */
122 //val = 1; /* Limited */
123 //val = 2; /* Manual */
124 break;
125 case NV_MemCkVal:
126 //val = 0; /* 200MHz */
127 //val = 1; /* 266MHz */
128 val = 2; /* 333MHz */
129 break;
130 case NV_BankIntlv:
131 /* Bank (chip select) interleaving */
132 //val = 0; /* disabled */
133 val = 1; /* enabled (recommended) */
Timothy Pearson068ca9c2015-02-14 16:40:20 -0600134
135 if (get_option(&nvram, "interleave_chip_selects") == CB_SUCCESS)
136 val = !!nvram;
Marc Jones8ae8c882007-12-19 01:32:08 +0000137 break;
138 case NV_MemHole:
139 //val = 0; /* Disabled */
140 val = 1; /* Enabled (recommended) */
141 break;
142 case NV_AllMemClks:
143 val = 0; /* Normal (only to slots that have enabled DIMMs) */
144 //val = 1; /* Enable all memclocks */
145 break;
146 case NV_SPDCHK_RESTRT:
147 val = 0; /* Exit current node initialization if any DIMM has SPD checksum error */
148 //val = 1; /* Ignore faulty SPD checksum (DIMM will still be disabled), continue current node intialization */
149 break;
150 case NV_DQSTrainCTL:
151 //val = 0; /*Skip dqs training */
152 val = 1; /* Perform dqs training */
153 break;
154 case NV_NodeIntlv:
155 val = 0; /* Disabled (recommended) */
156 //val = 1; /* Enable */
Timothy Pearson068ca9c2015-02-14 16:40:20 -0600157
158 if (get_option(&nvram, "interleave_nodes") == CB_SUCCESS)
159 val = !!nvram;
Marc Jones8ae8c882007-12-19 01:32:08 +0000160 break;
161 case NV_BurstLen32:
Patrick Georgie1667822012-05-05 15:29:32 +0200162#if !CONFIG_GFXUMA
Marc Jones8ae8c882007-12-19 01:32:08 +0000163 val = 0; /* 64 byte mode */
Patrick Georgif8f00622012-05-05 15:50:17 +0200164#elif CONFIG_GFXUMA
Marc Jones8ae8c882007-12-19 01:32:08 +0000165 val = 1; /* 32 byte mode */
166#endif
167 break;
168 case NV_CKE_PDEN:
169 //val = 0; /* Disable */
170 val = 1; /* Enable */
171 break;
172 case NV_CKE_CTL:
173 val = 0; /* per channel control */
174 //val = 1; /* per chip select control */
175 break;
176 case NV_CLKHZAltVidC3:
177 val = 0; /* disable */
178 //val = 1; /* enable */
179 break;
180 case NV_BottomIO:
Marc Jones8ae8c882007-12-19 01:32:08 +0000181 case NV_BottomUMA:
Timothy Pearsonbbd26472015-06-04 13:34:23 -0500182 /* address bits [31:24] */
Patrick Georgie1667822012-05-05 15:29:32 +0200183#if !CONFIG_GFXUMA
Timothy Pearsonbbd26472015-06-04 13:34:23 -0500184 val = (CONFIG_MMCONF_BASE_ADDRESS >> 24);
Patrick Georgif8f00622012-05-05 15:50:17 +0200185#elif CONFIG_GFXUMA
Timothy Pearsonbbd26472015-06-04 13:34:23 -0500186 #if (CONFIG_MMCONF_BASE_ADDRESS < (MAXIMUM_GFXUMA_SIZE + MINIMUM_DRAM_BELOW_4G))
187 #error "MMCONF_BASE_ADDRESS is too small"
188 #endif
189 val = ((CONFIG_MMCONF_BASE_ADDRESS - MAXIMUM_GFXUMA_SIZE) >> 24);
Marc Jones8ae8c882007-12-19 01:32:08 +0000190#endif
191 break;
192 case NV_ECC:
193#if (SYSTEM_TYPE == SERVER)
194 val = 1; /* Enable */
195#else
196 val = 0; /* Disable */
197#endif
Timothy Pearson068ca9c2015-02-14 16:40:20 -0600198
199 if (get_option(&nvram, "ECC_memory") == CB_SUCCESS)
200 val = !!nvram;
Marc Jones8ae8c882007-12-19 01:32:08 +0000201 break;
202 case NV_NBECC:
203#if (SYSTEM_TYPE == SERVER)
204 val = 1; /* Enable */
205#else
206 val = 0; /* Disable */
207#endif
208 break;
209 case NV_ChipKill:
210#if (SYSTEM_TYPE == SERVER)
211 val = 1; /* Enable */
212#else
213 val = 0; /* Disable */
214#endif
215 break;
216 case NV_ECCRedir:
Timothy Pearson5ec11532015-01-24 14:13:30 -0600217 /*
218 * 0: Disable
219 * 1: Enable
220 */
Timothy Pearson2b1bcc12015-02-14 03:40:35 -0600221 val = 0;
Timothy Pearson068ca9c2015-02-14 16:40:20 -0600222
223 if (get_option(&nvram, "ECC_redirection") == CB_SUCCESS)
224 val = !!nvram;
Marc Jones8ae8c882007-12-19 01:32:08 +0000225 break;
226 case NV_DramBKScrub:
Timothy Pearson6f2caa02015-01-23 20:24:30 -0600227 /*
228 * 0x00: Disabled
229 * 0x01: 40ns
230 * 0x02: 80ns
231 * 0x03: 160ns
232 * 0x04: 320ns
233 * 0x05: 640ns
234 * 0x06: 1.28us
235 * 0x07: 2.56us
236 * 0x08: 5.12us
237 * 0x09: 10.2us
238 * 0x0a: 20.5us
239 * 0x0b: 41us
240 * 0x0c: 81.9us
241 * 0x0d: 163.8us
242 * 0x0e: 327.7us
243 * 0x0f: 655.4us
244 * 0x10: 1.31ms
245 * 0x11: 2.62ms
246 * 0x12: 5.24ms
247 * 0x13: 10.49ms
248 * 0x14: 20.97sms
249 * 0x15: 42ms
250 * 0x16: 84ms
251 */
Timothy Pearson2b1bcc12015-02-14 03:40:35 -0600252 val = 0;
Timothy Pearson068ca9c2015-02-14 16:40:20 -0600253
254 if ((get_option(&nvram, "ecc_scrub_rate") == CB_SUCCESS) && (nvram <= 0x16))
255 val = nvram;
Marc Jones8ae8c882007-12-19 01:32:08 +0000256 break;
257 case NV_L2BKScrub:
258 val = 0; /* Disabled - See L2Scrub in BKDG */
259 break;
Timothy Pearson730a0432015-10-16 13:51:51 -0500260 case NV_L3BKScrub:
261 val = 0; /* Disabled - See L3Scrub in BKDG */
262 break;
Marc Jones8ae8c882007-12-19 01:32:08 +0000263 case NV_DCBKScrub:
264 val = 0; /* Disabled - See DcacheScrub in BKDG */
265 break;
266 case NV_CS_SpareCTL:
267 val = 0; /* Disabled */
268 //val = 1; /* Enabled */
Stefan Reinauerce00f1d2008-12-05 22:38:18 +0000269 break;
Marc Jones8ae8c882007-12-19 01:32:08 +0000270 case NV_SyncOnUnEccEn:
271 val = 0; /* Disabled */
272 //val = 1; /* Enabled */
Stefan Reinauerce00f1d2008-12-05 22:38:18 +0000273 break;
Marc Jones8ae8c882007-12-19 01:32:08 +0000274 case NV_Unganged:
275 /* channel interleave is better performance than ganged mode at this time */
276 val = 1; /* Enabled */
277 //val = 0; /* Disabled */
Timothy Pearson068ca9c2015-02-14 16:40:20 -0600278
279 if (get_option(&nvram, "interleave_memory_channels") == CB_SUCCESS)
280 val = !!nvram;
Stefan Reinauerce00f1d2008-12-05 22:38:18 +0000281 break;
Marc Jones8ae8c882007-12-19 01:32:08 +0000282 case NV_ChannelIntlv:
Marc Jones (marc.jonese3aeb932008-04-11 03:20:28 +0000283 val = 5; /* Not currently checked in mctchi_d.c */
Marc Jones8ae8c882007-12-19 01:32:08 +0000284 /* Bit 0 = 0 - Disable
285 * 1 - Enable
286 * Bits[2:1] = 00b - Address bits 6
287 * 01b - Address bits 1
288 * 10b - Hash*, XOR of address bits [20:16, 6]
289 * 11b - Hash*, XOR of address bits [20:16, 9]
290 */
Stefan Reinauerce00f1d2008-12-05 22:38:18 +0000291 break;
Marc Jones8ae8c882007-12-19 01:32:08 +0000292 }
293
294 return val;
295}
296
297
Myles Watson075fbe82010-04-15 05:19:29 +0000298static void mctHookAfterDIMMpre(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000299{
300}
301
302
Myles Watson075fbe82010-04-15 05:19:29 +0000303static void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat)
Marc Jones8ae8c882007-12-19 01:32:08 +0000304{
Timothy Pearson3c206782015-02-14 03:32:21 -0600305 pDCTstat->PresetmaxFreq = mctGet_NVbits(NV_MAX_MEMCLK);
306
307 /* Determine the number of installed DIMMs */
308 int ch1_count = 0;
309 int ch2_count = 0;
Timothy Pearson99e1a672015-09-05 18:00:27 -0500310 uint8_t ch1_registered = 0;
311 uint8_t ch2_registered = 0;
Timothy Pearson730a0432015-10-16 13:51:51 -0500312 uint8_t ch1_voltage = 0;
313 uint8_t ch2_voltage = 0;
314 uint8_t highest_rank_count[2];
Timothy Pearson3c206782015-02-14 03:32:21 -0600315 int i;
316 for (i = 0; i < 15; i = i + 2) {
317 if (pDCTstat->DIMMValid & (1 << i))
318 ch1_count++;
319 if (pDCTstat->DIMMValid & (1 << (i + 1)))
320 ch2_count++;
321 }
Timothy Pearson99e1a672015-09-05 18:00:27 -0500322 for (i = 0; i < MAX_DIMMS_SUPPORTED; i = i + 2) {
323 if (pDCTstat->DimmRegistered[i])
324 ch1_registered = 1;
325 if (pDCTstat->DimmRegistered[i + 1])
326 ch2_registered = 1;
327 }
Timothy Pearson3c206782015-02-14 03:32:21 -0600328 if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) {
329 printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 1: %d DIMM(s) detected\n", ch1_count);
330 printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 2: %d DIMM(s) detected\n", ch2_count);
331 }
332
Timothy Pearson730a0432015-10-16 13:51:51 -0500333#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
334 uint8_t dimm;
335
336 for (i = 0; i < 15; i = i + 2) {
337 if (pDCTstat->DIMMValid & (1 << i))
338 ch1_voltage |= pDCTstat->DimmConfiguredVoltage[i];
339 if (pDCTstat->DIMMValid & (1 << (i + 1)))
340 ch2_voltage |= pDCTstat->DimmConfiguredVoltage[i + 1];
341 }
342
343 for (i = 0; i < 2; i++) {
344 sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[i];
345 highest_rank_count[i] = 0x0;
346 for (dimm = 0; dimm < 8; dimm++) {
347 if (pDCTData->DimmRanks[dimm] > highest_rank_count[i])
348 highest_rank_count[i] = pDCTData->DimmRanks[dimm];
349 }
350 }
351#endif
352
Timothy Pearson3c206782015-02-14 03:32:21 -0600353 /* Set limits if needed */
Timothy Pearson730a0432015-10-16 13:51:51 -0500354 pDCTstat->PresetmaxFreq = mct_MaxLoadFreq(max(ch1_count, ch2_count), max(highest_rank_count[0], highest_rank_count[1]), (ch1_registered || ch2_registered), (ch1_voltage | ch2_voltage), pDCTstat->PresetmaxFreq);
Marc Jones8ae8c882007-12-19 01:32:08 +0000355}
356
Stefan Reinauerd6532112010-04-16 00:31:44 +0000357#ifdef UNUSED_CODE
Myles Watson075fbe82010-04-15 05:19:29 +0000358static void mctAdjustAutoCycTmg(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000359{
360}
Stefan Reinauerd6532112010-04-16 00:31:44 +0000361#endif
362
Marc Jones8ae8c882007-12-19 01:32:08 +0000363
Myles Watson075fbe82010-04-15 05:19:29 +0000364static void mctAdjustAutoCycTmg_D(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000365{
366}
367
368
Myles Watson075fbe82010-04-15 05:19:29 +0000369static void mctHookAfterAutoCycTmg(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000370{
371}
372
373
Myles Watson075fbe82010-04-15 05:19:29 +0000374static void mctGetCS_ExcludeMap(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000375{
376}
377
378
Myles Watson075fbe82010-04-15 05:19:29 +0000379static void mctHookAfterAutoCfg(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000380{
381}
382
383
Myles Watson075fbe82010-04-15 05:19:29 +0000384static void mctHookAfterPSCfg(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000385{
386}
387
388
Myles Watson075fbe82010-04-15 05:19:29 +0000389static void mctHookAfterHTMap(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000390{
391}
392
393
Myles Watson075fbe82010-04-15 05:19:29 +0000394static void mctHookAfterCPU(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000395{
396}
397
398
Myles Watson075fbe82010-04-15 05:19:29 +0000399static void mctSaveDQSSigTmg_D(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000400{
401}
402
403
Myles Watson075fbe82010-04-15 05:19:29 +0000404static void mctGetDQSSigTmg_D(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000405{
406}
407
408
Myles Watson075fbe82010-04-15 05:19:29 +0000409static void mctHookBeforeECC(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000410{
411}
412
413
Myles Watson075fbe82010-04-15 05:19:29 +0000414static void mctHookAfterECC(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000415{
416}
417
Stefan Reinauerd6532112010-04-16 00:31:44 +0000418#ifdef UNUSED_CODE
Myles Watson075fbe82010-04-15 05:19:29 +0000419static void mctInitMemGPIOs_A(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000420{
421}
Stefan Reinauerd6532112010-04-16 00:31:44 +0000422#endif
Marc Jones8ae8c882007-12-19 01:32:08 +0000423
424
Myles Watson075fbe82010-04-15 05:19:29 +0000425static void mctInitMemGPIOs_A_D(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000426{
427}
428
429
Myles Watson075fbe82010-04-15 05:19:29 +0000430static void mctNodeIDDebugPort_D(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000431{
432}
433
434
Stefan Reinauerd6532112010-04-16 00:31:44 +0000435#ifdef UNUSED_CODE
Myles Watson075fbe82010-04-15 05:19:29 +0000436static void mctWarmReset(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000437{
438}
Stefan Reinauerd6532112010-04-16 00:31:44 +0000439#endif
440
Marc Jones8ae8c882007-12-19 01:32:08 +0000441
Myles Watson075fbe82010-04-15 05:19:29 +0000442static void mctWarmReset_D(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000443{
444}
445
446
Myles Watson075fbe82010-04-15 05:19:29 +0000447static void mctHookBeforeDramInit(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000448{
449}
450
451
Myles Watson075fbe82010-04-15 05:19:29 +0000452static void mctHookAfterDramInit(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000453{
454}
455
Stefan Reinauer817d7542010-07-08 00:37:23 +0000456#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
Xavi Drudis Ferran213ab942010-08-22 19:51:34 +0000457static void vErratum372(struct DCTStatStruc *pDCTstat)
458{
459 msr_t msr = rdmsr(NB_CFG_MSR);
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000460
Edward O'Callaghan68a56ca2014-05-23 07:11:14 +1000461 int nbPstate1supported = !(msr.hi & (1 << (NB_GfxNbPstateDis -32)));
Xavi Drudis Ferran213ab942010-08-22 19:51:34 +0000462
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000463 // is this the right way to check for NB pstate 1 or DDR3-1333 ?
Xavi Drudis Ferran213ab942010-08-22 19:51:34 +0000464 if (((pDCTstat->PresetmaxFreq==1333)||(nbPstate1supported))
465 &&(!pDCTstat->GangedMode)) {
466 /* DisableCf8ExtCfg */
467 msr.hi &= ~(3 << (51 - 32));
468 wrmsr(NB_CFG_MSR, msr);
469 }
470}
Xavi Drudis Ferran4793ef12010-08-22 19:54:26 +0000471
472static void vErratum414(struct DCTStatStruc *pDCTstat)
473{
474 int dct=0;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000475 for(; dct < 2 ; dct++)
Xavi Drudis Ferran4793ef12010-08-22 19:54:26 +0000476 {
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000477 int dRAMConfigHi = Get_NB32(pDCTstat->dev_dct,0x94 + (0x100 * dct));
Edward O'Callaghan68a56ca2014-05-23 07:11:14 +1000478 int powerDown = dRAMConfigHi & (1 << PowerDownEn );
479 int ddr3 = dRAMConfigHi & (1 << Ddr3Mode );
Xavi Drudis Ferran4793ef12010-08-22 19:54:26 +0000480 int dRAMMRS = Get_NB32(pDCTstat->dev_dct,0x84 + (0x100 * dct));
Edward O'Callaghan68a56ca2014-05-23 07:11:14 +1000481 int pchgPDModeSel = dRAMMRS & (1 << PchgPDModeSel);
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000482 if (powerDown && ddr3 && pchgPDModeSel )
Xavi Drudis Ferran4793ef12010-08-22 19:54:26 +0000483 {
484 Set_NB32(pDCTstat->dev_dct,0x84 + (0x100 * dct), dRAMMRS & ~(1 << PchgPDModeSel) );
485 }
486 }
487}
Stefan Reinauer817d7542010-07-08 00:37:23 +0000488#endif
Marco Schmidta7741922009-06-06 11:33:58 +0000489
490
Myles Watson075fbe82010-04-15 05:19:29 +0000491static void mctHookBeforeAnyTraining(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
Marco Schmidta7741922009-06-06 11:33:58 +0000492{
Zheng Baoeb75f652010-04-23 17:32:48 +0000493#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
Xavi Drudis Ferran213ab942010-08-22 19:51:34 +0000494 /* FIXME : as of 25.6.2010 errata 350 and 372 should apply to ((RB|BL|DA)-C[23])|(HY-D[01])|(PH-E0) but I don't find constants for all of them */
Timothy Pearsonb8a355d2015-09-05 17:55:58 -0500495 if (pDCTstatA->LogicalCPUID & (AMD_DRBH_Cx | AMD_DR_Dx)) {
Xavi Drudis Ferran213ab942010-08-22 19:51:34 +0000496 vErratum372(pDCTstatA);
Xavi Drudis Ferran4793ef12010-08-22 19:54:26 +0000497 vErratum414(pDCTstatA);
Marco Schmidta7741922009-06-06 11:33:58 +0000498 }
Zheng Baoeb75f652010-04-23 17:32:48 +0000499#endif
500}
501
Stefan Reinauer6f57b512010-07-08 16:41:05 +0000502#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
Zheng Baoeb75f652010-04-23 17:32:48 +0000503static u32 mct_AdjustSPDTimings(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, u32 val)
504{
505 if (pDCTstatA->LogicalCPUID & AMD_DR_Bx) {
506 if (pDCTstatA->Status & (1 << SB_Registered)) {
507 val ++;
508 }
509 }
510 return val;
Marc Jones8ae8c882007-12-19 01:32:08 +0000511}
Stefan Reinauer6f57b512010-07-08 16:41:05 +0000512#endif
Marc Jones8ae8c882007-12-19 01:32:08 +0000513
Myles Watson075fbe82010-04-15 05:19:29 +0000514static void mctHookAfterAnyTraining(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000515{
516}
517
Timothy Pearson730a0432015-10-16 13:51:51 -0500518static uint64_t mctGetLogicalCPUID_D(u8 node)
Marc Jones8ae8c882007-12-19 01:32:08 +0000519{
520 return mctGetLogicalCPUID(node);
521}
Marc Jones (marc.jonese3aeb932008-04-11 03:20:28 +0000522
Stefan Reinauer6f57b512010-07-08 16:41:05 +0000523#if (CONFIG_DIMM_SUPPORT & 0x000F)!=0x0005 /* not needed for AMD_FAM10_DDR3 */
Myles Watson075fbe82010-04-15 05:19:29 +0000524static u8 mctSetNodeBoundary_D(void)
Marc Jones (marc.jonese3aeb932008-04-11 03:20:28 +0000525{
526 return 0;
527}
Stefan Reinauer6f57b512010-07-08 16:41:05 +0000528#endif