blob: 8dee9ab81470a7ecce962cf84c3d5ff89069e772 [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 *
Damien Zammit75a3d1f2016-11-28 00:29:10 +11004 * Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
Timothy Pearson3c206782015-02-14 03:32:21 -06005 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Marc Jones8ae8c882007-12-19 01:32:08 +00006 * Copyright (C) 2007 Advanced Micro Devices, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Marc Jones8ae8c882007-12-19 01:32:08 +000016 */
17
Damien Zammit75a3d1f2016-11-28 00:29:10 +110018#include <inttypes.h>
Damien Zammit75a3d1f2016-11-28 00:29:10 +110019#include <arch/acpi.h>
Elyes HAOUASd2b9ec12018-10-27 09:41:02 +020020#include <arch/cpu.h>
Damien Zammit75a3d1f2016-11-28 00:29:10 +110021#include <device/pci.h>
22#include <string.h>
23#include <cbmem.h>
24#include <console/console.h>
25#include <northbridge/amd/amdfam10/debug.h>
26#include <northbridge/amd/amdfam10/raminit.h>
27#include <northbridge/amd/amdfam10/amdfam10.h>
Elyes HAOUAS2dce9232019-01-09 08:43:09 +010028#include <timestamp.h>
Stefan Reinauer6f57b512010-07-08 16:41:05 +000029
Damien Zammit75a3d1f2016-11-28 00:29:10 +110030/* Global allocation of sysinfo_car */
31#include <arch/early_variables.h>
32struct sys_info sysinfo_car CAR_GLOBAL;
Marc Jones8ae8c882007-12-19 01:32:08 +000033
Damien Zammit75a3d1f2016-11-28 00:29:10 +110034struct mem_controller;
35extern void activate_spd_rom(const struct mem_controller *ctrl);
Elyes HAOUASb60920d2018-09-20 17:38:38 +020036extern int spd_read_byte(unsigned int device, unsigned int address);
Zheng Baoeb75f652010-04-23 17:32:48 +000037
Damien Zammit75a3d1f2016-11-28 00:29:10 +110038void fam15h_switch_dct(uint32_t dev, uint8_t dct)
Timothy Pearson3c206782015-02-14 03:32:21 -060039{
Timothy Pearson730a0432015-10-16 13:51:51 -050040 uint32_t dword;
41
42 dword = Get_NB32(dev, 0x10c);
43 dword &= ~0x1;
44 dword |= (dct & 0x1);
45 Set_NB32(dev, 0x10c, dword);
46}
47
48static inline void fam15h_switch_nb_pstate_config_reg(uint32_t dev, uint8_t nb_pstate)
49{
50 uint32_t dword;
51
52 dword = Get_NB32(dev, 0x10c);
53 dword &= ~(0x3 << 4);
54 dword |= (nb_pstate & 0x3) << 4;
55 Set_NB32(dev, 0x10c, dword);
56}
57
Damien Zammit75a3d1f2016-11-28 00:29:10 +110058uint32_t Get_NB32_DCT(uint32_t dev, uint8_t dct, uint32_t reg)
Timothy Pearson730a0432015-10-16 13:51:51 -050059{
60 if (is_fam15h()) {
61 /* Obtain address of function 0x1 */
62 uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
63 fam15h_switch_dct(dev_map, dct);
64 return Get_NB32(dev, reg);
65 } else {
66 return Get_NB32(dev, (0x100 * dct) + reg);
67 }
68}
69
Damien Zammit75a3d1f2016-11-28 00:29:10 +110070void Set_NB32_DCT(uint32_t dev, uint8_t dct, uint32_t reg, uint32_t val)
Timothy Pearson730a0432015-10-16 13:51:51 -050071{
72 if (is_fam15h()) {
73 /* Obtain address of function 0x1 */
74 uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
75 fam15h_switch_dct(dev_map, dct);
76 Set_NB32(dev, reg, val);
77 } else {
78 Set_NB32(dev, (0x100 * dct) + reg, val);
79 }
80}
81
Damien Zammit75a3d1f2016-11-28 00:29:10 +110082uint32_t Get_NB32_DCT_NBPstate(uint32_t dev, uint8_t dct, uint8_t nb_pstate, uint32_t reg)
Timothy Pearson730a0432015-10-16 13:51:51 -050083{
84 if (is_fam15h()) {
85 /* Obtain address of function 0x1 */
86 uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
87 fam15h_switch_dct(dev_map, dct);
88 fam15h_switch_nb_pstate_config_reg(dev_map, nb_pstate);
89 return Get_NB32(dev, reg);
90 } else {
91 return Get_NB32(dev, (0x100 * dct) + reg);
92 }
93}
94
Damien Zammit75a3d1f2016-11-28 00:29:10 +110095void Set_NB32_DCT_NBPstate(uint32_t dev, uint8_t dct, uint8_t nb_pstate, uint32_t reg, uint32_t val)
Timothy Pearson730a0432015-10-16 13:51:51 -050096{
97 if (is_fam15h()) {
98 /* Obtain address of function 0x1 */
99 uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
100 fam15h_switch_dct(dev_map, dct);
101 fam15h_switch_nb_pstate_config_reg(dev_map, nb_pstate);
102 Set_NB32(dev, reg, val);
103 } else {
104 Set_NB32(dev, (0x100 * dct) + reg, val);
105 }
106}
107
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100108uint32_t Get_NB32_index_wait_DCT(uint32_t dev, uint8_t dct, uint32_t index_reg, uint32_t index)
Timothy Pearson730a0432015-10-16 13:51:51 -0500109{
110 if (is_fam15h()) {
111 /* Obtain address of function 0x1 */
112 uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
113 fam15h_switch_dct(dev_map, dct);
114 return Get_NB32_index_wait(dev, index_reg, index);
115 } else {
116 return Get_NB32_index_wait(dev, (0x100 * dct) + index_reg, index);
117 }
118}
119
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100120void Set_NB32_index_wait_DCT(uint32_t dev, uint8_t dct, uint32_t index_reg, uint32_t index, uint32_t data)
Timothy Pearson730a0432015-10-16 13:51:51 -0500121{
122 if (is_fam15h()) {
123 /* Obtain address of function 0x1 */
124 uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
125 fam15h_switch_dct(dev_map, dct);
126 Set_NB32_index_wait(dev, index_reg, index, data);
127 } else {
128 Set_NB32_index_wait(dev, (0x100 * dct) + index_reg, index, data);
129 }
130}
131
132static uint16_t voltage_index_to_mv(uint8_t index)
133{
134 if (index & 0x8)
135 return 1150;
136 if (index & 0x4)
137 return 1250;
138 else if (index & 0x2)
139 return 1350;
140 else
141 return 1500;
142}
143
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100144uint16_t mct_MaxLoadFreq(uint8_t count, uint8_t highest_rank_count, uint8_t registered, uint8_t voltage, uint16_t freq)
Timothy Pearson730a0432015-10-16 13:51:51 -0500145{
146 /* FIXME
147 * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
148 * For now assume a maximum of 2 DIMMs per channel can be installed
149 */
150 uint8_t MaxDimmsInstallable = 2;
151
Timothy Pearson3c206782015-02-14 03:32:21 -0600152 /* Return limited maximum RAM frequency */
153 if (IS_ENABLED(CONFIG_DIMM_DDR2)) {
Timothy Pearson99e1a672015-09-05 18:00:27 -0500154 if (IS_ENABLED(CONFIG_DIMM_REGISTERED) && registered) {
Timothy Pearson3c206782015-02-14 03:32:21 -0600155 /* K10 BKDG Rev. 3.62 Table 53 */
156 if (count > 2) {
157 /* Limit to DDR2-533 */
158 if (freq > 266) {
159 freq = 266;
Timothy Pearson99e1a672015-09-05 18:00:27 -0500160 print_tf(__func__, ": More than 2 registered DIMMs on channel; limiting to DDR2-533\n");
Timothy Pearson3c206782015-02-14 03:32:21 -0600161 }
162 }
Timothy Pearson99e1a672015-09-05 18:00:27 -0500163 } else {
Timothy Pearson3c206782015-02-14 03:32:21 -0600164 /* K10 BKDG Rev. 3.62 Table 52 */
165 if (count > 1) {
166 /* Limit to DDR2-800 */
167 if (freq > 400) {
168 freq = 400;
Timothy Pearson99e1a672015-09-05 18:00:27 -0500169 print_tf(__func__, ": More than 1 unbuffered DIMM on channel; limiting to DDR2-800\n");
Timothy Pearson3c206782015-02-14 03:32:21 -0600170 }
171 }
172 }
Timothy Pearson99e1a672015-09-05 18:00:27 -0500173 } else if (IS_ENABLED(CONFIG_DIMM_DDR3)) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500174 if (voltage == 0) {
175 printk(BIOS_DEBUG, "%s: WARNING: Mainboard DDR3 voltage unknown, assuming 1.5V!\n", __func__);
176 voltage = 0x1;
177 }
178
179 if (is_fam15h()) {
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600180 if (CONFIG_CPU_SOCKET_TYPE == 0x15) {
181 /* Socket G34 */
182 if (IS_ENABLED(CONFIG_DIMM_REGISTERED) && registered) {
183 /* Fam15h BKDG Rev. 3.14 Table 27 */
184 if (voltage & 0x4) {
185 /* 1.25V */
186 if (count > 1) {
187 if (highest_rank_count > 1) {
188 /* Limit to DDR3-1066 */
189 if (freq > 533) {
190 freq = 533;
191 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
192 }
193 } else {
194 /* Limit to DDR3-1333 */
195 if (freq > 666) {
196 freq = 666;
197 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
198 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500199 }
200 } else {
201 /* Limit to DDR3-1333 */
202 if (freq > 666) {
203 freq = 666;
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600204 printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
Timothy Pearson730a0432015-10-16 13:51:51 -0500205 }
206 }
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600207 } else if (voltage & 0x2) {
208 /* 1.35V */
209 if (count > 1) {
210 /* Limit to DDR3-1333 */
211 if (freq > 666) {
212 freq = 666;
213 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
214 }
215 } else {
216 /* Limit to DDR3-1600 */
217 if (freq > 800) {
218 freq = 800;
219 printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
220 }
221 }
222 } else if (voltage & 0x1) {
223 /* 1.50V */
224 if (count > 1) {
225 /* Limit to DDR3-1600 */
226 if (freq > 800) {
227 freq = 800;
228 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
229 }
230 } else {
231 /* Limit to DDR3-1866 */
232 if (freq > 933) {
233 freq = 933;
234 printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1866\n", __func__, voltage_index_to_mv(voltage));
235 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500236 }
237 }
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600238 } else {
239 /* Fam15h BKDG Rev. 3.14 Table 26 */
240 if (voltage & 0x4) {
241 /* 1.25V */
242 if (count > 1) {
243 if (highest_rank_count > 1) {
244 /* Limit to DDR3-1066 */
245 if (freq > 533) {
246 freq = 533;
247 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
248 }
249 } else {
250 /* Limit to DDR3-1333 */
251 if (freq > 666) {
252 freq = 666;
253 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
254 }
255 }
256 } else {
257 /* Limit to DDR3-1333 */
258 if (freq > 666) {
259 freq = 666;
260 printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
261 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500262 }
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600263 } else if (voltage & 0x2) {
264 /* 1.35V */
265 if (MaxDimmsInstallable > 1) {
266 /* Limit to DDR3-1333 */
267 if (freq > 666) {
268 freq = 666;
269 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
270 }
271 } else {
272 /* Limit to DDR3-1600 */
273 if (freq > 800) {
274 freq = 800;
275 printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
276 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500277 }
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600278 } else if (voltage & 0x1) {
279 if (MaxDimmsInstallable == 1) {
280 if (count > 1) {
281 /* Limit to DDR3-1600 */
282 if (freq > 800) {
283 freq = 800;
284 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
285 }
286 } else {
287 /* Limit to DDR3-1866 */
288 if (freq > 933) {
289 freq = 933;
290 printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1866\n", __func__, voltage_index_to_mv(voltage));
291 }
292 }
293 } else {
294 if (count > 1) {
295 if (highest_rank_count > 1) {
296 /* Limit to DDR3-1333 */
297 if (freq > 666) {
298 freq = 666;
299 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
300 }
301 } else {
302 /* Limit to DDR3-1600 */
303 if (freq > 800) {
304 freq = 800;
305 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
306 }
307 }
308 } else {
309 /* Limit to DDR3-1600 */
310 if (freq > 800) {
311 freq = 800;
312 printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
313 }
314 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500315 }
316 }
Timothy Pearson99e1a672015-09-05 18:00:27 -0500317 }
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600318 } else if (CONFIG_CPU_SOCKET_TYPE == 0x14) {
319 /* Socket C32 */
320 if (IS_ENABLED(CONFIG_DIMM_REGISTERED) && registered) {
321 /* Fam15h BKDG Rev. 3.14 Table 30 */
322 if (voltage & 0x4) {
323 /* 1.25V */
324 if (count > 1) {
325 if (highest_rank_count > 2) {
326 /* Limit to DDR3-800 */
327 if (freq > 400) {
328 freq = 400;
329 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-800\n", __func__, voltage_index_to_mv(voltage));
330 }
331 } else {
332 /* Limit to DDR3-1333 */
333 if (freq > 666) {
334 freq = 666;
335 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
336 }
337 }
338 } else {
339 /* Limit to DDR3-1333 */
340 if (freq > 666) {
341 freq = 666;
342 printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
343 }
344 }
345 } else if (voltage & 0x2) {
346 /* 1.35V */
347 if (count > 1) {
348 if (highest_rank_count > 2) {
349 /* Limit to DDR3-800 */
350 if (freq > 400) {
351 freq = 400;
352 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-800\n", __func__, voltage_index_to_mv(voltage));
353 }
354 } else if (highest_rank_count > 1) {
355 /* Limit to DDR3-1066 */
356 if (freq > 533) {
357 freq = 533;
358 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
359 }
360 } else {
361 /* Limit to DDR3-1333 */
362 if (freq > 666) {
363 freq = 666;
364 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
365 }
366 }
367 } else {
368 /* Limit to DDR3-1600 */
369 if (freq > 800) {
370 freq = 800;
371 printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
372 }
373 }
374 } else if (voltage & 0x1) {
375 /* 1.50V */
376 if (count > 1) {
377 if (highest_rank_count > 2) {
378 /* Limit to DDR3-800 */
379 if (freq > 400) {
380 freq = 400;
381 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-800\n", __func__, voltage_index_to_mv(voltage));
382 }
383 } else if (highest_rank_count > 1) {
384 /* Limit to DDR3-1066 */
385 if (freq > 533) {
386 freq = 533;
387 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
388 }
389 } else {
390 /* Limit to DDR3-1333 */
391 if (freq > 666) {
392 freq = 666;
393 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
394 }
395 }
396 } else {
397 if (highest_rank_count > 2) {
398 /* Limit to DDR3-1333 */
399 if (freq > 666) {
400 freq = 666;
401 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
402 }
403 } else {
404 /* Limit to DDR3-1600 */
405 if (freq > 800) {
406 freq = 800;
407 printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
408 }
409 }
410 }
411 }
412 } else {
413 /* Fam15h BKDG Rev. 3.14 Table 29 */
414 if (voltage & 0x4) {
415 /* 1.25V */
416 if (count > 1) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500417 /* Limit to DDR3-1066 */
418 if (freq > 533) {
419 freq = 533;
420 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
421 }
422 } else {
423 /* Limit to DDR3-1333 */
424 if (freq > 666) {
425 freq = 666;
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600426 printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
Timothy Pearson730a0432015-10-16 13:51:51 -0500427 }
428 }
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600429 } else if (voltage & 0x2) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500430 if (count > 1) {
431 if (highest_rank_count > 1) {
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600432 /* Limit to DDR3-1066 */
433 if (freq > 533) {
434 freq = 533;
435 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
436 }
437 } else {
Timothy Pearson730a0432015-10-16 13:51:51 -0500438 /* Limit to DDR3-1333 */
439 if (freq > 666) {
440 freq = 666;
441 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
442 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500443 }
444 } else {
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600445 /* Limit to DDR3-1333 */
446 if (freq > 666) {
447 freq = 666;
448 printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
449 }
450 }
451 } else if (voltage & 0x1) {
452 if (MaxDimmsInstallable == 1) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500453 /* Limit to DDR3-1600 */
454 if (freq > 800) {
455 freq = 800;
456 printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
457 }
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600458 } else {
459 if (count > 1) {
460 if (highest_rank_count > 1) {
461 /* Limit to DDR3-1066 */
462 if (freq > 533) {
463 freq = 533;
464 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
465 }
466 } else {
467 /* Limit to DDR3-1333 */
468 if (freq > 666) {
469 freq = 666;
470 printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
471 }
472 }
473 } else {
474 /* Limit to DDR3-1600 */
475 if (freq > 800) {
476 freq = 800;
477 printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
478 }
479 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500480 }
481 }
Timothy Pearson99e1a672015-09-05 18:00:27 -0500482 }
Timothy Pearson19ce16a2015-11-24 14:11:47 -0600483 } else {
484 /* TODO
485 * Other socket support unimplemented
486 */
Timothy Pearson99e1a672015-09-05 18:00:27 -0500487 }
488 } else {
Timothy Pearson730a0432015-10-16 13:51:51 -0500489 if (IS_ENABLED(CONFIG_DIMM_REGISTERED) && registered) {
490 /* K10 BKDG Rev. 3.62 Table 34 */
491 if (count > 2) {
492 /* Limit to DDR3-800 */
493 if (freq > 400) {
494 freq = 400;
495 printk(BIOS_DEBUG, "%s: More than 2 registered DIMMs on %dmV channel; limiting to DDR3-800\n", __func__, voltage_index_to_mv(voltage));
496 }
497 } else if (count == 2) {
498 /* Limit to DDR3-1066 */
499 if (freq > 533) {
500 freq = 533;
501 printk(BIOS_DEBUG, "%s: 2 registered DIMMs on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
502 }
503 } else {
504 /* Limit to DDR3-1333 */
505 if (freq > 666) {
506 freq = 666;
507 printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
508 }
509 }
510 } else {
511 /* K10 BKDG Rev. 3.62 Table 33 */
512 /* Limit to DDR3-1333 */
513 if (freq > 666) {
514 freq = 666;
515 printk(BIOS_DEBUG, "%s: unbuffered DIMMs on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
516 }
Timothy Pearson99e1a672015-09-05 18:00:27 -0500517 }
518 }
Timothy Pearson3c206782015-02-14 03:32:21 -0600519 }
520
521 return freq;
522}
523
Marc Jones8ae8c882007-12-19 01:32:08 +0000524int mctRead_SPD(u32 smaddr, u32 reg)
525{
526 return spd_read_byte(smaddr, reg);
527}
528
529
530void mctSMBhub_Init(u32 node)
531{
Patrick Georgibbc880e2012-11-20 18:20:56 +0100532 struct sys_info *sysinfo = &sysinfo_car;
Elyes HAOUAS04f8fd92016-09-19 10:24:34 -0600533 struct mem_controller *ctrl = &(sysinfo->ctrl[node]);
Marc Jones8ae8c882007-12-19 01:32:08 +0000534 activate_spd_rom(ctrl);
535}
536
537
538void mctGet_DIMMAddr(struct DCTStatStruc *pDCTstat, u32 node)
539{
540 int j;
Patrick Georgibbc880e2012-11-20 18:20:56 +0100541 struct sys_info *sysinfo = &sysinfo_car;
Elyes HAOUAS04f8fd92016-09-19 10:24:34 -0600542 struct mem_controller *ctrl = &(sysinfo->ctrl[node]);
Marc Jones8ae8c882007-12-19 01:32:08 +0000543
Elyes HAOUAS04f8fd92016-09-19 10:24:34 -0600544 for (j = 0; j < DIMM_SOCKETS; j++) {
Marc Jones8ae8c882007-12-19 01:32:08 +0000545 pDCTstat->DIMMAddr[j*2] = ctrl->spd_addr[j] & 0xff;
546 pDCTstat->DIMMAddr[j*2+1] = ctrl->spd_addr[DIMM_SOCKETS + j] & 0xff;
547 }
548
549}
550
Timothy Pearson730a0432015-10-16 13:51:51 -0500551#if IS_ENABLED(CONFIG_SET_FIDVID)
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100552u8 mctGetProcessorPackageType(void) {
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000553 /* FIXME: I guess this belongs wherever mctGetLogicalCPUID ends up ? */
Timothy Pearson730a0432015-10-16 13:51:51 -0500554 u32 BrandId = cpuid_ebx(0x80000001);
555 return (u8)((BrandId >> 28) & 0x0F);
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000556}
Timothy Pearson730a0432015-10-16 13:51:51 -0500557#endif
Marc Jones8ae8c882007-12-19 01:32:08 +0000558
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100559void raminit_amdmct(struct sys_info *sysinfo)
Marc Jones8ae8c882007-12-19 01:32:08 +0000560{
561 struct MCTStatStruc *pMCTstat = &(sysinfo->MCTstat);
562 struct DCTStatStruc *pDCTstatA = sysinfo->DCTstatA;
563
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800564 printk(BIOS_DEBUG, "raminit_amdmct begin:\n");
Elyes HAOUAS2dce9232019-01-09 08:43:09 +0100565 timestamp_add_now(TS_BEFORE_INITRAM);
Marc Jones8ae8c882007-12-19 01:32:08 +0000566
567 mctAutoInitMCT_D(pMCTstat, pDCTstatA);
568
Elyes HAOUAS2dce9232019-01-09 08:43:09 +0100569 timestamp_add_now(TS_AFTER_INITRAM);
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800570 printk(BIOS_DEBUG, "raminit_amdmct end:\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000571}
Timothy Pearson22564082015-03-27 22:49:18 -0500572
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100573void amdmct_cbmem_store_info(struct sys_info *sysinfo)
Timothy Pearson22564082015-03-27 22:49:18 -0500574{
Timothy Pearson46b22712015-04-12 14:11:27 -0500575 if (!sysinfo)
576 return;
577
Timothy Pearson22564082015-03-27 22:49:18 -0500578 /* Save memory info structures for use in ramstage */
579 size_t i;
Timothy Pearson22564082015-03-27 22:49:18 -0500580 struct DCTStatStruc *pDCTstatA = NULL;
581
Timothy Pearson4ea0cc02015-09-05 18:39:34 -0500582 if (!acpi_is_wakeup_s3()) {
583 /* Allocate memory */
584 struct amdmct_memory_info *mem_info;
585 mem_info = cbmem_add(CBMEM_ID_AMDMCT_MEMINFO, sizeof(struct amdmct_memory_info));
586 if (!mem_info)
587 return;
Timothy Pearson22564082015-03-27 22:49:18 -0500588
Timothy Pearson4ea0cc02015-09-05 18:39:34 -0500589 printk(BIOS_DEBUG, "%s: Storing AMDMCT configuration in CBMEM\n", __func__);
Timothy Pearson22564082015-03-27 22:49:18 -0500590
Timothy Pearson4ea0cc02015-09-05 18:39:34 -0500591 /* Initialize memory */
592 memset(mem_info, 0, sizeof(struct amdmct_memory_info));
Timothy Pearson22564082015-03-27 22:49:18 -0500593
Timothy Pearson4ea0cc02015-09-05 18:39:34 -0500594 /* Copy data */
595 memcpy(&mem_info->mct_stat, &sysinfo->MCTstat, sizeof(struct MCTStatStruc));
596 for (i = 0; i < MAX_NODES_SUPPORTED; i++) {
597 pDCTstatA = sysinfo->DCTstatA + i;
598 memcpy(&mem_info->dct_stat[i], pDCTstatA, sizeof(struct DCTStatStruc));
599 }
600 mem_info->ecc_enabled = mctGet_NVbits(NV_ECC_CAP);
601 mem_info->ecc_scrub_rate = mctGet_NVbits(NV_DramBKScrub);
Timothy Pearson46b22712015-04-12 14:11:27 -0500602
Timothy Pearson4ea0cc02015-09-05 18:39:34 -0500603 /* Zero out invalid/unused pointers */
Timothy Pearson46b22712015-04-12 14:11:27 -0500604#if IS_ENABLED(CONFIG_DIMM_DDR3)
Timothy Pearson4ea0cc02015-09-05 18:39:34 -0500605 for (i = 0; i < MAX_NODES_SUPPORTED; i++) {
606 mem_info->dct_stat[i].C_MCTPtr = NULL;
607 mem_info->dct_stat[i].C_DCTPtr[0] = NULL;
608 mem_info->dct_stat[i].C_DCTPtr[1] = NULL;
609 }
Timothy Pearson46b22712015-04-12 14:11:27 -0500610#endif
Timothy Pearson4ea0cc02015-09-05 18:39:34 -0500611 }
Timothy Pearson22564082015-03-27 22:49:18 -0500612}