1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2024 Oxide Computer Company
14 */
15
16 /*
17 * DDR3-specific SPD processing logic. For an overview of the processing design
18 * please see libjedec_spd.c.
19 */
20
21 #include <sys/sysmacros.h>
22 #include <sys/debug.h>
23 #include "libjedec_spd.h"
24
25 static const spd_value_map_t spd_ddr3_nbytes_used_map[] = {
26 { SPD_DDR3_NBYTES_USED_UNDEF, 0, true },
27 { SPD_DDR3_NBYTES_USED_128, 128, false },
28 { SPD_DDR3_NBYTES_USED_176, 176, false },
29 { SPD_DDR3_NBYTES_USED_256, 256, false },
30 };
31
32 static const spd_value_map_t spd_ddr3_nbytes_total_map[] = {
33 { SPD_DDR3_NBYTES_TOTAL_UNDEF, 0, true },
34 { SPD_DDR3_NBYTES_TOTAL_256, 256, false }
35 };
36
37 /*
38 * The macro values represent the last byte covered therefore the number of
39 * bytes is that plus one.
40 */
41 static const spd_value_map_t spd_ddr3_crc_map[] = {
42 { SPD_DDR3_NBYTES_CRC_125, 126, false },
43 { SPD_DDR3_NBYTES_CRC_116, 117, false }
44 };
45
46 static void
spd_parse_ddr3_nbytes(spd_info_t * si,uint32_t off,uint32_t len,const char * key)47 spd_parse_ddr3_nbytes(spd_info_t *si, uint32_t off, uint32_t len,
48 const char *key)
49 {
50 const uint8_t data = si->si_data[off];
51 const uint8_t used = SPD_DDR3_NBYTES_USED(data);
52 const uint8_t total = SPD_DDR3_NBYTES_TOTAL(data);
53 const uint8_t crc = SPD_DDR3_NBYTES_CRC(data);
54
55 spd_insert_map(si, SPD_KEY_NBYTES_USED, used, spd_ddr3_nbytes_used_map,
56 ARRAY_SIZE(spd_ddr3_nbytes_used_map));
57 spd_insert_map(si, SPD_KEY_NBYTES_TOTAL, total,
58 spd_ddr3_nbytes_total_map, ARRAY_SIZE(spd_ddr3_nbytes_total_map));
59
60 /*
61 * Unlike DDR5, there is no specific definition to indicate that the SPD
62 * is present or what type of device it is. There is only one standard
63 * DDR3 EEPROM, EE1002, so we note that it's here when we process this.
64 */
65 spd_upsert_flag(si, SPD_KEY_DEVS, SPD_DEVICE_SPD);
66 spd_nvl_insert_u32(si, SPD_KEY_DEV_SPD_TYPE, SPD_SPD_T_EE1002);
67
68 spd_insert_map(si, SPD_KEY_CRC_DDR3_LEN, crc, spd_ddr3_crc_map,
69 ARRAY_SIZE(spd_ddr3_crc_map));
70 }
71
72 static const spd_value_map_t spd_ddr3_mod_type_map[] = {
73 { SPD_DDR3_MOD_TYPE_TYPE_UNDEF, UINT32_MAX, true },
74 { SPD_DDR3_MOD_TYPE_TYPE_RDIMM, SPD_MOD_TYPE_RDIMM, false },
75 { SPD_DDR3_MOD_TYPE_TYPE_UDIMM, SPD_MOD_TYPE_UDIMM, false },
76 { SPD_DDR3_MOD_TYPE_TYPE_SODIMM, SPD_MOD_TYPE_SODIMM, false },
77 { SPD_DDR3_MOD_TYPE_TYPE_MICRO_DIMM, SPD_MOD_TYPE_MICRO_DIMM, false },
78 { SPD_DDR3_MOD_TYPE_TYPE_MINI_RDIMM, SPD_MOD_TYPE_MINI_RDIMM, false },
79 { SPD_DDR3_MOD_TYPE_TYPE_MINI_UDIMM, SPD_MOD_TYPE_MINI_UDIMM, false },
80 { SPD_DDR3_MOD_TYPE_TYPE_MINI_CDIMM, SPD_MOD_TYPE_MINI_CDIMM, false },
81 { SPD_DDR3_MOD_TYPE_TYPE_72b_SORDIMM, SPD_MOD_TYPE_72b_SO_RDIMM,
82 false },
83 { SPD_DDR3_MOD_TYPE_TYPE_72b_SOUDIMM, SPD_MOD_TYPE_72b_SO_UDIMM,
84 false },
85 { SPD_DDR3_MOD_TYPE_TYPE_72b_SOCDIMM, SPD_MOD_TYPE_72b_SO_CDIMM,
86 false },
87 { SPD_DDR3_MOD_TYPE_TYPE_LRDIMM, SPD_MOD_TYPE_LRDIMM, false },
88 { SPD_DDR3_MOD_TYPE_TYPE_16b_SODIMM, SPD_MOD_TYPE_16b_SO_DIMM, false },
89 { SPD_DDR3_MOD_TYPE_TYPE_32b_SODIMM, SPD_MOD_TYPE_32b_SO_DIMM, false },
90 };
91
92 static void
spd_parse_ddr3_mod_type(spd_info_t * si,uint32_t off,uint32_t len,const char * key)93 spd_parse_ddr3_mod_type(spd_info_t *si, uint32_t off, uint32_t len,
94 const char *key)
95 {
96 const uint8_t data = si->si_data[off];
97 const uint8_t type = SPD_DDR3_MOD_TYPE_TYPE(data);
98
99 spd_insert_map(si, SPD_KEY_MOD_TYPE, type, spd_ddr3_mod_type_map,
100 ARRAY_SIZE(spd_ddr3_mod_type_map));
101 }
102
103 static const spd_value_range_t spd_ddr3_nba_range = {
104 .svr_max = SPD_DDR3_DENSITY_NBA_BITS_MAX,
105 .svr_base = SPD_DDR3_DENSITY_NBA_BITS_BASE
106 };
107
108 static const spd_value_map64_t spd_ddr3_density_map[] = {
109 {SPD_DDR3_DENSITY_DENSITY_256Mb, 256ULL * 1024ULL * 1024ULL, false },
110 {SPD_DDR3_DENSITY_DENSITY_512Mb, 512ULL * 1024ULL * 1024ULL, false },
111 {SPD_DDR3_DENSITY_DENSITY_1Gb, 1ULL * 1024ULL * 1024ULL * 1024ULL,
112 false },
113 {SPD_DDR3_DENSITY_DENSITY_2Gb, 2ULL * 1024ULL * 1024ULL * 1024ULL,
114 false },
115 {SPD_DDR3_DENSITY_DENSITY_4Gb, 4ULL * 1024ULL * 1024ULL * 1024ULL,
116 false },
117 {SPD_DDR3_DENSITY_DENSITY_8Gb, 8ULL * 1024ULL * 1024ULL * 1024ULL,
118 false },
119 {SPD_DDR3_DENSITY_DENSITY_16Gb, 16ULL * 1024ULL * 1024ULL * 1024ULL,
120 false },
121 {SPD_DDR3_DENSITY_DENSITY_32Gb, 32ULL * 1024ULL * 1024ULL * 1024ULL,
122 false },
123 {SPD_DDR3_DENSITY_DENSITY_12Gb, 12ULL * 1024ULL * 1024ULL * 1024ULL,
124 false },
125 {SPD_DDR3_DENSITY_DENSITY_24Gb, 24ULL * 1024ULL * 1024ULL * 1024ULL,
126 false },
127 };
128
129 /*
130 * DDR3 does not define bank groups, hence when we insert the bank address bits
131 * we come back and set bank group bits to 0.
132 */
133 static void
spd_parse_ddr3_density(spd_info_t * si,uint32_t off,uint32_t len,const char * key)134 spd_parse_ddr3_density(spd_info_t *si, uint32_t off, uint32_t len,
135 const char *key)
136 {
137 const uint8_t data = si->si_data[off];
138 const uint8_t dens = SPD_DDR3_DENSITY_DENSITY(data);
139 const uint8_t nba = SPD_DDR3_DENSITY_NBA_BITS(data);
140
141 spd_insert_range(si, SPD_KEY_NBANK_BITS, nba, &spd_ddr3_nba_range);
142 spd_nvl_insert_u32(si, SPD_KEY_NBGRP_BITS, 0);
143 spd_insert_map64(si, SPD_KEY_DIE_SIZE, dens, spd_ddr3_density_map,
144 ARRAY_SIZE(spd_ddr3_density_map));
145 }
146
147 static const spd_value_range_t spd_ddr3_nrow_range = {
148 .svr_max = SPD_DDR3_ADDR_NROWS_MAX,
149 .svr_base = SPD_DDR3_ADDR_NROWS_BASE
150 };
151
152 static const spd_value_range_t spd_ddr3_ncol_range = {
153 .svr_max = SPD_DDR3_ADDR_NCOLS_MAX,
154 .svr_base = SPD_DDR3_ADDR_NCOLS_BASE
155 };
156
157 static void
spd_parse_ddr3_addr(spd_info_t * si,uint32_t off,uint32_t len,const char * key)158 spd_parse_ddr3_addr(spd_info_t *si, uint32_t off, uint32_t len,
159 const char *key)
160 {
161 const uint8_t data = si->si_data[off];
162 const uint8_t nrows = SPD_DDR3_ADDR_NROWS(data);
163 const uint8_t ncols = SPD_DDR3_ADDR_NCOLS(data);
164
165 spd_insert_range(si, SPD_KEY_NROW_BITS, nrows, &spd_ddr3_nrow_range);
166 spd_insert_range(si, SPD_KEY_NCOL_BITS, ncols, &spd_ddr3_ncol_range);
167 }
168
169 static void
spd_parse_ddr3_volt(spd_info_t * si,uint32_t off,uint32_t len,const char * key)170 spd_parse_ddr3_volt(spd_info_t *si, uint32_t off, uint32_t len,
171 const char *key)
172 {
173 const uint8_t data = si->si_data[off];
174 uint32_t volts[3];
175 uint_t nvolt = 0;
176
177 /*
178 * DDR3 came out with 1.5V support initially meaning a value of zero
179 * indicates that 1.5V is supported. Affirmative values came later.
180 */
181 if (SPD_DDR3_VOLT_V1P5_OPER(data) == 0) {
182 volts[nvolt] = 1500;
183 nvolt++;
184 }
185
186 if (SPD_DDR3_VOLT_V1P35_OPER(data) != 0) {
187 volts[nvolt] = 1350;
188 nvolt++;
189 }
190
191 if (SPD_DDR3_VOLT_V1P25_OPER(data) != 0) {
192 volts[nvolt] = 1250;
193 nvolt++;
194 }
195
196 if (nvolt > 0) {
197 spd_nvl_insert_u32_array(si, key, volts, nvolt);
198 }
199 }
200
201 static const spd_value_range_t spd_ddr3_width_range = {
202 .svr_base = SPD_DDR3_MOD_ORG_WIDTH_BASE,
203 .svr_max = SPD_DDR3_MOD_ORG_WIDTH_MAX,
204 .svr_exp = true
205 };
206
207 static const spd_value_map_t spd_ddr3_nranks[] = {
208 { SPD_DDR3_MOD_ORG_NRANKS_1, 1, false },
209 { SPD_DDR3_MOD_ORG_NRANKS_2, 2, false },
210 { SPD_DDR3_MOD_ORG_NRANKS_3, 3, false },
211 { SPD_DDR3_MOD_ORG_NRANKS_4, 4, false },
212 { SPD_DDR3_MOD_ORG_NRANKS_8, 8, false }
213 };
214
215 static void
spd_parse_ddr3_mod_org(spd_info_t * si,uint32_t off,uint32_t len,const char * key)216 spd_parse_ddr3_mod_org(spd_info_t *si, uint32_t off, uint32_t len,
217 const char *key)
218 {
219 const uint8_t data = si->si_data[off];
220 const uint8_t nranks = SPD_DDR4_MOD_ORG_NPKG_RANK(data);
221 const uint8_t width = SPD_DDR4_MOD_ORG_WIDTH(data);
222
223 spd_insert_range(si, SPD_KEY_DRAM_WIDTH, width, &spd_ddr3_width_range);
224 spd_insert_map(si, SPD_KEY_NRANKS, nranks, spd_ddr3_nranks,
225 ARRAY_SIZE(spd_ddr3_nranks));
226 }
227
228 static const spd_value_map_t spd_ddr3_ext_width[] = {
229 { SPD_DDR4_MOD_BUS_WIDTH_EXT_NONE, 0, false },
230 { SPD_DDR4_MOD_BUS_WIDTH_EXT_8b, 8, false }
231 };
232
233 static const spd_value_range_t spd_ddr3_pri_range = {
234 .svr_base = SPD_DDR3_BUS_WIDTH_PRI_BASE,
235 .svr_max = SPD_DDR3_BUS_WIDTH_PRI_MAX,
236 .svr_exp = true
237 };
238
239 static void
spd_parse_ddr3_bus_width(spd_info_t * si,uint32_t off,uint32_t len,const char * key)240 spd_parse_ddr3_bus_width(spd_info_t *si, uint32_t off, uint32_t len,
241 const char *key)
242 {
243 const uint8_t data = si->si_data[off];
244 const uint8_t ext = SPD_DDR3_BUS_WIDTH_EXT(data);
245 const uint8_t pri = SPD_DDR3_BUS_WIDTH_PRI(data);
246
247 /*
248 * DDR3 only has a single channel and subchanne. Record that reality
249 * here.
250 */
251 spd_nvl_insert_u32(si, SPD_KEY_NSUBCHAN, 1);
252 spd_nvl_insert_u32(si, SPD_KEY_DRAM_NCHAN, 1);
253 spd_insert_range(si, SPD_KEY_DATA_WIDTH, pri, &spd_ddr3_pri_range);
254 spd_insert_map(si, SPD_KEY_ECC_WIDTH, ext, spd_ddr3_ext_width,
255 ARRAY_SIZE(spd_ddr3_ext_width));
256 }
257
258 /*
259 * We only currently support a 1 ps FTB. The DDR3 spec has examples of 2.5ps and
260 * 5ps versions. 1p was the magic number required for DDR4 and LPDDR3-5. For now
261 * we admit we don't support processing it and will cross the bridge when it
262 * becomes important for consumers.
263 */
264 static void
spd_parse_ddr3_ftb(spd_info_t * si,uint32_t off,uint32_t len,const char * key)265 spd_parse_ddr3_ftb(spd_info_t *si, uint32_t off, uint32_t len,
266 const char *key)
267 {
268 const uint8_t data = si->si_data[off];
269
270 if (SPD_DDR3_FTB_DIVIDEND(data) != 1 ||
271 SPD_DDR3_FTB_DIVISOR(data) != 1) {
272 spd_nvl_err(si, key, SPD_ERROR_NO_XLATE, "library cannot "
273 "handle FTB value that's not 1ps, found divisor and "
274 "dividend %u/%u", SPD_DDR3_FTB_DIVISOR(data),
275 SPD_DDR3_FTB_DIVIDEND(data));
276 return;
277 }
278
279 spd_nvl_insert_u32(si, key, SPD_DDR3_FTB_PS);
280 }
281
282 /*
283 * There are two bytes that represent the divisor and dividend; however, only a
284 * value that results in 125ps is supported by the spec.
285 */
286 static void
spd_parse_ddr3_mtb(spd_info_t * si,uint32_t off,uint32_t len,const char * key)287 spd_parse_ddr3_mtb(spd_info_t *si, uint32_t off, uint32_t len,
288 const char *key)
289 {
290 const uint8_t dividend = si->si_data[off];
291 const uint8_t divisor = si->si_data[off + 1];
292
293 if (dividend != SPD_DDR3_MTB_125PS_DIVIDEND ||
294 divisor != SPD_DDR3_MTB_125PS_DIVISOR) {
295 spd_nvl_err(si, key, SPD_ERROR_NO_XLATE, "library encountered "
296 "undefined MTB value (not 125ps): found divisor and "
297 "dividend %u/%u", divisor, dividend);
298 return;
299 }
300
301 spd_nvl_insert_u32(si, key, SPD_DDR3_MTB_PS);
302 }
303
304 static void
spd_parse_ddr3_cas(spd_info_t * si,uint32_t off,uint32_t len,const char * key)305 spd_parse_ddr3_cas(spd_info_t *si, uint32_t off, uint32_t len,
306 const char *key)
307 {
308 uint32_t cas[16] = { 0 };
309 uint_t ncas = 0;
310
311 ASSERT3U(len, ==, 2);
312 for (uint32_t byte = 0; byte < len; byte++) {
313 const uint32_t data = si->si_data[off + byte];
314 uint32_t nbits = NBBY;
315
316 /*
317 * The last byte reserves the last bit.
318 */
319 if (byte == len - 1)
320 nbits--;
321
322 for (uint32_t i = 0; i < nbits; i++) {
323 if (bitx8(data, i, i) == 1) {
324 cas[ncas] = SPD_DDR3_CAS_BASE + i + NBBY * byte;
325 ncas++;
326 }
327 }
328 }
329
330 spd_nvl_insert_u32_array(si, key, cas, ncas);
331 }
332
333 /*
334 * Parse a time value that is a single number of MTB units.
335 */
336 static void
spd_parse_ddr3_mtb_time(spd_info_t * si,uint32_t off,uint32_t len,const char * key)337 spd_parse_ddr3_mtb_time(spd_info_t *si, uint32_t off, uint32_t len,
338 const char *key)
339 {
340 const uint64_t ps = (uint64_t)si->si_data[off] * SPD_DDR3_MTB_PS;
341
342 if (ps == 0) {
343 spd_nvl_err(si, key, SPD_ERROR_NO_XLATE,
344 "encountered unexpected zero time value");
345 return;
346 }
347 spd_nvl_insert_u64(si, key, ps);
348 }
349
350 /*
351 *
352 * t~RAS~ consists of the upper nibble at off and the MTB at off + 1.
353 */
354 static void
spd_parse_ddr3_tras(spd_info_t * si,uint32_t off,uint32_t len,const char * key)355 spd_parse_ddr3_tras(spd_info_t *si, uint32_t off, uint32_t len,
356 const char *key)
357 {
358 const uint8_t ras_nib = SPD_DDR3_RAS_RC_UPPER_RAS(si->si_data[off]);
359 ASSERT3U(len, ==, 2);
360
361 return (spd_parse_ddr_time(si, key, ras_nib, si->si_data[off + 1], 0));
362 }
363
364 /*
365 * t~RC~ consists of an upper 4-bit nibble at off. Its MTB is at off + 2. The
366 * FTB is at off + len - 1.
367 */
368 static void
spd_parse_ddr3_trc(spd_info_t * si,uint32_t off,uint32_t len,const char * key)369 spd_parse_ddr3_trc(spd_info_t *si, uint32_t off, uint32_t len,
370 const char *key)
371 {
372 const uint8_t rc_nib = SPD_DDR3_RAS_RC_UPPER_RC(si->si_data[off]);
373
374 return (spd_parse_ddr_time(si, key, rc_nib, si->si_data[off + 2],
375 si->si_data[off + len - 1]));
376 }
377
378 static void
spd_parse_ddr3_tfaw(spd_info_t * si,uint32_t off,uint32_t len,const char * key)379 spd_parse_ddr3_tfaw(spd_info_t *si, uint32_t off, uint32_t len,
380 const char *key)
381 {
382 const uint8_t nib = SPD_DDR3_TFAB_NIB_UPPER_TFAW(si->si_data[off]);
383 ASSERT3U(len, ==, 2);
384
385 return (spd_parse_ddr_time(si, key, nib, si->si_data[off + 1], 0));
386 }
387
388 static void
spd_parse_ddr3_opt_feat(spd_info_t * si,uint32_t off,uint32_t len,const char * key)389 spd_parse_ddr3_opt_feat(spd_info_t *si, uint32_t off, uint32_t len,
390 const char *key)
391 {
392 const uint8_t data = si->si_data[off];
393 spd_ddr3_feat_t flags = 0;
394
395 if (SPD_DDR3_OPT_FEAT_RZQ6(data) != 0)
396 flags |= SPD_DDR3_FEAT_RZQ_6;
397 if (SPD_DDR3_OPT_FEAT_RZQ7(data) != 0)
398 flags |= SPD_DDR3_FEAT_RZQ_7;
399 if (SPD_DDR3_OPT_FEAT_DLLO(data) != 0)
400 flags |= SPD_DDR3_FEAT_DLL_OFF;
401
402 if (flags != 0) {
403 spd_upsert_flag(si, SPD_KEY_DDR3_FEAT, flags);
404 }
405 }
406
407 static const spd_value_map_t spd_ddr3_temp[] = {
408 { SPD_DDR3_REFRESH_ETR_TEMP_85C, JEDEC_TEMP_CASE_NT, false },
409 { SPD_DDR3_REFRESH_ETR_TEMP_95C, JEDEC_TEMP_CASE_XT, false },
410 };
411
412 static const spd_value_map_t spd_ddr3_xtrr[] = {
413 { SPD_DDR3_REFRESH_ETR_REF_2X, 2, false },
414 { SPD_DDR3_REFRESH_ETR_REF_1X, 1, false },
415 };
416
417 /*
418 * While this defines an ODTS bit it was pending a ballot and it's not clear to
419 * us that this ballot has ever passed. If it has, then we will denote
420 * something there.
421 */
422 static void
spd_parse_ddr3_refresh(spd_info_t * si,uint32_t off,uint32_t len,const char * key)423 spd_parse_ddr3_refresh(spd_info_t *si, uint32_t off, uint32_t len,
424 const char *key)
425 {
426 const uint8_t data = si->si_data[off];
427 const uint8_t etr = SPD_DDR3_REFRESH_ETR_TEMP(data);
428 const uint8_t rr = SPD_DDR3_REFRESH_ETR_REF(data);
429
430 spd_insert_map(si, SPD_KEY_MOD_OPER_TEMP, etr,
431 spd_ddr3_temp, ARRAY_SIZE(spd_ddr3_temp));
432 spd_insert_map(si, SPD_KEY_DDR3_XTRR, rr,
433 spd_ddr3_xtrr, ARRAY_SIZE(spd_ddr3_xtrr));
434 if (SPD_DDR3_REFRESH_ASR_SUP(data) != 0) {
435 spd_upsert_flag(si, SPD_KEY_DDR3_FEAT, SPD_DDR3_FEAT_ASR);
436 }
437
438 if (SPD_DDR3_REFRESH_PASR_SUP(data) != 0) {
439 spd_nvl_insert_key(si, SPD_KEY_DDR_PASR);
440 }
441 }
442
443 static void
spd_parse_ddr3_ts(spd_info_t * si,uint32_t off,uint32_t len,const char * key)444 spd_parse_ddr3_ts(spd_info_t *si, uint32_t off, uint32_t len,
445 const char *key)
446 {
447 const uint8_t data = si->si_data[off];
448
449 if (SPD_DDR3_MOD_THERM_PRES(data)) {
450 spd_upsert_flag(si, SPD_KEY_DEVS, SPD_DEVICE_TEMP_1);
451 spd_nvl_insert_u32(si, SPD_KEY_DEV_TEMP_TYPE,
452 SPD_TEMP_T_TSE2002);
453 }
454 }
455
456 static const spd_value_map_t spd_ddr3_sl_map[] = {
457 { SPD_DDR3_PKG_SIG_LOAD_UNSPEC, SPD_SL_UNSPECIFIED, false },
458 { SPD_DDR3_PKG_SIG_LOAD_MULTI, SPD_SL_MUTLI_STACK, false },
459 { SPD_DDR3_PKG_SIG_LOAD_SINGLE, SPD_SL_3DS, false }
460 };
461
462 static const spd_value_range_t spd_ddr3_ndie_range = {
463 .svr_min = SPD_DDR3_PKG_DIE_CNT_MIN,
464 .svr_max = SPD_DDR3_PKG_DIE_CNT_MAX,
465 .svr_exp = true
466 };
467
468 static void
spd_parse_ddr3_type(spd_info_t * si,uint32_t off,uint32_t len,const char * key)469 spd_parse_ddr3_type(spd_info_t *si, uint32_t off, uint32_t len,
470 const char *key)
471 {
472 const uint8_t data = si->si_data[off];
473 const uint8_t ndie = SPD_DDR3_PKG_DIE_CNT(data);
474 const uint8_t sl = SPD_DDR3_PKG_SIG_LOAD(data);
475
476 if (SPD_DDR3_PKG_TYPE(data) == SPD_DDR3_PKG_TYPE_NOT) {
477 spd_nvl_insert_key(si, SPD_KEY_PKG_NOT_MONO);
478 }
479
480 /*
481 * A value of zero here is considered unspecified.
482 */
483 if (SPD_DDR3_PKG_DIE_CNT(data) != 0) {
484 spd_insert_range(si, SPD_KEY_PKG_NDIE, ndie,
485 &spd_ddr3_ndie_range);
486 }
487
488 spd_insert_map(si, SPD_KEY_PKG_SL, sl, spd_ddr3_sl_map,
489 ARRAY_SIZE(spd_ddr3_sl_map));
490 }
491
492 static const spd_value_map_t spd_ddr3_maw_map[] = {
493 { SPD_DDR3_MAC_MAW_8192X, 8192, false },
494 { SPD_DDR3_MAC_MAW_4096X, 4096, false },
495 { SPD_DDR3_MAC_MAW_2048X, 2048, false }
496 };
497
498 static const spd_value_map_t spd_ddr3_mac_map[] = {
499 { SPD_DDR3_MAC_MAC_UNTESTED, 0, true},
500 { SPD_DDR3_MAC_MAC_700K, 700000, false },
501 { SPD_DDR3_MAC_MAC_600K, 600000, false },
502 { SPD_DDR3_MAC_MAC_500K, 500000, false },
503 { SPD_DDR3_MAC_MAC_400K, 400000, false },
504 { SPD_DDR3_MAC_MAC_300K, 300000, false },
505 { SPD_DDR3_MAC_MAC_200K, 200000, false },
506 { SPD_DDR3_MAC_MAC_UNLIMITED, SPD_KEY_MAC_UNLIMITED, false }
507 };
508
509 static void
spd_parse_ddr3_mac(spd_info_t * si,uint32_t off,uint32_t len,const char * key)510 spd_parse_ddr3_mac(spd_info_t *si, uint32_t off, uint32_t len, const char *key)
511 {
512 const uint8_t data = si->si_data[off];
513 const uint8_t maw = SPD_DDR3_MAC_MAW(data);
514 const uint8_t mac = SPD_DDR3_MAC_MAC(data);
515
516 spd_insert_map(si, SPD_KEY_MAW, maw, spd_ddr3_maw_map,
517 ARRAY_SIZE(spd_ddr3_maw_map));
518 spd_insert_map(si, SPD_KEY_MAC, mac, spd_ddr3_mac_map,
519 ARRAY_SIZE(spd_ddr3_mac_map));
520 }
521
522 /*
523 * The DDR3 CRC comes in two different lengths as the DDR3 CRC may optionally
524 * cover the manufacturing information or stop short at byte 116. Which length
525 * this is is defined in byte 0.
526 */
527 static void
spd_parse_ddr3_crc(spd_info_t * si,uint32_t off,uint32_t len,const char * key)528 spd_parse_ddr3_crc(spd_info_t *si, uint32_t off, uint32_t len, const char *key)
529 {
530 const uint16_t expect = si->si_data[off + len - 2] |
531 (si->si_data[off + len - 1] << 8);
532 const uint8_t crc = SPD_DDR3_NBYTES_CRC(si->si_data[SPD_DDR3_NBYTES]);
533 const uint32_t crc_len = crc == SPD_DDR3_NBYTES_CRC_125 ? 127 : 117;
534
535 spd_parse_crc_expect(si, off, crc_len, expect, key);
536 }
537
538 static const spd_parse_t spd_ddr3_common[] = {
539 { .sp_off = SPD_DDR3_NBYTES, .sp_parse = spd_parse_ddr3_nbytes },
540 { .sp_off = SPD_DDR3_SPD_REV, .sp_parse = spd_parse_rev },
541 /*
542 * We have previously validated that the DRAM type is something that we
543 * understand. We pass through the raw enum to users here.
544 */
545 { .sp_off = SPD_DDR3_DRAM_TYPE, .sp_key = SPD_KEY_DRAM_TYPE,
546 .sp_parse = spd_parse_raw_u8 },
547 { .sp_off = SPD_DDR3_MOD_TYPE, .sp_parse = spd_parse_ddr3_mod_type },
548 { .sp_off = SPD_DDR3_DENSITY, .sp_parse = spd_parse_ddr3_density },
549 { .sp_off = SPD_DDR3_ADDR, .sp_parse = spd_parse_ddr3_addr },
550 { .sp_off = SPD_DDR3_VOLT, .sp_key = SPD_KEY_NOM_VDD,
551 .sp_parse = spd_parse_ddr3_volt },
552 { .sp_off = SPD_DDR3_MOD_ORG, .sp_parse = spd_parse_ddr3_mod_org },
553 { .sp_off = SPD_DDR3_BUS_WIDTH, .sp_parse = spd_parse_ddr3_bus_width },
554 { .sp_off = SPD_DDR3_FTB, .sp_key = SPD_KEY_FTB,
555 .sp_parse = spd_parse_ddr3_ftb },
556 { .sp_off = SPD_DDR3_MTB_DIVIDEND, .sp_key = SPD_KEY_MTB, .sp_len = 2,
557 .sp_parse = spd_parse_ddr3_mtb },
558 { .sp_off = SPD_DDR3_TCK_MIN, .sp_key = SPD_KEY_TCKAVG_MIN,
559 .sp_len = SPD_DDR3_TCK_MIN_FINE - SPD_DDR3_TCK_MIN + 1,
560 .sp_parse = spd_parse_mtb_ftb_time_pair },
561 { .sp_off = SPD_DDR3_CAS_SUP0, .sp_key = SPD_KEY_CAS, .sp_len = 2,
562 .sp_parse = spd_parse_ddr3_cas },
563 { .sp_off = SPD_DDR3_TAA_MIN, .sp_key = SPD_KEY_TAA_MIN,
564 .sp_len = SPD_DDR3_TAA_MIN_FINE - SPD_DDR3_TAA_MIN + 1,
565 .sp_parse = spd_parse_mtb_ftb_time_pair },
566 { .sp_off = SPD_DDR3_TWR_MIN, .sp_key = SPD_KEY_TWR_MIN,
567 .sp_parse = spd_parse_ddr3_mtb_time },
568 { .sp_off = SPD_DDR3_TRCD_MIN, .sp_key = SPD_KEY_TRCD_MIN,
569 .sp_len = SPD_DDR3_TRCD_MIN_FINE - SPD_DDR3_TRCD_MIN + 1,
570 .sp_parse = spd_parse_mtb_ftb_time_pair },
571 /*
572 * DDR3 defines only a single tRRD value. There are no bank groups in
573 * DDR3 therefore we translate that to tRRD_L, as we consider everything
574 * to be in a single bank group.
575 */
576 { .sp_off = SPD_DDR3_TRRD_MIN, .sp_key = SPD_KEY_TRRD_L_MIN,
577 .sp_parse = spd_parse_ddr3_mtb_time },
578 { .sp_off = SPD_DDR3_TRP_MIN, .sp_key = SPD_KEY_TRP_MIN,
579 .sp_len = SPD_DDR3_TRP_MIN_FINE - SPD_DDR3_TRP_MIN + 1,
580 .sp_parse = spd_parse_mtb_ftb_time_pair },
581 { .sp_off = SPD_DDR3_RAS_RC_UPPER, .sp_len = 2,
582 .sp_key = SPD_KEY_TRAS_MIN, .sp_parse = spd_parse_ddr3_tras },
583 { .sp_off = SPD_DDR3_RAS_RC_UPPER, .sp_key = SPD_KEY_TRC_MIN,
584 .sp_len = SPD_DDR3_TRC_MIN_FINE - SPD_DDR3_RAS_RC_UPPER + 1,
585 .sp_parse = spd_parse_ddr3_trc },
586 /*
587 * Our rough understanding is that the DDR3 tRFC is a 1x rate.
588 */
589 { .sp_off = SPD_DDR3_TRFC_MIN_LSB, .sp_len = 2,
590 .sp_key = SPD_KEY_TRFC1_MIN, .sp_parse = spd_parse_mtb_pair },
591 /*
592 * tWTR is like tRRD and it gets mapped to the same bank group case.
593 */
594 { .sp_off = SPD_DDR3_TWTR_MIN, .sp_key = SPD_KEY_TWTRS_MIN,
595 .sp_parse = spd_parse_ddr3_mtb_time },
596 { .sp_off = SPD_DDR3_TRTP_MIN, .sp_key = SPD_KEY_TRTP,
597 .sp_parse = spd_parse_ddr3_mtb_time },
598 { .sp_off = SPD_DDR3_TFAW_NIB, .sp_len = 2,
599 .sp_key = SPD_KEY_TFAW, .sp_parse = spd_parse_ddr3_tfaw },
600 { .sp_off = SPD_DDR3_OPT_FEAT, .sp_parse = spd_parse_ddr3_opt_feat },
601 { .sp_off = SPD_DDR3_REFRESH, .sp_parse = spd_parse_ddr3_refresh },
602 { .sp_off = SPD_DDR3_MOD_THERM, .sp_parse = spd_parse_ddr3_ts },
603 { .sp_off = SPD_DDR3_TYPE, .sp_parse = spd_parse_ddr3_type },
604 { .sp_off = SPD_DDR3_MAC, .sp_parse = spd_parse_ddr3_mac},
605 /*
606 * As the CRC is part of all module types we just stick in with the
607 * general processing.
608 */
609 { .sp_len = SPD_DDR3_CRC_MSB + 1, .sp_key = SPD_KEY_CRC_DDR3,
610 .sp_parse = spd_parse_ddr3_crc },
611 };
612
613 static const spd_parse_t spd_ddr3_mfg[] = {
614 { .sp_off = SPD_DDR3_MFG_MOD_ID0, .sp_len = 2,
615 .sp_key = SPD_KEY_MFG_MOD_MFG_ID,
616 .sp_parse = spd_parse_jedec_id },
617 { .sp_off = SPD_DDR3_MFG_MOD_ID0, .sp_len = 2,
618 .sp_key = SPD_KEY_MFG_MOD_MFG_NAME,
619 .sp_parse = spd_parse_jedec_id_str },
620 { .sp_off = SPD_DDR3_MFG_LOC, .sp_key = SPD_KEY_MFG_MOD_LOC_ID,
621 .sp_parse = spd_parse_raw_u8 },
622 { .sp_off = SPD_DDR3_MFG_YEAR, .sp_key = SPD_KEY_MFG_MOD_YEAR,
623 .sp_parse = spd_parse_hex_string },
624 { .sp_off = SPD_DDR3_MFG_WEEK, .sp_key = SPD_KEY_MFG_MOD_WEEK,
625 .sp_parse = spd_parse_hex_string },
626 { .sp_off = SPD_DDR3_MOD_SN, .sp_len = SPD_DDR3_MOD_SN_LEN,
627 .sp_key = SPD_KEY_MFG_MOD_SN, .sp_parse = spd_parse_hex_string },
628 { .sp_off = SPD_DDR3_MOD_PN, .sp_len = SPD_DDR3_MOD_PN_LEN,
629 .sp_key = SPD_KEY_MFG_MOD_PN, .sp_parse = spd_parse_string },
630 /*
631 * In DDR3 the module revision is a two byte value that is up to the
632 * vendor to define. While we've seen one instance where this was split
633 * into a DDR4 style module and DRAM revision, we just blindly turn it
634 * into a hex string just because that is not a guarantee.
635 */
636 { .sp_off = SPD_DDR3_MOD_REV, .sp_len = SPD_DDR3_MOD_REV_LEN,
637 .sp_key = SPD_KEY_MFG_MOD_REV, .sp_parse = spd_parse_hex_string },
638 { .sp_off = SPD_DDR3_MFG_DRAM_ID0, .sp_len = 2,
639 .sp_key = SPD_KEY_MFG_DRAM_MFG_ID,
640 .sp_parse = spd_parse_jedec_id },
641 { .sp_off = SPD_DDR3_MFG_DRAM_ID0, .sp_len = 2,
642 .sp_key = SPD_KEY_MFG_DRAM_MFG_NAME,
643 .sp_parse = spd_parse_jedec_id_str },
644 };
645
646 static void
spd_parse_ddr3_design(spd_info_t * si,uint32_t off,uint32_t len,const char * key)647 spd_parse_ddr3_design(spd_info_t *si, uint32_t off, uint32_t len,
648 const char *key)
649 {
650 ASSERT3U(off, >=, SPD_DDR3_RDIMM_HEIGHT);
651 return (spd_parse_design(si, off, SPD_DDR3_UDIMM_HEIGHT));
652 }
653
654 static void
spd_parse_ddr3_edge(spd_info_t * si,uint32_t off,uint32_t len,const char * key)655 spd_parse_ddr3_edge(spd_info_t *si, uint32_t off, uint32_t len,
656 const char *key)
657 {
658 const uint8_t data = si->si_data[off];
659
660 if (SPD_DDR3_UDIMM_MAP_R1(data) == SPD_DDR3_UDIMM_MAP_R1_MIRROR)
661 spd_nvl_insert_key(si, SPD_KEY_MOD_EDGE_MIRROR);
662 }
663
664 static const spd_parse_t spd_ddr3_udimm[] = {
665 { .sp_off = SPD_DDR3_UDIMM_HEIGHT, .sp_key = SPD_KEY_MOD_HEIGHT,
666 .sp_parse = spd_parse_height },
667 { .sp_off = SPD_DDR3_UDIMM_THICK, .sp_parse = spd_parse_thickness },
668 { .sp_off = SPD_DDR3_UDIMM_REF, .sp_parse = spd_parse_ddr3_design },
669 { .sp_off = SPD_DDR3_UDIMM_MAP, .sp_parse = spd_parse_ddr3_edge }
670 };
671
672 /*
673 * This mapping is true for both the number of rows and registers.
674 */
675 static const spd_value_map_t spd_ddr3_rdimm_nrows_map[] = {
676 { 0, 0, true },
677 { 1, 1, false },
678 { 2, 2, false },
679 { 3, 4, false }
680 };
681
682 static void
spd_parse_ddr3_rdimm_attr(spd_info_t * si,uint32_t off,uint32_t len,const char * key)683 spd_parse_ddr3_rdimm_attr(spd_info_t *si, uint32_t off, uint32_t len,
684 const char *key)
685 {
686 const uint8_t data = si->si_data[off];
687 const uint8_t nregs = SPD_DDR3_RDIMM_ATTR_NREGS(data);
688 const uint8_t nrows = SPD_DDR3_RDIMM_ATTR_NROWS(data);
689
690 spd_insert_map(si, SPD_KEY_MOD_NROWS, nrows, spd_ddr3_rdimm_nrows_map,
691 ARRAY_SIZE(spd_ddr3_rdimm_nrows_map));
692 spd_insert_map(si, SPD_KEY_MOD_NREGS, nregs, spd_ddr3_rdimm_nrows_map,
693 ARRAY_SIZE(spd_ddr3_rdimm_nrows_map));
694 }
695
696 static void
spd_parse_ddr3_rdimm_hs(spd_info_t * si,uint32_t off,uint32_t len,const char * key)697 spd_parse_ddr3_rdimm_hs(spd_info_t *si, uint32_t off, uint32_t len,
698 const char *key)
699 {
700 const uint8_t data = si->si_data[off];
701
702 if (SPD_DDR3_RDIMM_THERM_IMPL(data) != 0)
703 spd_upsert_flag(si, SPD_KEY_DEVS, SPD_DEVICE_HS);
704 }
705
706 static void
spd_parse_ddr3_rdimm_type(spd_info_t * si,uint32_t off,uint32_t len,const char * key)707 spd_parse_ddr3_rdimm_type(spd_info_t *si, uint32_t off, uint32_t len,
708 const char *key)
709 {
710 const uint8_t data = si->si_data[off];
711 const uint8_t type = SPD_DDR3_RDIMM_RTYPE_TYPE(data);
712
713 if (type != SPD_DDR3_RDIMM_RTYPE_TYPE_SSTE32882) {
714 spd_nvl_err(si, SPD_KEY_DEV_RCD_TYPE, SPD_ERROR_NO_XLATE,
715 "encountered unknown register type value: 0x%x", type);
716 return;
717 }
718
719 spd_upsert_flag(si, SPD_KEY_DEVS, SPD_DEVICE_RCD);
720 spd_nvl_insert_u32(si, SPD_KEY_DEV_RCD_TYPE, SPD_RCD_T_SSTE32882);
721 }
722
723 /*
724 * There are different variants of these maps that RDIMMs and LRDIMMs share
725 * which are used depending on the specific register value and what it actually
726 * supports.
727 */
728 static const spd_value_map_t spd_ddr3_rdimm_lmsv_ds_map[] = {
729 { SPD_DDR3_RDIMM_DS_LIGHT, SPD_DRIVE_LIGHT, false },
730 { SPD_DDR3_RDIMM_DS_MODERATE, SPD_DRIVE_MODERATE, false },
731 { SPD_DDR3_RDIMM_DS_STRONG, SPD_DRIVE_STRONG, false },
732 { SPD_DDR3_RDIMM_DS_VERY_STRONG, SPD_DRIVE_VERY_STRONG, false },
733 };
734
735 static const spd_value_map_t spd_ddr3_rdimm_lms_ds_map[] = {
736 { SPD_DDR3_RDIMM_DS_LIGHT, SPD_DRIVE_LIGHT, false },
737 { SPD_DDR3_RDIMM_DS_MODERATE, SPD_DRIVE_MODERATE, false },
738 { SPD_DDR3_RDIMM_DS_STRONG, SPD_DRIVE_STRONG, false },
739 };
740
741 static const spd_value_map_t spd_ddr3_rdimm_lm_ds_map[] = {
742 { SPD_DDR3_RDIMM_DS_LIGHT, SPD_DRIVE_LIGHT, false },
743 { SPD_DDR3_RDIMM_DS_MODERATE, SPD_DRIVE_MODERATE, false },
744 };
745
746 static void
spd_parse_ddr3_rdimm_cads(spd_info_t * si,uint32_t off,uint32_t len,const char * key)747 spd_parse_ddr3_rdimm_cads(spd_info_t *si, uint32_t off, uint32_t len,
748 const char *key)
749 {
750 const uint8_t data = si->si_data[off];
751 const uint8_t caa = SPD_DDR3_RDIMM_CADS_CAA(data);
752 const uint8_t cab = SPD_DDR3_RDIMM_CADS_CAB(data);
753
754 spd_insert_map(si, SPD_KEY_DDR3_RCD_DS_CAA, caa,
755 spd_ddr3_rdimm_lms_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lms_ds_map));
756 spd_insert_map(si, SPD_KEY_DDR3_RCD_DS_CAB, cab,
757 spd_ddr3_rdimm_lms_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lms_ds_map));
758 }
759
760 static void
spd_parse_ddr3_rdimm_ccds(spd_info_t * si,uint32_t off,uint32_t len,const char * key)761 spd_parse_ddr3_rdimm_ccds(spd_info_t *si, uint32_t off, uint32_t len,
762 const char *key)
763 {
764 const uint8_t data = si->si_data[off];
765 const uint8_t ctla = SPD_DDR3_RDIMM_CCDS_CTLA(data);
766 const uint8_t ctlb = SPD_DDR3_RDIMM_CCDS_CTLB(data);
767 const uint8_t y1 = SPD_DDR3_RDIMM_CCDS_CLK1(data);
768 const uint8_t y0 = SPD_DDR3_RDIMM_CCDS_CLK0(data);
769
770
771 spd_insert_map(si, SPD_KEY_DDR3_RCD_DS_CTLA, ctla,
772 spd_ddr3_rdimm_lm_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lm_ds_map));
773 spd_insert_map(si, SPD_KEY_DDR3_RCD_DS_CTLB, ctlb,
774 spd_ddr3_rdimm_lm_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lm_ds_map));
775 spd_insert_map(si, SPD_KEY_DDR3_RCD_DS_Y0, y0,
776 spd_ddr3_rdimm_lms_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lms_ds_map));
777 spd_insert_map(si, SPD_KEY_DDR3_RCD_DS_Y1, y1,
778 spd_ddr3_rdimm_lms_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lms_ds_map));
779 }
780
781 static const spd_parse_t spd_ddr3_rdimm[] = {
782 { .sp_off = SPD_DDR3_RDIMM_HEIGHT, .sp_key = SPD_KEY_MOD_HEIGHT,
783 .sp_parse = spd_parse_height },
784 { .sp_off = SPD_DDR3_RDIMM_THICK, .sp_parse = spd_parse_thickness },
785 { .sp_off = SPD_DDR3_RDIMM_REF, .sp_parse = spd_parse_ddr3_design },
786 { .sp_off = SPD_DDR3_RDIMM_ATTR,
787 .sp_parse = spd_parse_ddr3_rdimm_attr },
788 { .sp_off = SPD_DDR3_RDIMM_THERM, .sp_parse = spd_parse_ddr3_rdimm_hs },
789 { .sp_off = SPD_DDR3_RDIMM_REG_MFG_ID0, .sp_len = 2,
790 .sp_key = SPD_KEY_DEV_RCD_MFG,
791 .sp_parse = spd_parse_jedec_id },
792 { .sp_off = SPD_DDR3_RDIMM_REG_MFG_ID0, .sp_len = 2,
793 .sp_key = SPD_KEY_DEV_RCD_MFG_NAME,
794 .sp_parse = spd_parse_jedec_id_str },
795 { .sp_off = SPD_DDR3_RDIMM_REV, .sp_key = SPD_KEY_DEV_RCD_REV,
796 .sp_parse = spd_parse_dram_step },
797 { .sp_off = SPD_DDR3_RDIMM_RTYPE,
798 .sp_parse = spd_parse_ddr3_rdimm_type },
799 { .sp_off = SPD_DDR3_RDIMM_CADS,
800 .sp_parse = spd_parse_ddr3_rdimm_cads },
801 { .sp_off = SPD_DDR3_RDIMM_CCDS,
802 .sp_parse = spd_parse_ddr3_rdimm_ccds },
803 };
804
805 static const spd_parse_t spd_ddr3_cdimm[] = {
806 { .sp_off = SPD_DDR3_CDIMM_HEIGHT, .sp_key = SPD_KEY_MOD_HEIGHT,
807 .sp_parse = spd_parse_height },
808 { .sp_off = SPD_DDR3_CDIMM_THICK, .sp_parse = spd_parse_thickness },
809 { .sp_off = SPD_DDR3_CDIMM_REF, .sp_parse = spd_parse_ddr3_design },
810 };
811
812 static const spd_value_map_t spd_ddr3_lrdimm_nrows_map[] = {
813 { 0, 0, true },
814 { 1, 1, false },
815 { 2, 2, false },
816 };
817
818 static const spd_value_map_t spd_ddr3_lrdimm_orient_map[] = {
819 { SPD_DDR3_LRDIMM_ATTR_ORIENT_VERT, SPD_ORNT_VERTICAL, false },
820 { SPD_DDR3_LRDIMM_ATTR_ORIENT_HORIZ, SPD_ORNT_HORIZONTAL, false }
821 };
822
823 static void
spd_parse_ddr3_lrdimm_attr(spd_info_t * si,uint32_t off,uint32_t len,const char * key)824 spd_parse_ddr3_lrdimm_attr(spd_info_t *si, uint32_t off, uint32_t len,
825 const char *key)
826 {
827 const uint8_t data = si->si_data[off];
828 const uint8_t mirror = SPD_DDR3_LRDIMM_ATTR_MIR(data);
829 const uint8_t nrows = SPD_DDR3_LRDIMM_ATTR_NROWS(data);
830 const uint8_t orient = SPD_DDR3_LRDIMM_ATTR_ORIENT(data);
831
832 if (mirror == SPD_DDR3_LRDIMM_ATTR_MIR_ODD_ARE)
833 spd_nvl_insert_key(si, SPD_KEY_MOD_EDGE_MIRROR);
834
835 spd_insert_map(si, SPD_KEY_MOD_NROWS, nrows, spd_ddr3_lrdimm_nrows_map,
836 ARRAY_SIZE(spd_ddr3_lrdimm_nrows_map));
837 spd_insert_map(si, SPD_KEY_DDR3_MB_ORIENT, orient,
838 spd_ddr3_lrdimm_orient_map, ARRAY_SIZE(spd_ddr3_lrdimm_orient_map));
839
840 if (SPD_DDR3_LRDIMM_ATTR_HS(data) != 0)
841 spd_upsert_flag(si, SPD_KEY_DEVS, SPD_DEVICE_HS);
842 }
843
844 static void
spd_parse_ddr3_lrdimm_mb(spd_info_t * si,uint32_t off,uint32_t len,const char * key)845 spd_parse_ddr3_lrdimm_mb(spd_info_t *si, uint32_t off, uint32_t len,
846 const char *key)
847 {
848 ASSERT3U(len, ==, 2);
849
850 /*
851 * Use this chance to set the DDR3 MB device as present and its type.
852 */
853 spd_upsert_flag(si, SPD_KEY_DEVS, SPD_DEVICE_DB);
854 spd_nvl_insert_u32(si, SPD_KEY_DEV_DB_TYPE, SPD_DB_T_DDR3MB);
855 spd_parse_jedec_id(si, off, 2, SPD_KEY_DEV_DB_MFG);
856 spd_parse_jedec_id_str(si, off, 2, SPD_KEY_DEV_DB_MFG_NAME);
857 }
858
859 static void
spd_parse_ddr3_lrdimm_tcds(spd_info_t * si,uint32_t off,uint32_t len,const char * key)860 spd_parse_ddr3_lrdimm_tcds(spd_info_t *si, uint32_t off, uint32_t len,
861 const char *key)
862 {
863 const uint8_t data = si->si_data[off];
864 const uint8_t ca = SPD_DDR3_LRDIMM_TCDS_AC(data);
865 const uint8_t cs = SPD_DDR3_LRDIMM_TCDS_QxCS(data);
866
867 spd_insert_map(si, SPD_KEY_DDR3_MB_DS_CA, ca,
868 spd_ddr3_rdimm_lmsv_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lmsv_ds_map));
869 spd_insert_map(si, SPD_KEY_DDR3_MB_DS_CS, cs,
870 spd_ddr3_rdimm_lms_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lms_ds_map));
871 }
872
873 static void
spd_parse_ddr3_lrdimm_ckds(spd_info_t * si,uint32_t off,uint32_t len,const char * key)874 spd_parse_ddr3_lrdimm_ckds(spd_info_t *si, uint32_t off, uint32_t len,
875 const char *key)
876 {
877 const uint8_t data = si->si_data[off];
878 const uint8_t odt = SPD_DDR3_LRDIMM_CKDS_ODT(data);
879 const uint8_t cke = SPD_DDR3_LRDIMM_CKDS_CKE(data);
880 const uint8_t y1 = SPD_DDR3_LRDIMM_CKDS_Y1Y3(data);
881 const uint8_t y0 = SPD_DDR3_LRDIMM_CKDS_Y0Y2(data);
882
883 spd_insert_map(si, SPD_KEY_DDR3_MB_DS_ODT, odt,
884 spd_ddr3_rdimm_lms_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lms_ds_map));
885 spd_insert_map(si, SPD_KEY_DDR3_MB_DS_CKE, cke,
886 spd_ddr3_rdimm_lms_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lms_ds_map));
887 spd_insert_map(si, SPD_KEY_DDR3_MB_DS_Y1, y1,
888 spd_ddr3_rdimm_lms_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lms_ds_map));
889 spd_insert_map(si, SPD_KEY_DDR3_MB_DS_Y0, y0,
890 spd_ddr3_rdimm_lms_ds_map, ARRAY_SIZE(spd_ddr3_rdimm_lms_ds_map));
891 }
892
893 static void
spd_parse_ddr3_lrdimm_ext_delay(spd_info_t * si,uint32_t off,uint32_t len,const char * key)894 spd_parse_ddr3_lrdimm_ext_delay(spd_info_t *si, uint32_t off, uint32_t len,
895 const char *key)
896 {
897 const uint8_t data = si->si_data[off];
898 const uint8_t y = SPD_DDR3_LRDIMM_EXTD_Y(data);
899 const uint8_t cs = SPD_DDR3_LRDIMM_EXTD_CS(data);
900 const uint8_t odt = SPD_DDR3_LRDIMM_EXTD_ODT(data);
901 const uint8_t cke = SPD_DDR3_LRDIMM_EXTD_CKE(data);
902
903 /*
904 * A value of 0 is equal to no delay, otherwise these are a measure of
905 * x/128 * tCK values and we store x in the nvlist.
906 */
907 if (y != 0)
908 spd_nvl_insert_u32(si, SPD_KEY_DDR3_MB_EXTD_Y, y);
909 if (cs != 0)
910 spd_nvl_insert_u32(si, SPD_KEY_DDR3_MB_EXTD_CS, cs);
911 if (odt != 0)
912 spd_nvl_insert_u32(si, SPD_KEY_DDR3_MB_EXTD_ODT, odt);
913 if (cke != 0)
914 spd_nvl_insert_u32(si, SPD_KEY_DDR3_MB_EXTD_CKE, cke);
915 }
916
917 /*
918 * Each additive delay nibble contains an enable bit. However, the enable bit
919 * for Y clocks is actually bit 0 in SPD_DDR3_LRDIMM_TCDS.
920 */
921 static void
spd_parse_ddr3_lrdimm_add_delay_csy(spd_info_t * si,uint32_t off,uint32_t len,const char * key)922 spd_parse_ddr3_lrdimm_add_delay_csy(spd_info_t *si, uint32_t off, uint32_t len,
923 const char *key)
924 {
925 const uint8_t data = si->si_data[off];
926 const uint8_t y = SPD_DDR3_LRDIMM_ADDD_CSY_Y(data);
927 const uint8_t cs = SPD_DDR3_LRDIMM_ADDD_CSY_CS(data);
928 ASSERT3U(off, >, SPD_DDR3_LRDIMM_TCDS);
929 const uint8_t yen = si->si_data[SPD_DDR3_LRDIMM_TCDS];
930
931 if (SPD_DDR3_LRDIMM_TCDS_ACPL(yen) != SPD_DDR3_LRDIMM_TCDS_ACPL_STD) {
932 const uint8_t val = SPD_DDR3_LRDIMM_ADD_BASE - y;
933 spd_nvl_insert_u32(si, SPD_KEY_DDR3_MB_ADDD_Y, val);
934 }
935
936 if (SPD_DDR3_LRDIMM_ADDD_CSY_CS_EN(data) != 0) {
937 const uint8_t val = SPD_DDR3_LRDIMM_ADD_BASE - cs;
938 spd_nvl_insert_u32(si, SPD_KEY_DDR3_MB_ADDD_CS, val);
939 }
940 }
941
942 static void
spd_parse_ddr3_lrdimm_add_delay_odt(spd_info_t * si,uint32_t off,uint32_t len,const char * key)943 spd_parse_ddr3_lrdimm_add_delay_odt(spd_info_t *si, uint32_t off, uint32_t len,
944 const char *key)
945 {
946 const uint8_t data = si->si_data[off];
947 const uint8_t cke = SPD_DDR3_LRDIMM_ADDD_ODT_CKE(data);
948 const uint8_t odt = SPD_DDR3_LRDIMM_ADDD_ODT_ODT(data);
949
950 if (SPD_DDR3_LRDIMM_ADDD_ODT_CKE_EN(data) != 0) {
951 const uint8_t val = SPD_DDR3_LRDIMM_ADD_BASE - cke;
952 spd_nvl_insert_u32(si, SPD_KEY_DDR3_MB_ADDD_CKE, val);
953 }
954
955 if (SPD_DDR3_LRDIMM_ADDD_ODT_ODT_EN(data) != 0) {
956 const uint8_t val = SPD_DDR3_LRDIMM_ADD_BASE - odt;
957 spd_nvl_insert_u32(si, SPD_KEY_DDR3_MB_ADDD_ODT, val);
958 }
959 }
960
961 static const spd_value_map_t spd_ddr3_mdq_ds_map[] = {
962 { SPD_DDR3_LRDIMM_MDQ_DS_40R, 40, false },
963 { SPD_DDR3_LRDIMM_MDQ_DS_34R, 34, false },
964 { SPD_DDR3_LRDIMM_MDQ_DS_48R, 48, false },
965 { SPD_DDR3_LRDIMM_MDQ_DS_27R, 27, false },
966 { SPD_DDR3_LRDIMM_MDQ_DS_20R, 20, false }
967 };
968
969 static const spd_value_map_t spd_ddr3_odt_map[] = {
970 { SPD_DDR3_LRDIMM_MDQ_ODT_DIS, SPD_TERM_DISABLED, false },
971 { SPD_DDR3_LRDIMM_MDQ_ODT_60R, 60, false },
972 { SPD_DDR3_LRDIMM_MDQ_ODT_120R, 120, false },
973 { SPD_DDR3_LRDIMM_MDQ_ODT_40R, 40, false },
974 { SPD_DDR3_LRDIMM_MDQ_ODT_30R, 30, false },
975 { SPD_DDR3_LRDIMM_MDQ_ODT_240R, 240, false },
976 { SPD_DDR3_LRDIMM_MDQ_ODT_80R, 80, false },
977 };
978
979 static void
spd_parse_ddr3_lrdimm_mdq(spd_info_t * si,uint32_t off,uint32_t len,const char * key)980 spd_parse_ddr3_lrdimm_mdq(spd_info_t *si, uint32_t off, uint32_t len,
981 const char *key)
982 {
983 const uint8_t d800 = si->si_data[off];
984 const uint8_t d1333 = si->si_data[off + SPD_DDR3_LRDIMM_STRIDE];
985 const uint8_t d1866 = si->si_data[off + SPD_DDR3_LRDIMM_STRIDE * 2];
986 const uint8_t odt[3] = { SPD_DDR3_LRDIMM_MDQ_ODT(d800),
987 SPD_DDR3_LRDIMM_MDQ_ODT(d1333), SPD_DDR3_LRDIMM_MDQ_ODT(d1866) };
988 const uint8_t ds[3] = { SPD_DDR3_LRDIMM_MDQ_DS(d800),
989 SPD_DDR3_LRDIMM_MDQ_DS(d1333), SPD_DDR3_LRDIMM_MDQ_DS(d1866) };
990
991 spd_insert_map_array(si, SPD_KEY_DDR3_MDQ_ODT, odt, ARRAY_SIZE(odt),
992 spd_ddr3_odt_map, ARRAY_SIZE(spd_ddr3_odt_map));
993 spd_insert_map_array(si, SPD_KEY_DDR3_MDQ_DS, ds, ARRAY_SIZE(ds),
994 spd_ddr3_mdq_ds_map, ARRAY_SIZE(spd_ddr3_mdq_ds_map));
995 }
996
997 static void
spd_parse_ddr3_lrdimm_odt_common(spd_info_t * si,uint32_t off,const char * r0_odt0_rd_key,const char * r0_odt1_rd_key,const char * r1_odt0_rd_key,const char * r1_odt1_rd_key,const char * r0_odt0_wr_key,const char * r0_odt1_wr_key,const char * r1_odt0_wr_key,const char * r1_odt1_wr_key)998 spd_parse_ddr3_lrdimm_odt_common(spd_info_t *si, uint32_t off,
999 const char *r0_odt0_rd_key, const char *r0_odt1_rd_key,
1000 const char *r1_odt0_rd_key, const char *r1_odt1_rd_key,
1001 const char *r0_odt0_wr_key, const char *r0_odt1_wr_key,
1002 const char *r1_odt0_wr_key, const char *r1_odt1_wr_key)
1003 {
1004 const uint8_t d800 = si->si_data[off];
1005 const uint8_t d1333 = si->si_data[off + SPD_DDR3_LRDIMM_STRIDE];
1006 const uint8_t d1866 = si->si_data[off + SPD_DDR3_LRDIMM_STRIDE * 2];
1007 boolean_t r0_odt0_rd[3] = { SPD_DDR3_LRDIMM_ODT_R0_ODT0_RD(d800),
1008 SPD_DDR3_LRDIMM_ODT_R0_ODT0_RD(d1333),
1009 SPD_DDR3_LRDIMM_ODT_R0_ODT0_RD(d1866) };
1010 boolean_t r0_odt1_rd[3] = { SPD_DDR3_LRDIMM_ODT_R0_ODT1_RD(d800),
1011 SPD_DDR3_LRDIMM_ODT_R0_ODT1_RD(d1333),
1012 SPD_DDR3_LRDIMM_ODT_R0_ODT1_RD(d1866) };
1013 boolean_t r1_odt0_rd[3] = { SPD_DDR3_LRDIMM_ODT_R1_ODT0_RD(d800),
1014 SPD_DDR3_LRDIMM_ODT_R1_ODT0_RD(d1333),
1015 SPD_DDR3_LRDIMM_ODT_R1_ODT0_RD(d1866) };
1016 boolean_t r1_odt1_rd[3] = { SPD_DDR3_LRDIMM_ODT_R1_ODT1_RD(d800),
1017 SPD_DDR3_LRDIMM_ODT_R1_ODT1_RD(d1333),
1018 SPD_DDR3_LRDIMM_ODT_R1_ODT1_RD(d1866) };
1019 boolean_t r0_odt0_wr[3] = { SPD_DDR3_LRDIMM_ODT_R0_ODT0_WR(d800),
1020 SPD_DDR3_LRDIMM_ODT_R0_ODT0_WR(d1333),
1021 SPD_DDR3_LRDIMM_ODT_R0_ODT0_WR(d1866) };
1022 boolean_t r0_odt1_wr[3] = { SPD_DDR3_LRDIMM_ODT_R0_ODT1_WR(d800),
1023 SPD_DDR3_LRDIMM_ODT_R0_ODT1_WR(d1333),
1024 SPD_DDR3_LRDIMM_ODT_R0_ODT1_WR(d1866) };
1025 boolean_t r1_odt0_wr[3] = { SPD_DDR3_LRDIMM_ODT_R1_ODT0_WR(d800),
1026 SPD_DDR3_LRDIMM_ODT_R1_ODT0_WR(d1333),
1027 SPD_DDR3_LRDIMM_ODT_R1_ODT0_WR(d1866) };
1028 boolean_t r1_odt1_wr[3] = { SPD_DDR3_LRDIMM_ODT_R1_ODT1_WR(d800),
1029 SPD_DDR3_LRDIMM_ODT_R1_ODT1_WR(d1333),
1030 SPD_DDR3_LRDIMM_ODT_R1_ODT1_WR(d1866) };
1031
1032 spd_nvl_insert_boolean_array(si, r0_odt0_rd_key, r0_odt0_rd,
1033 ARRAY_SIZE(r0_odt0_rd));
1034 spd_nvl_insert_boolean_array(si, r0_odt1_rd_key, r0_odt1_rd,
1035 ARRAY_SIZE(r0_odt1_rd));
1036 spd_nvl_insert_boolean_array(si, r1_odt0_rd_key, r1_odt0_rd,
1037 ARRAY_SIZE(r1_odt0_rd));
1038 spd_nvl_insert_boolean_array(si, r1_odt1_rd_key, r1_odt1_rd,
1039 ARRAY_SIZE(r1_odt1_rd));
1040 spd_nvl_insert_boolean_array(si, r0_odt0_wr_key, r0_odt0_wr,
1041 ARRAY_SIZE(r0_odt0_wr));
1042 spd_nvl_insert_boolean_array(si, r0_odt1_wr_key, r0_odt1_wr,
1043 ARRAY_SIZE(r0_odt1_wr));
1044 spd_nvl_insert_boolean_array(si, r1_odt0_wr_key, r1_odt0_wr,
1045 ARRAY_SIZE(r1_odt0_wr));
1046 spd_nvl_insert_boolean_array(si, r1_odt1_wr_key, r1_odt1_wr,
1047 ARRAY_SIZE(r1_odt1_wr));
1048 }
1049
1050 static void
spd_parse_ddr3_lrdimm_odt_r0(spd_info_t * si,uint32_t off,uint32_t len,const char * key)1051 spd_parse_ddr3_lrdimm_odt_r0(spd_info_t *si, uint32_t off, uint32_t len,
1052 const char *key)
1053 {
1054 spd_parse_ddr3_lrdimm_odt_common(si, off,
1055 SPD_KEY_DDR3_MB_R0_ODT0_RD, SPD_KEY_DDR3_MB_R0_ODT1_RD,
1056 SPD_KEY_DDR3_MB_R1_ODT0_RD, SPD_KEY_DDR3_MB_R1_ODT1_RD,
1057 SPD_KEY_DDR3_MB_R0_ODT0_WR, SPD_KEY_DDR3_MB_R0_ODT1_WR,
1058 SPD_KEY_DDR3_MB_R1_ODT0_WR, SPD_KEY_DDR3_MB_R1_ODT1_WR);
1059 }
1060
1061 static void
spd_parse_ddr3_lrdimm_odt_r2(spd_info_t * si,uint32_t off,uint32_t len,const char * key)1062 spd_parse_ddr3_lrdimm_odt_r2(spd_info_t *si, uint32_t off, uint32_t len,
1063 const char *key)
1064 {
1065 spd_parse_ddr3_lrdimm_odt_common(si, off,
1066 SPD_KEY_DDR3_MB_R2_ODT0_RD, SPD_KEY_DDR3_MB_R2_ODT1_RD,
1067 SPD_KEY_DDR3_MB_R3_ODT0_RD, SPD_KEY_DDR3_MB_R3_ODT1_RD,
1068 SPD_KEY_DDR3_MB_R2_ODT0_WR, SPD_KEY_DDR3_MB_R2_ODT1_WR,
1069 SPD_KEY_DDR3_MB_R3_ODT0_WR, SPD_KEY_DDR3_MB_R3_ODT1_WR);
1070
1071 }
1072
1073 static void
spd_parse_ddr3_lrdimm_odt_r4(spd_info_t * si,uint32_t off,uint32_t len,const char * key)1074 spd_parse_ddr3_lrdimm_odt_r4(spd_info_t *si, uint32_t off, uint32_t len,
1075 const char *key)
1076 {
1077 spd_parse_ddr3_lrdimm_odt_common(si, off,
1078 SPD_KEY_DDR3_MB_R4_ODT0_RD, SPD_KEY_DDR3_MB_R4_ODT1_RD,
1079 SPD_KEY_DDR3_MB_R5_ODT0_RD, SPD_KEY_DDR3_MB_R5_ODT1_RD,
1080 SPD_KEY_DDR3_MB_R4_ODT0_WR, SPD_KEY_DDR3_MB_R4_ODT1_WR,
1081 SPD_KEY_DDR3_MB_R5_ODT0_WR, SPD_KEY_DDR3_MB_R5_ODT1_WR);
1082
1083 }
1084
1085 static void
spd_parse_ddr3_lrdimm_odt_r6(spd_info_t * si,uint32_t off,uint32_t len,const char * key)1086 spd_parse_ddr3_lrdimm_odt_r6(spd_info_t *si, uint32_t off, uint32_t len,
1087 const char *key)
1088 {
1089 spd_parse_ddr3_lrdimm_odt_common(si, off,
1090 SPD_KEY_DDR3_MB_R6_ODT0_RD, SPD_KEY_DDR3_MB_R6_ODT1_RD,
1091 SPD_KEY_DDR3_MB_R7_ODT0_RD, SPD_KEY_DDR3_MB_R7_ODT1_RD,
1092 SPD_KEY_DDR3_MB_R6_ODT0_WR, SPD_KEY_DDR3_MB_R6_ODT1_WR,
1093 SPD_KEY_DDR3_MB_R7_ODT0_WR, SPD_KEY_DDR3_MB_R7_ODT1_WR);
1094 }
1095
1096 static const spd_value_map_t spd_ddr3_rtt_wr_map[] = {
1097 { SPD_DDR3_LRDIMM_RTT_WR_DIS, SPD_TERM_DISABLED, false },
1098 { SPD_DDR3_LRDIMM_RTT_WR_60R, 60, false },
1099 { SPD_DDR3_LRDIMM_RTT_WR_120R, 120, false },
1100 };
1101
1102 static const spd_value_map_t spd_ddr3_rtt_nom_map[] = {
1103 { SPD_DDR3_LRDIMM_RTT_NOM_DIS, SPD_TERM_DISABLED, false },
1104 { SPD_DDR3_LRDIMM_RTT_NOM_60R, 60, false },
1105 { SPD_DDR3_LRDIMM_RTT_NOM_120R, 120, false },
1106 { SPD_DDR3_LRDIMM_RTT_NOM_40R, 40, false },
1107 { SPD_DDR3_LRDIMM_RTT_NOM_20R, 20, false },
1108 { SPD_DDR3_LRDIMM_RTT_NOM_30R, 30, false },
1109 };
1110
1111 static const spd_value_map_t spd_ddr3_dram_imp_map[] = {
1112 { SPD_DDR3_LRDIMM_RTT_IMP_40R, 40, false },
1113 { SPD_DDR3_LRDIMM_RTT_IMP_34R, 34, false }
1114 };
1115
1116 static void
spd_parse_ddr3_lrdimm_rtt(spd_info_t * si,uint32_t off,uint32_t len,const char * key)1117 spd_parse_ddr3_lrdimm_rtt(spd_info_t *si, uint32_t off, uint32_t len,
1118 const char *key)
1119 {
1120 const uint8_t d800 = si->si_data[off];
1121 const uint8_t d1333 = si->si_data[off + SPD_DDR3_LRDIMM_STRIDE];
1122 const uint8_t d1866 = si->si_data[off + SPD_DDR3_LRDIMM_STRIDE * 2];
1123 const uint8_t imp[3] = { SPD_DDR3_LRDIMM_RTT_IMP(d800),
1124 SPD_DDR3_LRDIMM_RTT_IMP(d1333), SPD_DDR3_LRDIMM_RTT_IMP(d1866) };
1125 const uint8_t nom[3] = { SPD_DDR3_LRDIMM_RTT_NOM(d800),
1126 SPD_DDR3_LRDIMM_RTT_NOM(d1333), SPD_DDR3_LRDIMM_RTT_NOM(d1866) };
1127 const uint8_t wr[3] = { SPD_DDR3_LRDIMM_RTT_WR(d800),
1128 SPD_DDR3_LRDIMM_RTT_WR(d1333), SPD_DDR3_LRDIMM_RTT_WR(d1866) };
1129
1130 spd_insert_map_array(si, SPD_KEY_DDR3_DRAM_DS, imp, ARRAY_SIZE(imp),
1131 spd_ddr3_dram_imp_map, ARRAY_SIZE(spd_ddr3_dram_imp_map));
1132 spd_insert_map_array(si, SPD_KEY_DDR3_RTT_NOM, nom, ARRAY_SIZE(nom),
1133 spd_ddr3_rtt_nom_map, ARRAY_SIZE(spd_ddr3_rtt_nom_map));
1134 spd_insert_map_array(si, SPD_KEY_DDR3_RTT_WRT, wr, ARRAY_SIZE(wr),
1135 spd_ddr3_rtt_wr_map, ARRAY_SIZE(spd_ddr3_rtt_wr_map));
1136 }
1137
1138 /*
1139 * Parse the delay that is spread out amongst three registers, each of which are
1140 * two apart. These are for 1.5V, 1.35, and 1.25V each.
1141 */
1142 static void
spd_parse_ddr3_lrdimm_mod_delay(spd_info_t * si,uint32_t off,uint32_t len,const char * key)1143 spd_parse_ddr3_lrdimm_mod_delay(spd_info_t *si, uint32_t off, uint32_t len,
1144 const char *key)
1145 {
1146 const uint8_t d1v5 = si->si_data[off];
1147 const uint8_t d1v35 = si->si_data[off + 2];
1148 const uint8_t d1v25 = si->si_data[off + 4];
1149 uint64_t delay[3] = { d1v25 * SPD_DDR3_MTB_PS, d1v35 * SPD_DDR3_MTB_PS,
1150 d1v5 * SPD_DDR3_MTB_PS };
1151
1152 spd_nvl_insert_u64_array(si, key, delay, ARRAY_SIZE(delay));
1153 }
1154
1155 static const spd_parse_t spd_ddr3_lrdimm[] = {
1156 { .sp_off = SPD_DDR3_LRDIMM_HEIGHT, .sp_key = SPD_KEY_MOD_HEIGHT,
1157 .sp_parse = spd_parse_height },
1158 { .sp_off = SPD_DDR3_LRDIMM_THICK, .sp_parse = spd_parse_thickness },
1159 { .sp_off = SPD_DDR3_LRDIMM_REF, .sp_parse = spd_parse_ddr3_design },
1160 { .sp_off = SPD_DDR3_LRDIMM_ATTR,
1161 .sp_parse = spd_parse_ddr3_lrdimm_attr },
1162 { .sp_off = SPD_DDR3_LRDIMM_MB_REV, .sp_key = SPD_KEY_DEV_DB_REV,
1163 .sp_parse = spd_parse_dram_step },
1164 { .sp_off = SPD_DDR3_LRDIMM_MB_MFG_ID0, .sp_len = 2,
1165 .sp_parse = spd_parse_ddr3_lrdimm_mb },
1166 { .sp_off = SPD_DDR3_LRDIMM_TCDS,
1167 .sp_parse = spd_parse_ddr3_lrdimm_tcds },
1168 { .sp_off = SPD_DDR3_LRDIMM_CKDS,
1169 .sp_parse = spd_parse_ddr3_lrdimm_ckds },
1170 { .sp_off = SPD_DDR3_LRDIMM_EXTD,
1171 .sp_parse = spd_parse_ddr3_lrdimm_ext_delay },
1172 { .sp_off = SPD_DDR3_LRDIMM_ADDD_CSY,
1173 .sp_parse = spd_parse_ddr3_lrdimm_add_delay_csy },
1174 { .sp_off = SPD_DDR3_LRDIMM_ADDD_ODT,
1175 .sp_parse = spd_parse_ddr3_lrdimm_add_delay_odt },
1176 { .sp_off = SPD_DDR3_LRDIMM_MDQ_800,
1177 .sp_len = SPD_DDR3_LRDIMM_MDQ_1866 - SPD_DDR3_LRDIMM_MDQ_800 + 1,
1178 .sp_parse = spd_parse_ddr3_lrdimm_mdq },
1179 { .sp_off = SPD_DDR3_LRDIMM_ODT_R0_800,
1180 .sp_len = SPD_DDR3_LRDIMM_ODT_R0_1866 -
1181 SPD_DDR3_LRDIMM_ODT_R0_800 + 1,
1182 .sp_parse = spd_parse_ddr3_lrdimm_odt_r0 },
1183 { .sp_off = SPD_DDR3_LRDIMM_ODT_R2_800,
1184 .sp_len = SPD_DDR3_LRDIMM_ODT_R2_1866 -
1185 SPD_DDR3_LRDIMM_ODT_R2_800 + 1,
1186 .sp_parse = spd_parse_ddr3_lrdimm_odt_r2 },
1187 { .sp_off = SPD_DDR3_LRDIMM_ODT_R4_800,
1188 .sp_len = SPD_DDR3_LRDIMM_ODT_R4_1866 -
1189 SPD_DDR3_LRDIMM_ODT_R4_800 + 1,
1190 .sp_parse = spd_parse_ddr3_lrdimm_odt_r4 },
1191 { .sp_off = SPD_DDR3_LRDIMM_ODT_R6_800,
1192 .sp_len = SPD_DDR3_LRDIMM_ODT_R6_1866 -
1193 SPD_DDR3_LRDIMM_ODT_R6_800 + 1,
1194 .sp_parse = spd_parse_ddr3_lrdimm_odt_r6 },
1195 { .sp_off = SPD_DDR3_LRDIMM_RTT_800,
1196 .sp_len = SPD_DDR3_LRDIMM_RTT_1866 - SPD_DDR3_LRDIMM_RTT_800 + 1,
1197 .sp_parse = spd_parse_ddr3_lrdimm_rtt },
1198 { .sp_off = SPD_DDR3_LRDIMM_MIN_DELAY_1V5,
1199 .sp_key = SPD_KEY_DDR3_MOD_MIN_DELAY,
1200 .sp_len = SPD_DDR3_LRDIMM_MIN_DELAY_1V25 -
1201 SPD_DDR3_LRDIMM_MIN_DELAY_1V5 + 1,
1202 .sp_parse = spd_parse_ddr3_lrdimm_mod_delay },
1203 { .sp_off = SPD_DDR3_LRDIMM_MAX_DELAY_1V5,
1204 .sp_key = SPD_KEY_DDR3_MOD_MAX_DELAY,
1205 .sp_len = SPD_DDR3_LRDIMM_MAX_DELAY_1V25 -
1206 SPD_DDR3_LRDIMM_MAX_DELAY_1V5 + 1,
1207 .sp_parse = spd_parse_ddr3_lrdimm_mod_delay },
1208 { .sp_off = SPD_DDR3_LRDIMM_PERS, .sp_key = SPD_KEY_DDR3_MB_PERS,
1209 .sp_len = SPD_DDR3_LRDIMM_PERS_NBYTES,
1210 .sp_parse = spd_parse_u8_array }
1211 };
1212
1213 static void
spd_parse_ddr3_mod_specific(spd_info_t * si)1214 spd_parse_ddr3_mod_specific(spd_info_t *si)
1215 {
1216 uint32_t type;
1217
1218 if (nvlist_lookup_uint32(si->si_nvl, SPD_KEY_MOD_TYPE, &type) != 0)
1219 return;
1220
1221 switch (type) {
1222 case SPD_MOD_TYPE_UDIMM:
1223 case SPD_MOD_TYPE_SODIMM:
1224 case SPD_MOD_TYPE_MICRO_DIMM:
1225 case SPD_MOD_TYPE_MINI_UDIMM:
1226 case SPD_MOD_TYPE_16b_SO_DIMM:
1227 case SPD_MOD_TYPE_32b_SO_DIMM:
1228 case SPD_MOD_TYPE_72b_SO_UDIMM:
1229 spd_parse(si, spd_ddr3_udimm, ARRAY_SIZE(spd_ddr3_udimm));
1230 break;
1231 case SPD_MOD_TYPE_RDIMM:
1232 case SPD_MOD_TYPE_MINI_RDIMM:
1233 case SPD_MOD_TYPE_72b_SO_RDIMM:
1234 spd_parse(si, spd_ddr3_rdimm, ARRAY_SIZE(spd_ddr3_rdimm));
1235 break;
1236 case SPD_MOD_TYPE_72b_SO_CDIMM:
1237 case SPD_MOD_TYPE_MINI_CDIMM:
1238 spd_parse(si, spd_ddr3_cdimm, ARRAY_SIZE(spd_ddr3_cdimm));
1239 break;
1240 case SPD_MOD_TYPE_LRDIMM:
1241 spd_parse(si, spd_ddr3_lrdimm, ARRAY_SIZE(spd_ddr3_lrdimm));
1242 break;
1243 default:
1244 break;
1245 }
1246 }
1247
1248 void
spd_parse_ddr3(spd_info_t * si)1249 spd_parse_ddr3(spd_info_t *si)
1250 {
1251 if (SPD_DDR3_SPD_REV_ENC(si->si_data[SPD_DDR3_SPD_REV]) !=
1252 SPD_DDR3_SPD_REV_V1) {
1253 si->si_error = LIBJEDEC_SPD_UNSUP_REV;
1254 return;
1255 }
1256
1257 spd_parse(si, spd_ddr3_common, ARRAY_SIZE(spd_ddr3_common));
1258 spd_parse_ddr3_mod_specific(si);
1259 spd_parse(si, spd_ddr3_mfg, ARRAY_SIZE(spd_ddr3_mfg));
1260 }
1261