blob: ce7a3bf777a3ae7e59426721c4485b29f071d447 [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Patrick Rudolph6e53ae62017-01-31 19:43:17 +01002
3/**
4 * @file ddr2.c
5 *
6 * \brief Utilities for decoding DDR2 SPDs
7 */
8
9#include <console/console.h>
10#include <device/device.h>
11#include <device/dram/ddr2.h>
Arthur Heymans3397aa12017-03-01 20:10:55 +010012#include <lib.h>
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010013#include <string.h>
Elyes HAOUASbd1683d2019-05-15 21:05:37 +020014#include <types.h>
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010015
16/*==============================================================================
17 * = DDR2 SPD decoding helpers
18 *----------------------------------------------------------------------------*/
19
20/**
21 * \brief Checks if the DIMM is Registered based on byte[20] of the SPD
22 *
23 * Tells if the DIMM type is registered or not.
24 *
25 * @param type DIMM type. This is byte[20] of the SPD.
26 */
Arthur Heymansfc31e442018-02-12 15:12:34 +010027int spd_dimm_is_registered_ddr2(enum spd_dimm_type_ddr2 type)
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010028{
Elyes Haouasc705ecd2022-05-29 14:58:00 +020029 if ((type == SPD_DDR2_DIMM_TYPE_RDIMM) || (type == SPD_DDR2_DIMM_TYPE_72B_SO_RDIMM) ||
30 (type == SPD_DDR2_DIMM_TYPE_MINI_RDIMM))
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010031 return 1;
32
33 return 0;
34}
35
36/**
37 * \brief Calculate the checksum of a DDR2 SPD unique identifier
38 *
39 * @param spd pointer to raw SPD data
40 * @param len length of data in SPD
41 *
42 * @return the checksum of SPD data bytes 63, or 0 when spd data is truncated.
43 */
44u8 spd_ddr2_calc_checksum(u8 *spd, int len)
45{
46 int i;
47 u8 c = 0;
48
49 if (len < 63)
50 /* Not enough bytes available to get the checksum */
51 return 0;
52
53 for (i = 0; i < 63; i++)
54 c += spd[i];
55
56 return c;
57}
58
59/**
Arthur Heymans97b337b2018-01-22 01:26:53 +010060 * \brief Calculate the CRC of a DDR2 SPD unique identifier
61 *
62 * @param spd pointer to raw SPD data
63 * @param len length of data in SPD
64 *
65 * @return the CRC of SPD data bytes 64..72 and 93..98, or 0
66 * when spd data is truncated.
67 */
68u16 spd_ddr2_calc_unique_crc(const u8 *spd, int len)
69{
70 u8 id_bytes[15];
71 int i, j = 0;
72 if (len < 98)
73 /* Not enough bytes available to get the CRC */
74 return 0;
75 for (i = 64; i <= 72; i++)
76 id_bytes[j++] = spd[i];
77 for (i = 93; i <= 98; i++)
78 id_bytes[j++] = spd[i];
79
Andrey Petrov3f85edb2019-08-01 14:18:06 -070080 return ddr_crc16(id_bytes, 15);
Arthur Heymans97b337b2018-01-22 01:26:53 +010081}
82
83/**
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010084 * \brief Return size of SPD.
85 *
86 * Returns size of SPD. Usually 128 Byte.
87 */
88u32 spd_decode_spd_size_ddr2(u8 byte0)
89{
90 return MIN(byte0, SPD_SIZE_MAX_DDR2);
91}
92
93/**
94 * \brief Return size of eeprom.
95 *
96 * Returns size of eeprom. Usually 256 Byte.
97 */
98u32 spd_decode_eeprom_size_ddr2(u8 byte1)
99{
100 if (!byte1)
101 return 0;
102
103 if (byte1 > 0x0e)
104 return 0x3fff;
105
106 return 1 << byte1;
107}
108
109/**
110 * \brief Return index of MSB set
111 *
Elyes HAOUAS05b1cb82018-09-05 17:37:56 +0200112 * Returns the index of MSB set.
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100113 */
Arthur Heymans3397aa12017-03-01 20:10:55 +0100114u8 spd_get_msbs(u8 c)
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100115{
Arthur Heymans3397aa12017-03-01 20:10:55 +0100116 return log2(c);
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100117}
118
119/**
120 * \brief Decode SPD tck cycle time
121 *
122 * Decodes a raw SPD data from a DDR2 DIMM.
123 * Returns cycle time in 1/256th ns.
124 */
Elyes Haouas803241c2022-10-08 15:50:32 +0200125static enum cb_err spd_decode_tck_time(u32 *tck, u8 c)
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100126{
127 u8 high, low;
128
129 high = c >> 4;
130
131 switch (c & 0xf) {
132 case 0xa:
133 low = 25;
134 break;
135 case 0xb:
136 low = 33;
137 break;
138 case 0xc:
139 low = 66;
140 break;
141 case 0xd:
142 low = 75;
143 break;
Arthur Heymans2785c112017-09-10 20:57:37 +0200144 case 0xe:
145 case 0xf:
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200146 printk(BIOS_WARNING, "Invalid tck setting. lower nibble is 0x%x\n", c & 0xf);
Arthur Heymans2785c112017-09-10 20:57:37 +0200147 return CB_ERR;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100148 default:
149 low = (c & 0xf) * 10;
150 }
151
Arthur Heymans2785c112017-09-10 20:57:37 +0200152 *tck = ((high * 100 + low) << 8) / 100;
153 return CB_SUCCESS;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100154}
155
156/**
157 * \brief Decode SPD bcd style timings
158 *
159 * Decodes a raw SPD data from a DDR2 DIMM.
160 * Returns cycle time in 1/256th ns.
161 */
Elyes Haouas803241c2022-10-08 15:50:32 +0200162static enum cb_err spd_decode_bcd_time(u32 *bcd, u8 c)
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100163{
164 u8 high, low;
165
166 high = c >> 4;
167 low = c & 0xf;
Arthur Heymans2785c112017-09-10 20:57:37 +0200168 if (high >= 10 || low >= 10)
169 return CB_ERR;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100170
Arthur Heymans2785c112017-09-10 20:57:37 +0200171 *bcd = ((high * 10 + low) << 8) / 100;
172 return CB_SUCCESS;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100173}
174
175/**
176 * \brief Decode SPD tRP, tRRP cycle time
177 *
178 * Decodes a raw SPD data from a DDR2 DIMM.
179 * Returns cycle time in 1/256th ns.
180 */
181static u32 spd_decode_quarter_time(u8 c)
182{
183 u8 high, low;
184
185 high = c >> 2;
186 low = 25 * (c & 0x3);
187
188 return ((high * 100 + low) << 8) / 100;
189}
190
191/**
192 * \brief Decode SPD tRR time
193 *
194 * Decodes a raw SPD data from a DDR2 DIMM.
195 * Returns cycle time in 1/256th us.
196 */
Elyes Haouas803241c2022-10-08 15:50:32 +0200197static enum cb_err spd_decode_tRR_time(u32 *tRR, u8 c)
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100198{
Arthur Heymans7eb01572017-09-21 08:28:23 +0200199 switch (c & ~0x80) {
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100200 default:
Arthur Heymans2785c112017-09-10 20:57:37 +0200201 printk(BIOS_WARNING, "Invalid tRR value 0x%x\n", c);
202 return CB_ERR;
Arthur Heymans7eb01572017-09-21 08:28:23 +0200203 case 0x0:
Arthur Heymans2785c112017-09-10 20:57:37 +0200204 *tRR = 15625 << 8;
Patrick Georgia2248cb2017-09-22 18:21:52 +0200205 break;
Arthur Heymans7eb01572017-09-21 08:28:23 +0200206 case 0x1:
Arthur Heymans2785c112017-09-10 20:57:37 +0200207 *tRR = 15625 << 6;
Patrick Georgia2248cb2017-09-22 18:21:52 +0200208 break;
Arthur Heymans7eb01572017-09-21 08:28:23 +0200209 case 0x2:
Arthur Heymans2785c112017-09-10 20:57:37 +0200210 *tRR = 15625 << 7;
Patrick Georgia2248cb2017-09-22 18:21:52 +0200211 break;
Arthur Heymans7eb01572017-09-21 08:28:23 +0200212 case 0x3:
Arthur Heymans2785c112017-09-10 20:57:37 +0200213 *tRR = 15625 << 9;
Patrick Georgia2248cb2017-09-22 18:21:52 +0200214 break;
Arthur Heymans7eb01572017-09-21 08:28:23 +0200215 case 0x4:
Arthur Heymans2785c112017-09-10 20:57:37 +0200216 *tRR = 15625 << 10;
Patrick Georgia2248cb2017-09-22 18:21:52 +0200217 break;
Arthur Heymans7eb01572017-09-21 08:28:23 +0200218 case 0x5:
Arthur Heymans2785c112017-09-10 20:57:37 +0200219 *tRR = 15625 << 11;
Patrick Georgia2248cb2017-09-22 18:21:52 +0200220 break;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100221 }
Arthur Heymans2785c112017-09-10 20:57:37 +0200222 return CB_SUCCESS;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100223}
224
225/**
226 * \brief Decode SPD tRC,tRFC time
227 *
228 * Decodes a raw SPD data from a DDR2 DIMM.
229 * Returns cycle time in 1/256th us.
230 */
231static void spd_decode_tRCtRFC_time(u8 *spd_40_41_42, u32 *tRC, u32 *tRFC)
232{
233 u8 b40, b41, b42;
234
235 b40 = spd_40_41_42[0];
236 b41 = spd_40_41_42[1];
237 b42 = spd_40_41_42[2];
238
239 *tRC = b41 * 100;
240 *tRFC = b42 * 100;
241
242 if (b40 & 0x01)
243 *tRFC += 256 * 100;
244
245 switch ((b40 >> 1) & 0x07) {
246 case 1:
247 *tRFC += 25;
248 break;
249 case 2:
250 *tRFC += 33;
251 break;
252 case 3:
253 *tRFC += 50;
254 break;
255 case 4:
256 *tRFC += 66;
257 break;
258 case 5:
259 *tRFC += 75;
260 break;
261 default:
262 break;
263 }
264
265 switch ((b40 >> 4) & 0x07) {
266 case 1:
267 *tRC += 25;
268 break;
269 case 2:
270 *tRC += 33;
271 break;
272 case 3:
273 *tRC += 50;
274 break;
275 case 4:
276 *tRC += 66;
277 break;
278 case 5:
279 *tRC += 75;
280 break;
281 default:
282 break;
283 }
284
285 /* Convert to 1/256th us */
286 *tRC = (*tRC << 8) / 100;
287 *tRFC = (*tRFC << 8) / 100;
288}
289
290/**
291 * \brief Decode the raw SPD data
292 *
293 * Decodes a raw SPD data from a DDR2 DIMM, and organizes it into a
294 * @ref dimm_attr structure. The SPD data must first be read in a contiguous
295 * array, and passed to this function.
296 *
297 * @param dimm pointer to @ref dimm_attr structure where the decoded data is to
298 * be stored
299 * @param spd array of raw data previously read from the SPD.
300 *
301 * @return @ref spd_status enumerator
302 * SPD_STATUS_OK -- decoding was successful
303 * SPD_STATUS_INVALID -- invalid SPD or not a DDR2 SPD
304 * SPD_STATUS_CRC_ERROR -- CRC did not verify
305 * SPD_STATUS_INVALID_FIELD -- A field with an invalid value was
306 * detected.
307 */
Arthur Heymansfc31e442018-02-12 15:12:34 +0100308int spd_decode_ddr2(struct dimm_attr_ddr2_st *dimm, u8 spd[SPD_SIZE_MAX_DDR2])
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100309{
310 u8 spd_size, cl, reg8;
311 u16 eeprom_size;
312 int ret = SPD_STATUS_OK;
313
314 memset(dimm, 0, sizeof(*dimm));
315
316 spd_size = spd_decode_spd_size_ddr2(spd[0]);
317 eeprom_size = spd_decode_eeprom_size_ddr2(spd[1]);
318
319 printram("EEPROM with 0x%04x bytes\n", eeprom_size);
320 printram("SPD contains 0x%02x bytes\n", spd_size);
321
322 if (spd_size < 64 || eeprom_size < 64) {
Elyes HAOUAS83bc4082022-02-04 19:34:53 +0100323 printk(BIOS_ERR, "SPD too small\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100324 dimm->dram_type = SPD_MEMORY_TYPE_UNDEFINED;
325 return SPD_STATUS_INVALID;
326 }
327
328 if (spd_ddr2_calc_checksum(spd, spd_size) != spd[63]) {
Elyes HAOUAS83bc4082022-02-04 19:34:53 +0100329 printk(BIOS_ERR, "SPD checksum error\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100330 dimm->dram_type = SPD_MEMORY_TYPE_UNDEFINED;
331 return SPD_STATUS_CRC_ERROR;
332 }
Arthur Heymansb5d4dd12017-09-25 12:47:41 +0200333 dimm->checksum = spd[63];
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100334
335 reg8 = spd[62];
336 if ((reg8 & 0xf0) != 0x10) {
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200337 printk(BIOS_ERR, "Unsupported SPD revision %01x.%01x\n", reg8 >> 4, reg8 & 0xf);
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100338 dimm->dram_type = SPD_MEMORY_TYPE_UNDEFINED;
339 return SPD_STATUS_INVALID;
340 }
341 dimm->rev = reg8;
342 printram(" Revision : %01x.%01x\n", dimm->rev >> 4, dimm->rev & 0xf);
343
344 reg8 = spd[2];
345 printram(" Type : 0x%02x\n", reg8);
346 if (reg8 != 0x08) {
Elyes HAOUAS83bc4082022-02-04 19:34:53 +0100347 printk(BIOS_ERR, "Unsupported SPD type %x\n", reg8);
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100348 dimm->dram_type = SPD_MEMORY_TYPE_UNDEFINED;
349 return SPD_STATUS_INVALID;
350 }
351 dimm->dram_type = SPD_MEMORY_TYPE_SDRAM_DDR2;
352
353 dimm->row_bits = spd[3];
354 printram(" Rows : %u\n", dimm->row_bits);
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200355 if ((dimm->row_bits > 31) || ((dimm->row_bits > 15) && (dimm->rev < 0x13))) {
356 printk(BIOS_WARNING, "SPD decode: invalid number of memory rows\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100357 ret = SPD_STATUS_INVALID_FIELD;
358 }
359
360 dimm->col_bits = spd[4];
361 printram(" Columns : %u\n", dimm->col_bits);
362 if (dimm->col_bits > 15) {
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200363 printk(BIOS_WARNING, "SPD decode: invalid number of memory columns\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100364 ret = SPD_STATUS_INVALID_FIELD;
365 }
366
367 dimm->ranks = (spd[5] & 0x7) + 1;
368 printram(" Ranks : %u\n", dimm->ranks);
369
370 dimm->mod_width = spd[6];
371 printram(" Module data width : x%u\n", dimm->mod_width);
372 if (!dimm->mod_width) {
Arthur Heymans2785c112017-09-10 20:57:37 +0200373 printk(BIOS_WARNING, "SPD decode: invalid module data width\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100374 ret = SPD_STATUS_INVALID_FIELD;
375 }
376
377 dimm->width = spd[13];
378 printram(" SDRAM width : x%u\n", dimm->width);
379 if (!dimm->width) {
Arthur Heymans2785c112017-09-10 20:57:37 +0200380 printk(BIOS_WARNING, "SPD decode: invalid SDRAM width\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100381 ret = SPD_STATUS_INVALID_FIELD;
382 }
383
384 dimm->banks = spd[17];
385 printram(" Banks : %u\n", dimm->banks);
386 if (!dimm->banks) {
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200387 printk(BIOS_WARNING, "SPD decode: invalid module banks count\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100388 ret = SPD_STATUS_INVALID_FIELD;
389 }
390
391 switch (spd[8]) {
392 case 0:
393 dimm->flags.operable_5_00V = 1;
394 printram(" Voltage : 5.0V\n");
395 break;
396 case 1:
397 dimm->flags.operable_3_33V = 1;
398 printram(" Voltage : 3.3V\n");
399 break;
400 case 2:
401 dimm->flags.operable_1_50V = 1;
402 printram(" Voltage : 1.5V\n");
403 break;
404 case 3:
405 dimm->flags.operable_3_33V = 1;
406 printram(" Voltage : 3.3V\n");
407 break;
408 case 4:
409 dimm->flags.operable_2_50V = 1;
410 printram(" Voltage : 2.5V\n");
411 break;
412 case 5:
413 dimm->flags.operable_1_80V = 1;
414 printram(" Voltage : 1.8V\n");
415 break;
416 default:
Arthur Heymans2785c112017-09-10 20:57:37 +0200417 printk(BIOS_WARNING, "SPD decode: unknown voltage level.\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100418 ret = SPD_STATUS_INVALID_FIELD;
419 }
420
421 dimm->cas_supported = spd[18];
422 if ((dimm->cas_supported & 0x3) || !dimm->cas_supported) {
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200423 printk(BIOS_WARNING, "SPD decode: invalid CAS support advertised.\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100424 ret = SPD_STATUS_INVALID_FIELD;
425 }
426 printram(" Supported CAS mask : 0x%x\n", dimm->cas_supported);
427
428 if ((dimm->rev < 0x13) && (dimm->cas_supported & 0x80)) {
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200429 printk(BIOS_WARNING, "SPD decode: invalid CAS support advertised.\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100430 ret = SPD_STATUS_INVALID_FIELD;
431 }
432 if ((dimm->rev < 0x12) && (dimm->cas_supported & 0x40)) {
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200433 printk(BIOS_WARNING, "SPD decode: invalid CAS support advertised.\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100434 ret = SPD_STATUS_INVALID_FIELD;
435 }
436
437 /* CL=X */
438 cl = spd_get_msbs(dimm->cas_supported);
439
440 /* SDRAM Cycle time at Maximum Supported CAS Latency (CL), CL=X */
Arthur Heymans2785c112017-09-10 20:57:37 +0200441 if (spd_decode_tck_time(&dimm->cycle_time[cl], spd[9]) != CB_SUCCESS) {
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200442 printk(BIOS_WARNING, "SPD decode: invalid min tCL for CAS%d\n", cl);
Arthur Heymans2785c112017-09-10 20:57:37 +0200443 ret = SPD_STATUS_INVALID_FIELD;
444 }
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100445 /* SDRAM Access from Clock */
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200446 if (spd_decode_bcd_time(&dimm->access_time[cl], spd[10]) != CB_SUCCESS) {
447 printk(BIOS_WARNING, "SPD decode: invalid min tAC for CAS%d\n", cl);
Arthur Heymans2785c112017-09-10 20:57:37 +0200448 ret = SPD_STATUS_INVALID_FIELD;
449 }
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100450
451 if (dimm->cas_supported & (1 << (cl - 1))) {
452 /* Minimum Clock Cycle at CLX-1 */
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200453 if (spd_decode_tck_time(&dimm->cycle_time[cl - 1], spd[23]) != CB_SUCCESS) {
454 printk(BIOS_WARNING, "SPD decode: invalid min tCL for CAS%d\n", cl - 1);
Arthur Heymans2785c112017-09-10 20:57:37 +0200455 ret = SPD_STATUS_INVALID_FIELD;
456 }
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100457 /* Maximum Data Access Time (tAC) from Clock at CLX-1 */
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200458 if (spd_decode_bcd_time(&dimm->access_time[cl - 1], spd[24]) != CB_SUCCESS) {
459 printk(BIOS_WARNING, "SPD decode: invalid min tAC for CAS%d\n", cl - 1);
Arthur Heymans2785c112017-09-10 20:57:37 +0200460 ret = SPD_STATUS_INVALID_FIELD;
461 }
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100462 }
463 if (dimm->cas_supported & (1 << (cl - 2))) {
464 /* Minimum Clock Cycle at CLX-2 */
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200465 if (spd_decode_tck_time(&dimm->cycle_time[cl - 2], spd[25]) != CB_SUCCESS) {
466 printk(BIOS_WARNING, "SPD decode: invalid min tCL for CAS%d\n", cl - 2);
Arthur Heymans2785c112017-09-10 20:57:37 +0200467 ret = SPD_STATUS_INVALID_FIELD;
468 }
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100469 /* Maximum Data Access Time (tAC) from Clock at CLX-2 */
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200470 if (spd_decode_bcd_time(&dimm->access_time[cl - 2], spd[26]) != CB_SUCCESS) {
471 printk(BIOS_WARNING, "SPD decode: invalid min tAC for CAS%d\n", cl - 2);
Arthur Heymans2785c112017-09-10 20:57:37 +0200472 ret = SPD_STATUS_INVALID_FIELD;
473 }
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100474 }
475
476 reg8 = (spd[31] >> 5) | (spd[31] << 3);
477 if (!reg8) {
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200478 printk(BIOS_WARNING, "SPD decode: invalid rank density.\n");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100479 ret = SPD_STATUS_INVALID_FIELD;
480 }
481
482 /* Rank density */
483 dimm->ranksize_mb = 128 * reg8;
484 /* Module density */
485 dimm->size_mb = dimm->ranksize_mb * dimm->ranks;
486 if (dimm->size_mb < 1024)
487 printram(" Capacity : %u MB\n", dimm->size_mb);
488 else
489 printram(" Capacity : %u GB\n", dimm->size_mb >> 10);
490
491 /* SDRAM Maximum Cycle Time (tCKmax) */
Arthur Heymans2785c112017-09-10 20:57:37 +0200492 if (spd_decode_bcd_time(&dimm->tCK, spd[43]) != CB_SUCCESS) {
493 printk(BIOS_WARNING, "SPD decode: invalid Max tCK\n");
494 ret = SPD_STATUS_INVALID_FIELD;
495 }
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100496 /* Minimum Write Recovery Time (tWRmin) */
497 dimm->tWR = spd_decode_quarter_time(spd[36]);
498 /* Minimum RAS# to CAS# Delay Time (tRCDmin) */
499 dimm->tRCD = spd_decode_quarter_time(spd[29]);
500 /* Minimum Row Active to Row Active Delay Time (tRRDmin) */
501 dimm->tRRD = spd_decode_quarter_time(spd[28]);
502 /* Minimum Row Precharge Delay Time (tRPmin) */
503 dimm->tRP = spd_decode_quarter_time(spd[27]);
504 /* Minimum Active to Precharge Delay Time (tRASmin) */
505 dimm->tRAS = spd[30] << 8;
506 /* Minimum Active to Active/Refresh Delay Time (tRCmin) */
507 /* Minimum Refresh Recovery Delay Time (tRFCmin) */
508 spd_decode_tRCtRFC_time(&spd[40], &dimm->tRC, &dimm->tRFC);
509 /* Minimum Internal Write to Read Command Delay Time (tWTRmin) */
510 dimm->tWTR = spd_decode_quarter_time(spd[37]);
511 /* Minimum Internal Read to Precharge Command Delay Time (tRTPmin) */
512 dimm->tRTP = spd_decode_quarter_time(spd[38]);
513 /* Data Input Setup Time Before Strobe */
Arthur Heymans2785c112017-09-10 20:57:37 +0200514 if (spd_decode_bcd_time(&dimm->tDS, spd[34]) != CB_SUCCESS) {
515 printk(BIOS_WARNING, "SPD decode: invalid tDS\n");
516 ret = SPD_STATUS_INVALID_FIELD;
517 }
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100518 /* Data Input Hold Time After Strobe */
Arthur Heymans2785c112017-09-10 20:57:37 +0200519 if (spd_decode_bcd_time(&dimm->tDH, spd[35]) != CB_SUCCESS) {
520 printk(BIOS_WARNING, "SPD decode: invalid tDH\n");
521 ret = SPD_STATUS_INVALID_FIELD;
522 }
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100523 /* SDRAM Device DQS-DQ Skew for DQS and associated DQ signals */
524 dimm->tDQSQ = (spd[44] << 8) / 100;
525 /* SDRAM Device Maximum Read Data Hold Skew Factor */
526 dimm->tQHS = (spd[45] << 8) / 100;
527 /* PLL Relock Time in us */
528 dimm->tPLL = spd[46] << 8;
529 /* Refresh rate in us */
Arthur Heymans2785c112017-09-10 20:57:37 +0200530 if (spd_decode_tRR_time(&dimm->tRR, spd[12]) != CB_SUCCESS)
531 ret = SPD_STATUS_INVALID_FIELD;
Arthur Heymans7eb01572017-09-21 08:28:23 +0200532 dimm->flags.self_refresh = (spd[12] >> 7) & 1;
533 printram("The assembly supports self refresh: %s\n",
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200534 dimm->flags.self_refresh ? "true" : "false");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100535
536 /* Number of PLLs on DIMM */
537 if (dimm->rev >= 0x11)
538 dimm->plls = (spd[21] >> 2) & 0x3;
539
540 /* SDRAM Thermal and Refresh Options */
541 printram(" General features :");
542 if ((dimm->rev >= 0x12) && (spd[22] & 0x04)) {
543 dimm->flags.pasr = 1;
544 printram(" PASR");
545 }
546 if ((dimm->rev >= 0x12) && (spd[22] & 0x02)) {
547 dimm->flags.terminate_50ohms = 1;
548 printram(" 50Ohm");
549 }
550 if (spd[22] & 0x01) {
551 dimm->flags.weak_driver = 1;
552 printram(" WEAK_DRIVER");
553 }
554 printram("\n");
555
556 /* SDRAM Supported Burst length */
557 printram(" Burst length :");
Elyes HAOUASec193542018-03-11 18:34:53 +0100558 if (spd[16] & 0x08) {
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100559 dimm->flags.bl8 = 1;
560 printram(" BL8");
561 }
Elyes HAOUASec193542018-03-11 18:34:53 +0100562 if (spd[16] & 0x04) {
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100563 dimm->flags.bl4 = 1;
564 printram(" BL4");
565 }
566 printram("\n");
567
Arthur Heymansfc31e442018-02-12 15:12:34 +0100568 dimm->dimm_type = spd[20] & SPD_DDR2_DIMM_TYPE_MASK;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100569 printram(" Dimm type : %x\n", dimm->dimm_type);
570
571 dimm->flags.is_ecc = !!(spd[11] & 0x3);
572 printram(" ECC support : %x\n", dimm->flags.is_ecc);
573
574 dimm->flags.stacked = !!(spd[5] & 0x10);
Elyes Haouasc705ecd2022-05-29 14:58:00 +0200575 printram(" Package : %s\n", dimm->flags.stacked ? "stack" : "planar");
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100576
577 if (spd_size > 71) {
578 memcpy(&dimm->manufacturer_id, &spd[64], 4);
579 printram(" Manufacturer ID : %x\n", dimm->manufacturer_id);
580 }
581
582 if (spd_size > 90) {
583 dimm->part_number[16] = 0;
584 memcpy(dimm->part_number, &spd[73], 16);
585 printram(" Part number : %s\n", dimm->part_number);
586 }
587
588 if (spd_size > 94) {
589 dimm->year = spd[93] + 2000;
590 dimm->weeks = spd[94];
591 printram(" Date : %d week %d\n", dimm->year, dimm->weeks);
592 }
593
594 if (spd_size > 98) {
595 memcpy(&dimm->serial, &spd[95], 4);
596 printram(" Serial number : 0x%08x\n", dimm->serial);
597 }
598 return ret;
599}
600
601/*
602 * The information printed below has a more informational character, and is not
603 * necessarily tied in to RAM init debugging. Hence, we stop using printram(),
604 * and use the standard printk()'s below.
605 */
606
607static void print_ns(const char *msg, u32 val)
608{
609 u32 mant, fp;
610 mant = val / 256;
611 fp = (val % 256) * 1000 / 256;
612
613 printk(BIOS_INFO, "%s%3u.%.3u ns\n", msg, mant, fp);
614}
615
616static void print_us(const char *msg, u32 val)
617{
618 u32 mant, fp;
619 mant = val / 256;
620 fp = (val % 256) * 1000 / 256;
621
622 printk(BIOS_INFO, "%s%3u.%.3u us\n", msg, mant, fp);
623}
624
625/**
626* \brief Print the info in DIMM
627*
Martin Rothf48acbd2020-07-24 12:24:27 -0600628* Print info about the DIMM. Useful to use when CONFIG(DEBUG_RAM_SETUP) is
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100629* selected, or for a purely informative output.
630*
631* @param dimm pointer to already decoded @ref dimm_attr structure
632*/
Arthur Heymansfc31e442018-02-12 15:12:34 +0100633void dram_print_spd_ddr2(const struct dimm_attr_ddr2_st *dimm)
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100634{
635 char buf[32];
636 int i;
637
638 printk(BIOS_INFO, " Row addr bits : %u\n", dimm->row_bits);
639 printk(BIOS_INFO, " Column addr bits : %u\n", dimm->col_bits);
640 printk(BIOS_INFO, " Number of ranks : %u\n", dimm->ranks);
641 printk(BIOS_INFO, " DIMM Capacity : %u MB\n", dimm->size_mb);
642 printk(BIOS_INFO, " Width : x%u\n", dimm->width);
643 printk(BIOS_INFO, " Banks : %u\n", dimm->banks);
644
645 /* CAS Latencies Supported */
646 printk(BIOS_INFO, " CAS latencies :");
647 for (i = 2; i < 8; i++) {
648 if (dimm->cas_supported & (1 << i))
649 printk(BIOS_INFO, " %u", i);
650 }
651 printk(BIOS_INFO, "\n");
652
653 for (i = 2; i < 8; i++) {
654 if (!(dimm->cas_supported & (1 << i)))
655 continue;
656
657 strcpy(buf, " tCK at CLx : ");
658 /* Simple snprintf replacement */
659 buf[11] = '0' + i;
660 print_ns(buf, dimm->cycle_time[i]);
661
662 strcpy(buf, " tAC at CLx : ");
663 /* Simple snprintf replacement */
664 buf[11] = '0' + i;
665 print_ns(buf, dimm->access_time[i]);
666 }
667 print_ns(" tCKmax : ", dimm->tCK);
668 print_ns(" tWRmin : ", dimm->tWR);
669 print_ns(" tRCDmin : ", dimm->tRCD);
670 print_ns(" tRRDmin : ", dimm->tRRD);
671 print_ns(" tRPmin : ", dimm->tRP);
672 print_ns(" tRASmin : ", dimm->tRAS);
673 print_ns(" tRCmin : ", dimm->tRC);
674 print_ns(" tRFCmin : ", dimm->tRFC);
675 print_ns(" tWTRmin : ", dimm->tWTR);
676 print_ns(" tRTPmin : ", dimm->tRTP);
677 print_ns(" tDS : ", dimm->tDS);
678 print_ns(" tDH : ", dimm->tDH);
679 print_ns(" tDQSQmax : ", dimm->tDQSQ);
680 print_ns(" tQHSmax : ", dimm->tQHS);
681 print_us(" tPLL : ", dimm->tPLL);
682 print_us(" tRR : ", dimm->tRR);
683}
Arthur Heymans3397aa12017-03-01 20:10:55 +0100684
685void normalize_tck(u32 *tclk)
686{
687 if (*tclk <= TCK_800MHZ) {
688 *tclk = TCK_800MHZ;
689 } else if (*tclk <= TCK_666MHZ) {
690 *tclk = TCK_666MHZ;
691 } else if (*tclk <= TCK_533MHZ) {
692 *tclk = TCK_533MHZ;
693 } else if (*tclk <= TCK_400MHZ) {
694 *tclk = TCK_400MHZ;
695 } else if (*tclk <= TCK_333MHZ) {
696 *tclk = TCK_333MHZ;
697 } else if (*tclk <= TCK_266MHZ) {
698 *tclk = TCK_266MHZ;
699 } else if (*tclk <= TCK_200MHZ) {
700 *tclk = TCK_200MHZ;
701 } else {
702 *tclk = 0;
703 printk(BIOS_ERR, "Too slow common tCLK found\n");
704 }
705}