1 /***********************license start***********************************
2 * Copyright (c) 2003-2017 Cavium Inc. ([email protected]). All rights
3 * reserved.
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * * Neither the name of Cavium Inc. nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
21 * permission.
22 *
23 * This Software, including technical data, may be subject to U.S. export
24 * control laws, including the U.S. Export Administration Act and its
25 * associated regulations, and may be subject to export or import
26 * regulations in other countries.
27 *
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
31 * TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
32 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
33 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
34 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
35 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
36 * QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
37 * ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
39 #include <bdk.h>
40 #include "dram-internal.h"
41
42 #include <bdk-minimal.h>
43 #include <libbdk-arch/bdk-warn.h>
44 #include <libbdk-hal/bdk-config.h>
45 #include <libbdk-hal/bdk-twsi.h>
46 #include <assert.h>
47 #include <ctype.h>
48 #include <stdlib.h>
49 #include <string.h>
50
51 /**
52 * Read the entire contents of a DIMM SPD and store it in the device tree. The
53 * current DRAM config is also updated, so future SPD accesses used the cached
54 * copy.
55 *
56 * @param node Node the DRAM config is for
57 * @param cfg Current DRAM config. Updated with SPD data
58 * @param lmc LMC to read DIMM for
59 * @param dimm DIMM slot for SPD to read
60 *
61 * @return Zero on success, negative on failure
62 */
63 static uint8_t spd_bufs[4 * 256]; /* FIXME(dhendrix): storage for SPD buffers, assume DDR4 */
read_entire_spd(bdk_node_t node,dram_config_t * cfg,int lmc,int dimm)64 int read_entire_spd(bdk_node_t node, dram_config_t *cfg, int lmc, int dimm)
65 {
66 /* FIXME(dhendrix): hack to get around using allocated mem */
67 assert(dimm < 4);
68
69 /* If pointer to data is provided, use it, otherwise read from SPD over twsi */
70 if (cfg->config[lmc].dimm_config_table[dimm].spd_ptr)
71 return 0;
72 if (!cfg->config[lmc].dimm_config_table[dimm].spd_addr)
73 return -1;
74
75 /* Figure out how to access the SPD */
76 int spd_addr = cfg->config[lmc].dimm_config_table[dimm].spd_addr;
77 int bus = spd_addr >> 12;
78 int address = spd_addr & 0x7f;
79
80 /* Figure out the size we will read */
81 int64_t dev_type = bdk_twsix_read_ia(node, bus, address, DDR4_SPD_KEY_BYTE_DEVICE_TYPE, 1, 1);
82 if (dev_type < 0)
83 return -1; /* No DIMM */
84 // FIXME: prudolph: Nobody needs 512 byte SPDs...
85 //int spd_size = (dev_type == 0x0c) ? 512 : 256;
86 int spd_size = 256;
87
88 /*
89 * FIXME: Assume DIMM doesn't support
90 * 'Hybrid Module Extended Function Parameters' aka only 256 Byte SPD,
91 * as the code below is broken ...
92 */
93 assert(spd_size == 256);
94 uint8_t *spd_buf = &spd_bufs[dimm * 256];
95 uint32_t *ptr = (uint32_t *)spd_buf;
96
97 for (int bank = 0; bank < (spd_size >> 8); bank++)
98 {
99 /* this should only happen for DDR4, which has a second bank of 256 bytes */
100 if (bank)
101 bdk_twsix_write_ia(node, bus, 0x36 | bank, 0, 2, 1, 0);
102 int bank_size = 256;
103 for (int i = 0; i < bank_size; i += 4)
104 {
105 int64_t data = bdk_twsix_read_ia(node, bus, address, i, 4, 1);
106 if (data < 0)
107 {
108 bdk_error("Failed to read SPD data at 0x%x\n", i + (bank << 8));
109 /* Restore the bank to zero */
110 if (bank)
111 bdk_twsix_write_ia(node, bus, 0x36 | 0, 0, 2, 1, 0);
112 return -1;
113 }
114 else
115 *ptr++ = bdk_be32_to_cpu(data);
116 }
117 /* Restore the bank to zero */
118 if (bank)
119 bdk_twsix_write_ia(node, bus, 0x36 | 0, 0, 2, 1, 0);
120 }
121
122 /* Store the SPD in the device tree */
123 /* FIXME(dhendrix): No need for this? cfg gets updated, so the caller
124 * (libdram_config()) has what it needs. */
125 // bdk_config_set_blob(spd_size, spd_buf, BDK_CONFIG_DDR_SPD_DATA, dimm, lmc, node);
126 cfg->config[lmc].dimm_config_table[dimm].spd_ptr = (void*)spd_buf;
127
128 return 0;
129 }
130
131 /* Read an DIMM SPD value, either using TWSI to read it from the DIMM, or
132 * from a provided array.
133 */
read_spd(bdk_node_t node,const dimm_config_t * dimm_config,int spd_field)134 int read_spd(bdk_node_t node, const dimm_config_t *dimm_config, int spd_field)
135 {
136 /* If pointer to data is provided, use it, otherwise read from SPD over twsi */
137 if (dimm_config->spd_ptr)
138 return dimm_config->spd_ptr[spd_field];
139 else if (dimm_config->spd_addr)
140 {
141 int data;
142 int bus = dimm_config->spd_addr >> 12;
143 int address = dimm_config->spd_addr & 0x7f;
144
145 /* this should only happen for DDR4, which has a second bank of 256 bytes */
146 int bank = (spd_field >> 8) & 1;
147 if (bank) {
148 bdk_twsix_write_ia(node, bus, 0x36 | bank, 0, 2, 1, 0);
149 spd_field %= 256;
150 }
151
152 data = bdk_twsix_read_ia(node, bus, address, spd_field, 1, 1);
153
154 /* Restore the bank to zero */
155 if (bank) {
156 bdk_twsix_write_ia(node, bus, 0x36 | 0, 0, 2, 1, 0);
157 }
158
159 return data;
160 }
161 else
162 return -1;
163 }
164
ddr3_crc16(uint8_t * ptr,int count)165 static uint16_t ddr3_crc16(uint8_t *ptr, int count)
166 {
167 /* From DDR3 spd specification */
168 int crc, i;
169 crc = 0;
170 while (--count >= 0)
171 {
172 crc = crc ^ (int)*ptr++ << 8;
173 for (i = 0; i < 8; ++i)
174 if (crc & 0x8000)
175 crc = crc << 1 ^ 0x1021;
176 else
177 crc = crc << 1;
178 }
179 return crc & 0xFFFF;
180 }
181
validate_spd_checksum_ddr3(bdk_node_t node,int twsi_addr,int silent)182 static int validate_spd_checksum_ddr3(bdk_node_t node, int twsi_addr, int silent)
183 {
184 uint8_t spd_data[128];
185 int crc_bytes = 126;
186 uint16_t crc_comp;
187 int i;
188 int rv;
189 int ret = 1;
190 for (i = 0; i < 128; i++)
191 {
192 rv = bdk_twsix_read_ia(node, twsi_addr >> 12, twsi_addr & 0x7f, i, 1, 1);
193 if (rv < 0)
194 return 0; /* TWSI read error */
195 spd_data[i] = (uint8_t)rv;
196 }
197 /* Check byte 0 to see how many bytes checksum is over */
198 if (spd_data[0] & 0x80)
199 crc_bytes = 117;
200
201 crc_comp = ddr3_crc16(spd_data, crc_bytes);
202
203 if (spd_data[DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_LOWER_NIBBLE] != (crc_comp & 0xff) ||
204 spd_data[DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_UPPER_NIBBLE] != (crc_comp >> 8))
205 {
206 if (!silent) {
207 printf("DDR3 SPD CRC error, spd addr: 0x%x, calculated crc: 0x%04x, read crc: 0x%02x%02x\n",
208 twsi_addr, crc_comp,
209 spd_data[DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_UPPER_NIBBLE],
210 spd_data[DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_LOWER_NIBBLE]);
211 }
212 ret = 0;
213 }
214 return ret;
215 }
216
validate_spd_checksum(bdk_node_t node,int twsi_addr,int silent)217 static int validate_spd_checksum(bdk_node_t node, int twsi_addr, int silent)
218 {
219 int rv;
220
221 debug_print("Validating DIMM at address 0x%x\n", twsi_addr);
222
223 if (!twsi_addr) return 1; /* return OK if we are not doing real DIMMs */
224
225 /* Look up module type to determine if DDR3 or DDR4 */
226 rv = bdk_twsix_read_ia(node, twsi_addr >> 12, twsi_addr & 0x7f, 2, 1, 1);
227
228 if (rv >= 0xB && rv <= 0xC) /* this is DDR3 or DDR4, do same */
229 return validate_spd_checksum_ddr3(node, twsi_addr, silent);
230
231 if (!silent)
232 printf("Unrecognized DIMM type: 0x%x at spd address: 0x%x\n",
233 rv, twsi_addr);
234
235 return 0;
236 }
237
238
validate_dimm(bdk_node_t node,const dimm_config_t * dimm_config)239 int validate_dimm(bdk_node_t node, const dimm_config_t *dimm_config)
240 {
241 int spd_addr;
242
243 spd_addr = dimm_config->spd_addr;
244
245 debug_print("Validating dimm spd addr: 0x%02x spd ptr: %x\n",
246 spd_addr, dimm_config->spd_ptr);
247
248 // if the slot is not possible
249 if (!spd_addr && !dimm_config->spd_ptr)
250 return -1;
251
252 {
253 int val0, val1;
254 int ddr_type = get_ddr_type(node, dimm_config);
255
256 switch (ddr_type)
257 {
258 case DDR3_DRAM: /* DDR3 */
259 case DDR4_DRAM: /* DDR4 */
260
261 debug_print("Validating DDR%d DIMM\n", ((dimm_type >> 2) & 3) + 1);
262
263 #define DENSITY_BANKS DDR4_SPD_DENSITY_BANKS // same for DDR3 and DDR4
264 #define ROW_COL_BITS DDR4_SPD_ADDRESSING_ROW_COL_BITS // same for DDR3 and DDR4
265
266 val0 = read_spd(node, dimm_config, DENSITY_BANKS);
267 val1 = read_spd(node, dimm_config, ROW_COL_BITS);
268 if (val0 < 0 && val1 < 0) {
269 debug_print("Error reading SPD for DIMM\n");
270 return 0; /* Failed to read dimm */
271 }
272 if (val0 == 0xff && val1 == 0xff) {
273 ddr_print("Blank or unreadable SPD for DIMM\n");
274 return 0; /* Blank SPD or otherwise unreadable device */
275 }
276
277 /* Don't treat bad checksums as fatal. */
278 validate_spd_checksum(node, spd_addr, 0);
279 break;
280
281 case 0x00: /* Terminator detected. Fail silently. */
282 return 0;
283
284 default:
285 debug_print("Unknown DIMM type 0x%x for DIMM @ 0x%x\n",
286 dimm_type, dimm_config->spd_addr);
287 return 0; /* Failed to read dimm */
288 }
289 }
290
291 return 1;
292 }
293
get_dimm_part_number(char * buffer,bdk_node_t node,const dimm_config_t * dimm_config,int ddr_type)294 int get_dimm_part_number(char *buffer, bdk_node_t node,
295 const dimm_config_t *dimm_config,
296 int ddr_type)
297 {
298 int i;
299 int c;
300 int skipping = 1;
301 int strlen = 0;
302
303 #define PART_LIMIT(t) (((t) == DDR4_DRAM) ? 19 : 18)
304 #define PART_NUMBER(t) (((t) == DDR4_DRAM) ? DDR4_SPD_MODULE_PART_NUMBER : DDR3_SPD_MODULE_PART_NUMBER)
305
306 int limit = PART_LIMIT(ddr_type);
307 int offset = PART_NUMBER(ddr_type);
308
309 for (i = 0; i < limit; ++i) {
310
311 c = (read_spd(node, dimm_config, offset+i) & 0xff);
312 if (c == 0) // any null, we are done
313 break;
314
315 /* Skip leading spaces. */
316 if (skipping) {
317 if (isspace(c))
318 continue;
319 else
320 skipping = 0;
321 }
322
323 /* Put non-null non-leading-space-skipped char into buffer */
324 buffer[strlen] = c;
325 ++strlen;
326 }
327
328 if (strlen > 0) {
329 i = strlen - 1; // last char put into buf
330 while (i >= 0 && isspace((int)buffer[i])) { // still in buf and a space
331 --i;
332 --strlen;
333 }
334 }
335 buffer[strlen] = 0; /* Insure that the string is terminated */
336
337 return strlen;
338 }
339
get_dimm_serial_number(bdk_node_t node,const dimm_config_t * dimm_config,int ddr_type)340 uint32_t get_dimm_serial_number(bdk_node_t node, const dimm_config_t *dimm_config, int ddr_type)
341 {
342 uint32_t serial_number = 0;
343 int offset;
344
345 #define SERIAL_NUMBER(t) (((t) == DDR4_DRAM) ? DDR4_SPD_MODULE_SERIAL_NUMBER : DDR3_SPD_MODULE_SERIAL_NUMBER)
346
347 offset = SERIAL_NUMBER(ddr_type);
348
349 for (int i = 0, j = 24; i < 4; ++i, j -= 8) {
350 serial_number |= ((read_spd(node, dimm_config, offset + i) & 0xff) << j);
351 }
352
353 return serial_number;
354 }
355
get_dimm_checksum(bdk_node_t node,const dimm_config_t * dimm_config,int ddr_type)356 static uint32_t get_dimm_checksum(bdk_node_t node, const dimm_config_t *dimm_config, int ddr_type)
357 {
358 uint32_t spd_chksum;
359
360 #define LOWER_NIBBLE(t) (((t) == DDR4_DRAM) ? DDR4_SPD_CYCLICAL_REDUNDANCY_CODE_LOWER_NIBBLE : DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_LOWER_NIBBLE)
361 #define UPPER_NIBBLE(t) (((t) == DDR4_DRAM) ? DDR4_SPD_CYCLICAL_REDUNDANCY_CODE_UPPER_NIBBLE : DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_UPPER_NIBBLE)
362
363 spd_chksum = 0xff & read_spd(node, dimm_config, LOWER_NIBBLE(ddr_type));
364 spd_chksum |= ((0xff & read_spd(node, dimm_config, UPPER_NIBBLE(ddr_type))) << 8);
365
366 return spd_chksum;
367 }
368
369 static
report_common_dimm(bdk_node_t node,const dimm_config_t * dimm_config,int dimm,const char ** dimm_types,int ddr_type,const char * volt_str,int ddr_interface_num,int num_ranks,int dram_width,int dimm_size_mb)370 void report_common_dimm(bdk_node_t node, const dimm_config_t *dimm_config, int dimm,
371 const char **dimm_types, int ddr_type, const char *volt_str,
372 int ddr_interface_num, int num_ranks, int dram_width, int dimm_size_mb)
373 {
374 int spd_ecc;
375 unsigned spd_module_type;
376 uint32_t serial_number;
377 char part_number[21]; /* 20 bytes plus string terminator is big enough for either */
378 const char *sn_str;
379
380 spd_module_type = get_dimm_module_type(node, dimm_config, ddr_type);
381 spd_ecc = get_dimm_ecc(node, dimm_config, ddr_type);
382
383 (void) get_dimm_part_number(part_number, node, dimm_config, ddr_type);
384
385 serial_number = get_dimm_serial_number(node, dimm_config, ddr_type);
386 if ((serial_number != 0) && (serial_number != 0xffffffff)) {
387 sn_str = "s/n";
388 } else {
389 serial_number = get_dimm_checksum(node, dimm_config, ddr_type);
390 sn_str = "chksum";
391 }
392
393 // FIXME: add output of DIMM rank/width, as in: 2Rx4, 1Rx8, etc
394 printf("N%d.LMC%d.DIMM%d: %d MB, DDR%d %s %dRx%d %s, p/n: %s, %s: %u, %s\n",
395 node, ddr_interface_num, dimm, dimm_size_mb, ddr_type,
396 dimm_types[spd_module_type], num_ranks, dram_width,
397 (spd_ecc ? "ECC" : "non-ECC"), part_number,
398 sn_str, serial_number, volt_str);
399 }
400
401 const char *ddr3_dimm_types[16] = {
402 /* 0000 */ "Undefined",
403 /* 0001 */ "RDIMM",
404 /* 0010 */ "UDIMM",
405 /* 0011 */ "SO-DIMM",
406 /* 0100 */ "Micro-DIMM",
407 /* 0101 */ "Mini-RDIMM",
408 /* 0110 */ "Mini-UDIMM",
409 /* 0111 */ "Mini-CDIMM",
410 /* 1000 */ "72b-SO-UDIMM",
411 /* 1001 */ "72b-SO-RDIMM",
412 /* 1010 */ "72b-SO-CDIMM",
413 /* 1011 */ "LRDIMM",
414 /* 1100 */ "16b-SO-DIMM",
415 /* 1101 */ "32b-SO-DIMM",
416 /* 1110 */ "Reserved",
417 /* 1111 */ "Reserved"
418 };
419
420 static
report_ddr3_dimm(bdk_node_t node,const dimm_config_t * dimm_config,int dimm,int ddr_interface_num,int num_ranks,int dram_width,int dimm_size_mb)421 void report_ddr3_dimm(bdk_node_t node, const dimm_config_t *dimm_config,
422 int dimm, int ddr_interface_num, int num_ranks,
423 int dram_width, int dimm_size_mb)
424 {
425 int spd_voltage;
426 const char *volt_str = "unknown voltage";
427
428 spd_voltage = read_spd(node, dimm_config, DDR3_SPD_NOMINAL_VOLTAGE);
429 if ((spd_voltage == 0) || (spd_voltage & 3))
430 volt_str = "1.5V";
431 if (spd_voltage & 2)
432 volt_str = "1.35V";
433 if (spd_voltage & 4)
434 volt_str = "1.2xV";
435
436 report_common_dimm(node, dimm_config, dimm, ddr3_dimm_types,
437 DDR3_DRAM, volt_str, ddr_interface_num,
438 num_ranks, dram_width, dimm_size_mb);
439 }
440
441 const char *ddr4_dimm_types[16] = {
442 /* 0000 */ "Extended",
443 /* 0001 */ "RDIMM",
444 /* 0010 */ "UDIMM",
445 /* 0011 */ "SO-DIMM",
446 /* 0100 */ "LRDIMM",
447 /* 0101 */ "Mini-RDIMM",
448 /* 0110 */ "Mini-UDIMM",
449 /* 0111 */ "Reserved",
450 /* 1000 */ "72b-SO-RDIMM",
451 /* 1001 */ "72b-SO-UDIMM",
452 /* 1010 */ "Reserved",
453 /* 1011 */ "Reserved",
454 /* 1100 */ "16b-SO-DIMM",
455 /* 1101 */ "32b-SO-DIMM",
456 /* 1110 */ "Reserved",
457 /* 1111 */ "Reserved"
458 };
459
460 static
report_ddr4_dimm(bdk_node_t node,const dimm_config_t * dimm_config,int dimm,int ddr_interface_num,int num_ranks,int dram_width,int dimm_size_mb)461 void report_ddr4_dimm(bdk_node_t node, const dimm_config_t *dimm_config,
462 int dimm, int ddr_interface_num, int num_ranks,
463 int dram_width, int dimm_size_mb)
464 {
465 int spd_voltage;
466 const char *volt_str = "unknown voltage";
467
468 spd_voltage = read_spd(node, dimm_config, DDR4_SPD_MODULE_NOMINAL_VOLTAGE);
469 if ((spd_voltage == 0x01) || (spd_voltage & 0x02))
470 volt_str = "1.2V";
471 if ((spd_voltage == 0x04) || (spd_voltage & 0x08))
472 volt_str = "TBD1 V";
473 if ((spd_voltage == 0x10) || (spd_voltage & 0x20))
474 volt_str = "TBD2 V";
475
476 report_common_dimm(node, dimm_config, dimm, ddr4_dimm_types,
477 DDR4_DRAM, volt_str, ddr_interface_num,
478 num_ranks, dram_width, dimm_size_mb);
479 }
480
report_dimm(bdk_node_t node,const dimm_config_t * dimm_config,int dimm,int ddr_interface_num,int num_ranks,int dram_width,int dimm_size_mb)481 void report_dimm(bdk_node_t node, const dimm_config_t *dimm_config,
482 int dimm, int ddr_interface_num, int num_ranks,
483 int dram_width, int dimm_size_mb)
484 {
485 int ddr_type;
486
487 /* ddr_type only indicates DDR4 or DDR3 */
488 ddr_type = get_ddr_type(node, dimm_config);
489
490 if (ddr_type == DDR4_DRAM)
491 report_ddr4_dimm(node, dimm_config, dimm, ddr_interface_num,
492 num_ranks, dram_width, dimm_size_mb);
493 else
494 report_ddr3_dimm(node, dimm_config, dimm, ddr_interface_num,
495 num_ranks, dram_width, dimm_size_mb);
496 }
497
498 static int
get_ddr4_spd_speed(bdk_node_t node,const dimm_config_t * dimm_config)499 get_ddr4_spd_speed(bdk_node_t node, const dimm_config_t *dimm_config)
500 {
501 int spdMTB = 125;
502 int spdFTB = 1;
503
504 int tCKAVGmin
505 = spdMTB * read_spd(node, dimm_config, DDR4_SPD_MINIMUM_CYCLE_TIME_TCKAVGMIN)
506 + spdFTB * (signed char) read_spd(node, dimm_config, DDR4_SPD_MIN_CYCLE_TIME_FINE_TCKAVGMIN);
507
508 return pretty_psecs_to_mts(tCKAVGmin);
509 }
510
511 static int
get_ddr3_spd_speed(bdk_node_t node,const dimm_config_t * dimm_config)512 get_ddr3_spd_speed(bdk_node_t node, const dimm_config_t *dimm_config)
513 {
514 int spd_mtb_dividend = 0xff & read_spd(node, dimm_config, DDR3_SPD_MEDIUM_TIMEBASE_DIVIDEND);
515 int spd_mtb_divisor = 0xff & read_spd(node, dimm_config, DDR3_SPD_MEDIUM_TIMEBASE_DIVISOR);
516 int spd_tck_min = 0xff & read_spd(node, dimm_config, DDR3_SPD_MINIMUM_CYCLE_TIME_TCKMIN);
517
518 short ftb_Dividend = read_spd(node, dimm_config, DDR3_SPD_FINE_TIMEBASE_DIVIDEND_DIVISOR) >> 4;
519 short ftb_Divisor = read_spd(node, dimm_config, DDR3_SPD_FINE_TIMEBASE_DIVIDEND_DIVISOR) & 0xf;
520
521 ftb_Divisor = (ftb_Divisor == 0) ? 1 : ftb_Divisor; /* Make sure that it is not 0 */
522
523 int mtb_psec = spd_mtb_dividend * 1000 / spd_mtb_divisor;
524 int tCKmin = mtb_psec * spd_tck_min;
525 tCKmin += ftb_Dividend *
526 (signed char) read_spd(node, dimm_config, DDR3_SPD_MINIMUM_CYCLE_TIME_FINE_TCKMIN)
527 / ftb_Divisor;
528
529 return pretty_psecs_to_mts(tCKmin);
530 }
531
532 static int
speed_bin_down(int speed)533 speed_bin_down(int speed)
534 {
535 if (speed == 2133)
536 return 1866;
537 else if (speed == 1866)
538 return 1600;
539 else
540 return speed;
541 }
542
543 int
dram_get_default_spd_speed(bdk_node_t node,const ddr_configuration_t * ddr_config)544 dram_get_default_spd_speed(bdk_node_t node, const ddr_configuration_t *ddr_config)
545 {
546 int lmc, dimm;
547 int speed, ret_speed = 0;
548 int ddr_type = get_ddr_type(node, &ddr_config[0].dimm_config_table[0]);
549 int dimm_speed[8], dimm_count = 0;
550 int dimms_per_lmc = 0;
551
552 memset (dimm_speed, 0, sizeof(dimm_speed));
553
554 for (lmc = 0; lmc < 4; lmc++) {
555 for (dimm = 0; dimm < DDR_CFG_T_MAX_DIMMS; dimm++) {
556 const dimm_config_t *dimm_config = &ddr_config[lmc].dimm_config_table[dimm];
557 if (dimm_config->spd_addr || dimm_config->spd_ptr)
558 {
559 speed = (ddr_type == DDR4_DRAM)
560 ? get_ddr4_spd_speed(node, dimm_config)
561 : get_ddr3_spd_speed(node, dimm_config);
562 printf("N%d.LMC%d.DIMM%d: SPD speed %d\n", node, lmc, dimm, speed);
563 dimm_speed[dimm_count] = speed;
564 dimm_count++;
565 if (lmc == 0)
566 dimms_per_lmc++;
567 }
568 }
569 }
570
571 // all DIMMs must be same speed
572 speed = dimm_speed[0];
573 for (dimm = 1; dimm < dimm_count; dimm++) {
574 if (dimm_speed[dimm] != speed) {
575 ret_speed = -1;
576 goto finish_up;
577 }
578 }
579
580 // if 2400 or greater, use 2133
581 if (speed >= 2400)
582 speed = 2133;
583
584 // use next speed down if 2DPC...
585 if (dimms_per_lmc > 1)
586 speed = speed_bin_down(speed);
587
588 // Update the in memory config to match the automatically calculated speed
589 bdk_config_set_int(speed, BDK_CONFIG_DDR_SPEED, node);
590
591 // do filtering for our jittery PLL
592 if (speed == 2133)
593 speed = 2100;
594 else if (speed == 1866)
595 speed = 1880;
596
597 // OK, return what we have...
598 ret_speed = mts_to_hertz(speed);
599
600 finish_up:
601 printf("N%d: Returning default SPD speed %d\n", node, ret_speed);
602 return ret_speed;
603 }
604