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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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