xref: /aosp_15_r20/external/coreboot/src/vendorcode/cavium/bdk/libdram/dram-spd.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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