1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2package main 3 4import ( 5 "encoding/json" 6 "fmt" 7 "strconv" 8 "strings" 9) 10 11/* ------------------------------------------------------------------------------------------ */ 12/* DDR4-defined types */ 13/* ------------------------------------------------------------------------------------------ */ 14 15type ddr4 struct { 16} 17 18type DDR4MemAttributes struct { 19 /* Primary attributes - must be provided by JSON file for each part */ 20 SpeedMTps int 21 CL_nRCD_nRP int 22 CapacityPerDieGb int 23 DiesPerPackage int 24 PackageBusWidth int 25 RanksPerPackage int 26 27 /* 28 * All the following parameters are optional and required only if the part requires 29 * special parameters as per the datasheet. 30 */ 31 /* Timing parameters */ 32 TAAMinPs int 33 TRCDMinPs int 34 TRPMinPs int 35 TRASMinPs int 36 TRCMinPs int 37 TCKMinPs int 38 TCKMaxPs int 39 TRFC1MinPs int 40 TRFC2MinPs int 41 TRFC4MinPs int 42 TFAWMinPs int 43 TRRDLMinPs int 44 TRRDSMinPs int 45 TCCDLMinPs int 46 TWRMinPs int 47 TWTRLMinPs int 48 TWTRSMinPs int 49 50 /* CAS */ 51 CASLatencies string 52 CASFirstByte byte 53 CASSecondByte byte 54 CASThirdByte byte 55 CASFourthByte byte 56 57 /* The following is for internal-use only and is not overridable */ 58 dieBusWidth int 59} 60 61type DDR4SpeedBinAttributes struct { 62 TRASMinPs int 63 TCKMaxPs int 64} 65 66type DDR4SPDMemAttribFunc func(*DDR4MemAttributes) byte 67 68type DDR4SPDAttribTableEntry struct { 69 constVal byte 70 getVal DDR4SPDMemAttribFunc 71} 72 73/* ------------------------------------------------------------------------------------------ */ 74/* Constants */ 75/* ------------------------------------------------------------------------------------------ */ 76 77const ( 78 /* SPD Byte Index */ 79 DDR4SPDIndexSize = 0 80 DDR4SPDIndexRevision = 1 81 DDR4SPDIndexMemoryType = 2 82 DDR4SPDIndexModuleType = 3 83 DDR4SPDIndexDensityBanks = 4 84 DDR4SPDIndexAddressing = 5 85 DDR4SPDIndexPackageType = 6 86 DDR4SPDIndexOptionalFeatures = 7 87 DDR4SPDIndexModuleOrganization = 12 88 DDR4SPDIndexBusWidth = 13 89 DDR4SPDIndexTimebases = 17 90 DDR4SPDIndexTCKMin = 18 91 DDR4SPDIndexTCKMax = 19 92 DDR4SPDIndexCASFirstByte = 20 93 DDR4SPDIndexCASSecondByte = 21 94 DDR4SPDIndexCASThirdByte = 22 95 DDR4SPDIndexCASFourthByte = 23 96 DDR4SPDIndexTAAMin = 24 97 DDR4SPDIndexTRCDMin = 25 98 DDR4SPDIndexTRPMin = 26 99 DDR4SPDIndexTRASRCMinMSNs = 27 100 DDR4SPDIndexTRASMinLsb = 28 101 DDR4SPDIndexTRCMinLsb = 29 102 DDR4SPDIndexTRFC1MinLsb = 30 103 DDR4SPDIndexTRFC1MinMsb = 31 104 DDR4SPDIndexTRFC2MinLsb = 32 105 DDR4SPDIndexTRFC2MinMsb = 33 106 DDR4SPDIndexTRFC4MinLsb = 34 107 DDR4SPDIndexTRFC4MinMsb = 35 108 DDR4SPDIndexTFAWMinMSN = 36 109 DDR4SPDIndexTFAWMinLsb = 37 110 DDR4SPDIndexTRRDSMin = 38 111 DDR4SPDIndexTRRDLMin = 39 112 DDR4SPDIndexTCCDLMin = 40 113 DDR4SPDIndexTWRMinMSN = 41 114 DDR4SPDIndexTWRMinLsb = 42 115 DDR4SPDIndexTWTRMinMSNs = 43 116 DDR4SPDIndexWTRSMinLsb = 44 117 DDR4SPDIndexWTRLMinLsb = 45 118 DDR4SPDIndexTCCDLMinFineOffset = 117 119 DDR4SPDIndexTRRDLMinFineOffset = 118 120 DDR4SPDIndexTRRDSMinFineOffset = 119 121 DDR4SPDIndexTRCMinFineOffset = 120 122 DDR4SPDIndexTRPMinFineOffset = 121 123 DDR4SPDIndexTRCDMinFineOffset = 122 124 DDR4SPDIndexTAAMinFineOffset = 123 125 DDR4SPDIndexTCKMaxFineOffset = 124 126 DDR4SPDIndexTCKMinFineOffset = 125 127 DDR4SPDIndexManufacturerPartNumberStartByte = 329 128 DDR4SPDIndexManufacturerPartNumberEndByte = 348 129 130 /* SPD Byte Value */ 131 132 /* 133 * From JEDEC spec: 134 * 6:4 (Bytes total) = 2 (512 bytes) 135 * 3:0 (Bytes used) = 3 (384 bytes) 136 * Set to 0x23 for DDR4. 137 */ 138 DDR4SPDValueSize = 0x23 139 140 /* 141 * From JEDEC spec: Revision 1.1 142 * Set to 0x11. 143 */ 144 DDR4SPDValueRevision = 0x11 145 146 /* DDR4 memory type = 0x0C */ 147 DDR4SPDValueMemoryType = 0x0C 148 149 /* 150 * From JEDEC spec: 151 * Module Type [0:3] : 152 * 0 = Undefined 153 * 1 = RDIMM (width = 133.35 mm nom) 154 * 2 = UDIMM (width = 133.35 mm nom) 155 * 3 = SO-DIMM (width = 68.60 mm nom) 156 * 4 = LRDIMM (width = 133.35 mm nom) 157 * 158 * DDR4 on TGL uses SO-DIMM type for for both memory down and DIMM config. 159 * Set to 0x03. 160 */ 161 DDR4SPDValueModuleType = 0x03 162 163 /* 164 * From JEDEC spec: 165 * 5:4 (Maximum Activate Window) = 00 (8192 * tREFI) 166 * 3:0 (Maximum Activate Count) = 1000 (Unlimited MAC) 167 * 168 * Needs to come from datasheet, but most parts seem to support unlimited MAC. 169 * MR#24 OP3 170 */ 171 DDR4SPDValueOptionalFeatures = 0x08 172 173 /* 174 * From JEDEC spec: 175 * 2:0 Primary Bus Width in Bits = 011 (x64 always) 176 * Set to 0x03. 177 */ 178 DDR4SPDValueModuleBusWidth = 0x03 179 180 /* 181 * From JEDEC spec: 182 * 3:2 (MTB) = 00 (0.125ns) 183 * 1:0 (FTB) = 00 (1ps) 184 * Set to 0x00. 185 */ 186 DDR4SPDValueTimebases = 0x00 187 188 /* CAS fourth byte: All bits are reserved */ 189 DDR4SPDValueCASFourthByte = 0x00 190 191 /* As per JEDEC spec, unused digits of manufacturer part number are left as blank. */ 192 DDR4SPDValueManufacturerPartNumberBlank = 0x20 193) 194 195const ( 196 /* First Byte */ 197 DDR4CAS9 = 1 << 2 198 DDR4CAS10 = 1 << 3 199 DDR4CAS11 = 1 << 4 200 DDR4CAS12 = 1 << 5 201 DDR4CAS13 = 1 << 6 202 DDR4CAS14 = 1 << 7 203 /* Second Byte */ 204 DDR4CAS15 = 1 << 0 205 DDR4CAS16 = 1 << 1 206 DDR4CAS17 = 1 << 2 207 DDR4CAS18 = 1 << 3 208 DDR4CAS19 = 1 << 4 209 DDR4CAS20 = 1 << 5 210 DDR4CAS21 = 1 << 6 211 DDR4CAS22 = 1 << 7 212 /* Third Byte */ 213 DDR4CAS24 = 1 << 1 214) 215 216const ( 217 /* 218 * As per Table 75 of Jedec spec 4.1.20-L-5 R29 v103: 219 * tWRMin = 15nS for all DDR4 Speed Bins 220 * Set to 15000 pS 221 */ 222 DDR4TimingValueTWRMinPs = 15000 223 224 /* 225 * As per Table 78 of Jedec spec 4.1.20-L-5 R29 v103: 226 * tWTR_SMin = 2.5nS for all DDR4 Speed Bins 227 * Set to 2500 pS 228 */ 229 DDR4TimingValueTWTRSMinPs = 2500 230 231 /* 232 * As per Table 80 of Jedec spec 4.1.20-L-5 R29 v103: 233 * tWTR_LMin = 7.5 nS for all DDR4 Speed Bins 234 * Set to 7500 pS 235 */ 236 DDR4TimingValueTWTRLMinPs = 7500 237) 238 239/* ------------------------------------------------------------------------------------------ */ 240/* Global variables */ 241/* ------------------------------------------------------------------------------------------ */ 242 243var DDR4PlatformSetMap = map[int][]int{ 244 0: {PlatformTGL, PlatformPCO}, 245} 246 247var DDR4PartAttributeMap = map[string]DDR4MemAttributes{} 248var DDR4CurrSet int 249 250/* This encodes the density in Gb to SPD low nibble value as per JESD 4.1.2.L-5 R29 */ 251var DDR4DensityGbToSPDEncoding = map[int]byte{ 252 2: 0x3, 253 4: 0x4, 254 8: 0x5, 255 16: 0x6, 256} 257 258/* 259 * Tables 4 thru Table 7 from JESD79-4C. 260 * Maps density per die to row-column encoding for a device with x8/x16 261 * physical channel. 262 */ 263var DDR4DensityGbx8x16DieCapacityToRowColumnEncoding = map[int]byte{ 264 2: 0x11, /* 14 rows, 10 columns */ 265 4: 0x19, /* 15 rows, 10 columns */ 266 8: 0x21, /* 16 rows, 10 columns */ 267 16: 0x29, /* 17 rows, 10 columns */ 268} 269 270/* 271 * Tables 169 & 170 in the JESD79-4C spec 272 * Maps die density to refresh timings. This is the same for x8 and x16 273 * devices. 274 */ 275 276/* maps die density to rcf1 timing in pico seconds */ 277var DDR4TRFC1Encoding = map[int]int{ 278 2: 160000, 279 4: 260000, 280 8: 350000, 281 16: 550000, 282} 283 284/* maps die density to rcf2 timing in pico seconds */ 285var DDR4TRFC2Encoding = map[int]int{ 286 2: 110000, 287 4: 160000, 288 8: 260000, 289 16: 350000, 290} 291 292/* maps die density to rcf4 timing in pico seconds */ 293var DDR4TRFC4Encoding = map[int]int{ 294 2: 90000, 295 4: 110000, 296 8: 160000, 297 16: 260000, 298} 299 300var DDR4SpeedBinToSPDEncoding = map[int]DDR4SpeedBinAttributes{ 301 1600: { 302 TRASMinPs: 35000, 303 TCKMaxPs: 1500, 304 }, 305 1866: { 306 TRASMinPs: 34000, 307 TCKMaxPs: 1250, 308 }, 309 2133: { 310 TRASMinPs: 33000, 311 TCKMaxPs: 1071, 312 }, 313 2400: { 314 TRASMinPs: 32000, 315 TCKMaxPs: 937, 316 }, 317 2666: { 318 TRASMinPs: 32000, 319 TCKMaxPs: 833, 320 }, 321 2933: { 322 TRASMinPs: 32000, 323 TCKMaxPs: 750, 324 }, 325 3200: { 326 TRASMinPs: 32000, 327 TCKMaxPs: 682, 328 }, 329} 330 331/* This takes memAttribs.PackageBusWidth as an index */ 332var DDR4PageSizefromBusWidthEncoding = map[int]int{ 333 8: 1, 334 16: 2, 335} 336 337var DDR4SpeedToTRRDSMinPsOneKPageSize = map[int]int{ 338 1600: 5000, 339 1866: 4200, 340 2133: 3700, 341 2400: 3300, 342 2666: 3000, 343 2933: 2700, 344 3200: 2500, 345} 346 347var DDR4SpeedToTRRDSMinPsTwoKPageSize = map[int]int{ 348 1600: 6000, 349 1866: 5300, 350 2133: 5300, 351 2400: 5300, 352 2666: 5300, 353 2933: 5300, 354 3200: 5300, 355} 356 357var DDR4SPDAttribTable = map[int]DDR4SPDAttribTableEntry{ 358 DDR4SPDIndexSize: {constVal: DDR4SPDValueSize}, 359 DDR4SPDIndexRevision: {constVal: DDR4SPDValueRevision}, 360 DDR4SPDIndexMemoryType: {constVal: DDR4SPDValueMemoryType}, 361 DDR4SPDIndexModuleType: {constVal: DDR4SPDValueModuleType}, 362 DDR4SPDIndexDensityBanks: {getVal: DDR4EncodeDensityBanks}, 363 DDR4SPDIndexAddressing: {getVal: DDR4EncodeSdramAddressing}, 364 DDR4SPDIndexPackageType: {getVal: DDR4EncodePackageType}, 365 DDR4SPDIndexOptionalFeatures: {constVal: DDR4SPDValueOptionalFeatures}, 366 DDR4SPDIndexModuleOrganization: {getVal: DDR4EncodeModuleOrganization}, 367 DDR4SPDIndexBusWidth: {constVal: DDR4SPDValueModuleBusWidth}, 368 DDR4SPDIndexTimebases: {constVal: DDR4SPDValueTimebases}, 369 DDR4SPDIndexTCKMin: {getVal: DDR4EncodeTCKMin}, 370 DDR4SPDIndexTCKMinFineOffset: {getVal: DDR4EncodeTCKMinFineOffset}, 371 DDR4SPDIndexTCKMax: {getVal: DDR4EncodeTCKMax}, 372 DDR4SPDIndexTCKMaxFineOffset: {getVal: DDR4EncodeTCKMaxFineOffset}, 373 DDR4SPDIndexCASFirstByte: {getVal: DDR4EncodeCASFirstByte}, 374 DDR4SPDIndexCASSecondByte: {getVal: DDR4EncodeCASSecondByte}, 375 DDR4SPDIndexCASThirdByte: {getVal: DDR4EncodeCASThirdByte}, 376 DDR4SPDIndexCASFourthByte: {getVal: DDR4EncodeCASFourthByte}, 377 DDR4SPDIndexTAAMin: {getVal: DDR4EncodeTAAMin}, 378 DDR4SPDIndexTAAMinFineOffset: {getVal: DDR4EncodeTAAMinFineOffset}, 379 DDR4SPDIndexTRCDMin: {getVal: DDR4EncodeTRCDMin}, 380 DDR4SPDIndexTRCDMinFineOffset: {getVal: DDR4EncodeTRCDMinFineOffset}, 381 DDR4SPDIndexTRPMin: {getVal: DDR4EncodeTRPMin}, 382 DDR4SPDIndexTRPMinFineOffset: {getVal: DDR4EncodeTRPMinFineOffset}, 383 DDR4SPDIndexTRASRCMinMSNs: {getVal: DDR4EncodeTRASRCMinMSNs}, 384 DDR4SPDIndexTRASMinLsb: {getVal: DDR4EncodeTRASMinLsb}, 385 DDR4SPDIndexTRCMinLsb: {getVal: DDR4EncodeTRCMinLsb}, 386 DDR4SPDIndexTRCMinFineOffset: {getVal: DDR4EncodeTRCMinFineOffset}, 387 DDR4SPDIndexTRFC1MinLsb: {getVal: DDR4EncodeTRFC1MinLsb}, 388 DDR4SPDIndexTRFC1MinMsb: {getVal: DDR4EncodeTRFC1MinMsb}, 389 DDR4SPDIndexTRFC2MinLsb: {getVal: DDR4EncodeTRFC2MinLsb}, 390 DDR4SPDIndexTRFC2MinMsb: {getVal: DDR4EncodeTRFC2MinMsb}, 391 DDR4SPDIndexTRFC4MinLsb: {getVal: DDR4EncodeTRFC4MinLsb}, 392 DDR4SPDIndexTRFC4MinMsb: {getVal: DDR4EncodeTRFC4MinMsb}, 393 DDR4SPDIndexTFAWMinMSN: {getVal: DDR4EncodeTFAWMinMSN}, 394 DDR4SPDIndexTFAWMinLsb: {getVal: DDR4EncodeTFAWMinLsb}, 395 DDR4SPDIndexTRRDSMin: {getVal: DDR4EncodeTRRDSMin}, 396 DDR4SPDIndexTRRDSMinFineOffset: {getVal: DDR4EncodeTRRDSMinFineOffset}, 397 DDR4SPDIndexTRRDLMin: {getVal: DDR4EncodeTRRDLMin}, 398 DDR4SPDIndexTRRDLMinFineOffset: {getVal: DDR4EncodeTRRDLMinFineOffset}, 399 DDR4SPDIndexTCCDLMin: {getVal: DDR4EncodeTCCDLMin}, 400 DDR4SPDIndexTCCDLMinFineOffset: {getVal: DDR4EncodeTCCDLMinFineOffset}, 401 DDR4SPDIndexTWRMinMSN: {getVal: DDR4EncodeTWRMinMSN}, 402 DDR4SPDIndexTWRMinLsb: {getVal: DDR4EncodeTWRMinLsb}, 403 DDR4SPDIndexTWTRMinMSNs: {getVal: DDR4EncodeTWTRMinMSNs}, 404 DDR4SPDIndexWTRSMinLsb: {getVal: DDR4EncodeTWTRSMinLsb}, 405 DDR4SPDIndexWTRLMinLsb: {getVal: DDR4EncodeTWTRLMinLsb}, 406} 407 408/* ------------------------------------------------------------------------------------------ */ 409/* Functions */ 410/* ------------------------------------------------------------------------------------------ */ 411 412func DDR4GetBankGroups(memAttribs *DDR4MemAttributes) byte { 413 var bg byte 414 415 switch memAttribs.PackageBusWidth { 416 case 8: 417 bg = 4 418 case 16: 419 if memAttribs.DiesPerPackage == 1 { 420 bg = 2 /* x16 SDP has 2 bank groups */ 421 } else { 422 bg = 4 /* x16 DDP has 4 bank groups */ 423 } 424 } 425 426 return bg 427} 428 429func DDR4EncodeBankGroups(bg byte) byte { 430 var val byte 431 432 switch bg { 433 case 2: 434 val = 1 435 case 4: 436 val = 2 437 } 438 439 return val << 6 440} 441 442func DDR4EncodeDensityBanks(memAttribs *DDR4MemAttributes) byte { 443 var b byte 444 445 b = DDR4DensityGbToSPDEncoding[memAttribs.CapacityPerDieGb] 446 b |= DDR4EncodeBankGroups(DDR4GetBankGroups(memAttribs)) 447 /* No need to encode banksPerGroup.it's always 4 ([4:5] = 0) */ 448 449 return b 450} 451 452func DDR4EncodeSdramAddressing(memAttribs *DDR4MemAttributes) byte { 453 var b byte 454 455 b = DDR4DensityGbx8x16DieCapacityToRowColumnEncoding[memAttribs.CapacityPerDieGb] 456 457 return b 458} 459 460func DDR4EncodePackageDeviceType(dies int) byte { 461 var b byte 462 463 if dies > 1 { 464 /* If more than one die, then this is a non-monolithic device. */ 465 b = 1 466 } else { 467 /* If only single die, then this is a monolithic device. */ 468 b = 0 469 } 470 471 return b << 7 472} 473 474func DDR4EncodeSignalLoadingFromDieCount(dies int) byte { 475 var loading byte 476 477 /* 478 * If die count = 1, signal loading = "not specified" = 0 479 * If die count > 1, signal loading = "multi" = 2 480 */ 481 if dies == 1 { 482 loading = 0 483 } else { 484 loading = 1 485 } 486 487 return loading 488} 489 490func DDR4EncodeDiesPerPackage(dies int) byte { 491 var b byte 492 493 b = DDR4EncodePackageDeviceType(dies) /* Monolithic / Non-monolithic device */ 494 b |= (byte(dies) - 1) << 4 495 496 return b 497} 498 499func DDR4EncodePackageType(memAttribs *DDR4MemAttributes) byte { 500 var b byte 501 502 b = DDR4EncodeDiesPerPackage(memAttribs.DiesPerPackage) 503 b |= DDR4EncodeSignalLoadingFromDieCount(memAttribs.DiesPerPackage) 504 505 return b 506} 507 508func DDR4EncodeDataWidth(bitWidthPerDevice int) byte { 509 var width byte 510 511 switch bitWidthPerDevice { 512 case 8: 513 width = 1 514 case 16: 515 width = 2 516 } 517 518 return width 519} 520 521func DDR4EncodeRanks(ranks int) byte { 522 var b byte 523 524 b = byte(ranks - 1) 525 526 return b << 3 527} 528 529func DDR4EncodeModuleOrganization(memAttribs *DDR4MemAttributes) byte { 530 var b byte 531 532 b = DDR4EncodeDataWidth(memAttribs.dieBusWidth) 533 b |= DDR4EncodeRanks(memAttribs.RanksPerPackage) 534 535 return b 536} 537 538func DDR4EncodeTCKMin(memAttribs *DDR4MemAttributes) byte { 539 return convPsToMtbByte(memAttribs.TCKMinPs) 540} 541 542func DDR4EncodeTCKMinFineOffset(memAttribs *DDR4MemAttributes) byte { 543 return convPsToFtbByte(memAttribs.TCKMinPs) 544} 545 546func DDR4EncodeTCKMax(memAttribs *DDR4MemAttributes) byte { 547 return convPsToMtbByte(memAttribs.TCKMaxPs) 548} 549 550func DDR4EncodeTCKMaxFineOffset(memAttribs *DDR4MemAttributes) byte { 551 return convPsToFtbByte(memAttribs.TCKMaxPs) 552} 553 554func DDR4EncodeTAAMin(memAttribs *DDR4MemAttributes) byte { 555 return convPsToMtbByte(memAttribs.TAAMinPs) 556} 557 558func DDR4EncodeTAAMinFineOffset(memAttribs *DDR4MemAttributes) byte { 559 return convPsToFtbByte(memAttribs.TAAMinPs) 560} 561 562func DDR4EncodeTRCDMin(memAttribs *DDR4MemAttributes) byte { 563 return convPsToMtbByte(memAttribs.TRCDMinPs) 564} 565 566func DDR4EncodeTRCDMinFineOffset(memAttribs *DDR4MemAttributes) byte { 567 return convPsToFtbByte(memAttribs.TRCDMinPs) 568} 569 570func DDR4EncodeTRPMin(memAttribs *DDR4MemAttributes) byte { 571 return convPsToMtbByte(memAttribs.TRPMinPs) 572} 573 574func DDR4EncodeTRCMinFineOffset(memAttribs *DDR4MemAttributes) byte { 575 return convPsToFtbByte(memAttribs.TRCMinPs) 576} 577 578func DDR4EncodeTRPMinFineOffset(memAttribs *DDR4MemAttributes) byte { 579 return convPsToFtbByte(memAttribs.TRPMinPs) 580} 581 582func DDR4EncodeTRASRCMinMSNs(memAttribs *DDR4MemAttributes) byte { 583 var b byte 584 585 b = byte((convPsToMtb(memAttribs.TRASMinPs) >> 4) & 0xf0) 586 b |= byte((convPsToMtb(memAttribs.TRCMinPs) >> 8) & 0x0f) 587 588 return b 589} 590 591func DDR4EncodeTRASMinLsb(memAttribs *DDR4MemAttributes) byte { 592 return byte(convPsToMtb(memAttribs.TRASMinPs) & 0xff) 593} 594 595func DDR4EncodeTRCMinLsb(memAttribs *DDR4MemAttributes) byte { 596 return byte(convPsToMtb(memAttribs.TRCMinPs) & 0xff) 597} 598 599func DDR4EncodeTRFC1MinLsb(memAttribs *DDR4MemAttributes) byte { 600 var mtb int 601 602 mtb = convPsToMtb(memAttribs.TRFC1MinPs) 603 604 return byte(mtb & 0xff) 605} 606 607func DDR4EncodeTRFC1MinMsb(memAttribs *DDR4MemAttributes) byte { 608 var mtb int 609 610 mtb = convPsToMtb(memAttribs.TRFC1MinPs) 611 612 return byte((mtb >> 8) & 0xff) 613} 614 615func DDR4EncodeTRFC2MinLsb(memAttribs *DDR4MemAttributes) byte { 616 var mtb int 617 618 mtb = convPsToMtb(memAttribs.TRFC2MinPs) 619 620 return byte(mtb & 0xff) 621} 622 623func DDR4EncodeTRFC2MinMsb(memAttribs *DDR4MemAttributes) byte { 624 var mtb int 625 626 mtb = convPsToMtb(memAttribs.TRFC2MinPs) 627 628 return byte((mtb >> 8) & 0xff) 629} 630 631func DDR4EncodeTRFC4MinLsb(memAttribs *DDR4MemAttributes) byte { 632 var mtb int 633 634 mtb = convPsToMtb(memAttribs.TRFC4MinPs) 635 636 return byte(mtb & 0xff) 637} 638 639func DDR4EncodeTRFC4MinMsb(memAttribs *DDR4MemAttributes) byte { 640 var mtb int 641 642 mtb = convPsToMtb(memAttribs.TRFC4MinPs) 643 644 return byte((mtb >> 8) & 0xff) 645} 646 647func DDR4EncodeTFAWMinMSN(memAttribs *DDR4MemAttributes) byte { 648 var mtb int 649 650 mtb = convPsToMtb(memAttribs.TFAWMinPs) 651 652 return byte((mtb >> 8) & 0x0f) 653} 654 655func DDR4EncodeTFAWMinLsb(memAttribs *DDR4MemAttributes) byte { 656 var mtb int 657 658 mtb = convPsToMtb(memAttribs.TFAWMinPs) 659 660 return byte(mtb & 0xff) 661} 662 663func DDR4EncodeCASFirstByte(memAttribs *DDR4MemAttributes) byte { 664 return memAttribs.CASFirstByte 665} 666 667func DDR4EncodeCASSecondByte(memAttribs *DDR4MemAttributes) byte { 668 return memAttribs.CASSecondByte 669} 670 671func DDR4EncodeCASThirdByte(memAttribs *DDR4MemAttributes) byte { 672 return memAttribs.CASThirdByte 673} 674 675func DDR4EncodeCASFourthByte(memAttribs *DDR4MemAttributes) byte { 676 return memAttribs.CASFourthByte 677} 678 679func DDR4EncodeTRRDSMin(memAttribs *DDR4MemAttributes) byte { 680 return convPsToMtbByte(memAttribs.TRRDSMinPs) 681} 682 683func DDR4EncodeTRRDSMinFineOffset(memAttribs *DDR4MemAttributes) byte { 684 return convPsToFtbByte(memAttribs.TRRDSMinPs) 685} 686 687func DDR4EncodeTRRDLMin(memAttribs *DDR4MemAttributes) byte { 688 return convPsToMtbByte(memAttribs.TRRDLMinPs) 689} 690 691func DDR4EncodeTRRDLMinFineOffset(memAttribs *DDR4MemAttributes) byte { 692 return convPsToFtbByte(memAttribs.TRRDLMinPs) 693} 694 695func DDR4EncodeTCCDLMin(memAttribs *DDR4MemAttributes) byte { 696 return convPsToMtbByte(memAttribs.TCCDLMinPs) 697} 698 699func DDR4EncodeTCCDLMinFineOffset(memAttribs *DDR4MemAttributes) byte { 700 return convPsToFtbByte(memAttribs.TCCDLMinPs) 701} 702 703func DDR4EncodeTWRMinMSN(memAttribs *DDR4MemAttributes) byte { 704 return byte((convPsToMtb(DDR4TimingValueTWRMinPs) >> 8) & 0x0f) 705} 706 707func DDR4EncodeTWRMinLsb(memAttribs *DDR4MemAttributes) byte { 708 return byte(convPsToMtb(DDR4TimingValueTWRMinPs) & 0xff) 709} 710 711func DDR4EncodeTWTRMinMSNs(memAttribs *DDR4MemAttributes) byte { 712 var b byte 713 714 b = byte((convPsToMtb(memAttribs.TWTRLMinPs) >> 4) & 0xf0) 715 b |= byte((convPsToMtb(memAttribs.TWTRSMinPs) >> 8) & 0x0f) 716 717 return b 718} 719 720func DDR4EncodeTWTRSMinLsb(memAttribs *DDR4MemAttributes) byte { 721 return byte(convPsToMtb(memAttribs.TWTRSMinPs) & 0xff) 722} 723 724func DDR4EncodeTWTRLMinLsb(memAttribs *DDR4MemAttributes) byte { 725 return byte(convPsToMtb(memAttribs.TWTRLMinPs) & 0xff) 726} 727 728func DDR4EncodeLatencies(latency int, memAttribs *DDR4MemAttributes) error { 729 switch latency { 730 case 9: 731 memAttribs.CASFirstByte |= DDR4CAS9 732 case 10: 733 memAttribs.CASFirstByte |= DDR4CAS10 734 case 11: 735 memAttribs.CASFirstByte |= DDR4CAS11 736 case 12: 737 memAttribs.CASFirstByte |= DDR4CAS12 738 case 13: 739 memAttribs.CASFirstByte |= DDR4CAS13 740 case 14: 741 memAttribs.CASFirstByte |= DDR4CAS14 742 case 15: 743 memAttribs.CASSecondByte |= DDR4CAS15 744 case 16: 745 memAttribs.CASSecondByte |= DDR4CAS16 746 case 17: 747 memAttribs.CASSecondByte |= DDR4CAS17 748 case 18: 749 memAttribs.CASSecondByte |= DDR4CAS18 750 case 19: 751 memAttribs.CASSecondByte |= DDR4CAS19 752 case 20: 753 memAttribs.CASSecondByte |= DDR4CAS20 754 case 21: 755 memAttribs.CASSecondByte |= DDR4CAS21 756 case 22: 757 memAttribs.CASSecondByte |= DDR4CAS22 758 case 24: 759 memAttribs.CASThirdByte |= DDR4CAS24 760 default: 761 fmt.Errorf("Incorrect CAS Latency: ", latency) 762 } 763 764 return nil 765} 766 767/* Default CAS Latencies from Speed Bin tables in JEDS79-4C */ 768func DDR4GetDefaultCASLatencies(memAttribs *DDR4MemAttributes) string { 769 var str string 770 771 switch memAttribs.SpeedMTps { 772 case 1600: 773 switch memAttribs.CL_nRCD_nRP { 774 case 10: 775 str = "9 10 11 12" 776 case 11: 777 str = "9 11 12" 778 case 12: 779 str = "10 12" 780 } 781 case 1866: 782 switch memAttribs.CL_nRCD_nRP { 783 case 12: 784 str = "9 10 12 13 14" 785 case 13: 786 str = "9 11 12 13 14" 787 case 14: 788 str = "10 12 14" 789 } 790 case 2133: 791 switch memAttribs.CL_nRCD_nRP { 792 case 14: 793 str = "9 10 12 14 15 16" 794 case 15: 795 str = "9 11 12 13 14 15 16" 796 case 16: 797 str = "10 12 14 16" 798 } 799 case 2400: 800 switch memAttribs.CL_nRCD_nRP { 801 case 15: 802 str = "9 10 12 14 15 16 17 18" 803 case 16: 804 str = "9 11 12 13 14 15 16 17 18" 805 case 17: 806 str = "10 11 12 13 14 15 16 17 18" 807 case 18: 808 str = "10 12 14 16 18" 809 } 810 case 2666: 811 switch memAttribs.CL_nRCD_nRP { 812 case 17: 813 str = "9 10 11 12 13 14 15 16 17 18 19 20" 814 case 18: 815 str = "9 10 11 12 13 14 15 16 17 18 19 20" 816 case 19: 817 str = "10 11 12 13 14 15 16 17 18 19 20" 818 case 20: 819 str = "10 12 14 16 18 20" 820 } 821 case 2933: 822 switch memAttribs.CL_nRCD_nRP { 823 case 19: 824 str = "9 10 11 12 13 14 15 16 17 18 19 20 21 22" 825 case 20: 826 str = "10 11 12 13 14 15 16 17 18 19 20 21 22" 827 case 21: 828 str = "10 11 12 13 14 15 16 17 18 19 20 21 22" 829 case 22: 830 str = "10 12 14 16 18 20 22" 831 } 832 case 3200: 833 switch memAttribs.CL_nRCD_nRP { 834 case 20: 835 str = "9 10 11 12 13 14 15 16 17 18 19 20 21 22 24" 836 case 22: 837 str = "10 11 12 13 14 15 16 17 18 19 20 21 22 24" 838 case 24: 839 str = "10 12 14 16 18 20 22 24" 840 } 841 } 842 843 return str 844} 845 846func DDR4UpdateDieBusWidth(memAttribs *DDR4MemAttributes) { 847 if memAttribs.PackageBusWidth == 16 && memAttribs.RanksPerPackage == 1 && 848 memAttribs.DiesPerPackage == 2 { 849 /* 850 * If a x16 part has 2 die with single rank, PackageBusWidth 851 * needs to be converted to match die bus width. 852 */ 853 memAttribs.dieBusWidth = 8 854 } else { 855 memAttribs.dieBusWidth = memAttribs.PackageBusWidth 856 } 857} 858 859func DDR4UpdateCAS(memAttribs *DDR4MemAttributes) error { 860 if len(memAttribs.CASLatencies) == 0 { 861 memAttribs.CASLatencies = DDR4GetDefaultCASLatencies(memAttribs) 862 } 863 864 latencies := strings.Fields(memAttribs.CASLatencies) 865 for i := 0; i < len(latencies); i++ { 866 latency, err := strconv.Atoi(latencies[i]) 867 if err != nil { 868 return fmt.Errorf("Unable to convert latency ", latencies[i]) 869 } 870 if err := DDR4EncodeLatencies(latency, memAttribs); err != nil { 871 return err 872 } 873 } 874 875 return nil 876} 877 878func DDR4GetTAAMinPs(memAttribs *DDR4MemAttributes) int { 879 return (memAttribs.CL_nRCD_nRP * 2000000) / memAttribs.SpeedMTps 880} 881 882func DDR4UpdateTAAMin(memAttribs *DDR4MemAttributes) { 883 if memAttribs.TAAMinPs == 0 { 884 memAttribs.TAAMinPs = DDR4GetTAAMinPs(memAttribs) 885 } 886} 887 888func DDR4UpdateTRCDMin(memAttribs *DDR4MemAttributes) { 889 /* tRCDmin is same as tAAmin for all cases */ 890 if memAttribs.TRCDMinPs == 0 { 891 memAttribs.TRCDMinPs = DDR4GetTAAMinPs(memAttribs) 892 } 893} 894 895func DDR4UpdateTRPMin(memAttribs *DDR4MemAttributes) { 896 /* tRPmin is same as tAAmin for all cases */ 897 if memAttribs.TRPMinPs == 0 { 898 memAttribs.TRPMinPs = DDR4GetTAAMinPs(memAttribs) 899 } 900} 901 902func DDR4UpdateTRASMin(memAttribs *DDR4MemAttributes) { 903 if memAttribs.TRASMinPs == 0 { 904 memAttribs.TRASMinPs = DDR4SpeedBinToSPDEncoding[memAttribs.SpeedMTps].TRASMinPs 905 } 906} 907 908func DDR4GetTRCMinPs(memAttribs *DDR4MemAttributes) int { 909 return memAttribs.TAAMinPs + memAttribs.TRASMinPs 910} 911 912func DDR4UpdateTRCMin(memAttribs *DDR4MemAttributes) { 913 if memAttribs.TRCMinPs == 0 { 914 memAttribs.TRCMinPs = DDR4GetTRCMinPs(memAttribs) 915 } 916} 917 918func DDR4GetDefaultTCKMinPs(memAttribs *DDR4MemAttributes) int { 919 /* value 2000000 = 2 * 1000000, where 1000000 is to convert mS to pS */ 920 return 2000000 / memAttribs.SpeedMTps 921} 922 923func DDR4UpdateTCK(memAttribs *DDR4MemAttributes) { 924 if memAttribs.TCKMinPs == 0 { 925 memAttribs.TCKMinPs = DDR4GetDefaultTCKMinPs(memAttribs) 926 } 927 if memAttribs.TCKMaxPs == 0 { 928 memAttribs.TCKMaxPs = DDR4SpeedBinToSPDEncoding[memAttribs.SpeedMTps].TCKMaxPs 929 } 930} 931 932func DDR4UpdateTWRMin(memAttribs *DDR4MemAttributes) { 933 if memAttribs.TWRMinPs == 0 { 934 memAttribs.TWRMinPs = DDR4TimingValueTWRMinPs 935 } 936} 937 938func DDR4UpdateTWTRMin(memAttribs *DDR4MemAttributes) { 939 if memAttribs.TWTRLMinPs == 0 { 940 memAttribs.TWTRLMinPs = DDR4TimingValueTWTRLMinPs 941 } 942 if memAttribs.TWTRSMinPs == 0 { 943 memAttribs.TWTRSMinPs = DDR4TimingValueTWTRSMinPs 944 } 945} 946 947/* 948 * Per Table 169 & Table 170 of Jedec JESD79-4C 949 * tFAW timing is based on : 950 * Speed bin and page size 951 */ 952func DDR4GetTFAWMinPs(memAttribs *DDR4MemAttributes) int { 953 var tFAWFixed int 954 955 if DDR4PageSizefromBusWidthEncoding[memAttribs.PackageBusWidth] == 1 { 956 switch memAttribs.SpeedMTps { 957 case 1600: 958 tFAWFixed = 25000 959 case 1866: 960 tFAWFixed = 23000 961 default: 962 tFAWFixed = 21000 963 } 964 } else if DDR4PageSizefromBusWidthEncoding[memAttribs.PackageBusWidth] == 2 { 965 switch memAttribs.SpeedMTps { 966 case 1600: 967 tFAWFixed = 35000 968 default: 969 tFAWFixed = 30000 970 } 971 } 972 973 return tFAWFixed 974} 975 976/* Update settings based on data sheet (json) supplied memory attributes */ 977 978func DDR4UpdateTFAWMin(memAttribs *DDR4MemAttributes) { 979 var tFAWFromTck int 980 981 if memAttribs.TFAWMinPs == 0 { 982 memAttribs.TFAWMinPs = DDR4GetTFAWMinPs(memAttribs) 983 } 984 985 switch DDR4PageSizefromBusWidthEncoding[memAttribs.PackageBusWidth] { 986 case 1: 987 tFAWFromTck = 20 * memAttribs.TCKMinPs 988 case 2: 989 tFAWFromTck = 28 * memAttribs.TCKMinPs 990 } 991 992 if memAttribs.TFAWMinPs < tFAWFromTck { 993 memAttribs.TFAWMinPs = tFAWFromTck 994 } 995} 996 997func DDR4UpdateTRFC1Min(memAttribs *DDR4MemAttributes) { 998 if memAttribs.TRFC1MinPs == 0 { 999 memAttribs.TRFC1MinPs = DDR4TRFC1Encoding[memAttribs.CapacityPerDieGb] 1000 } 1001} 1002 1003func DDR4UpdateTRFC2Min(memAttribs *DDR4MemAttributes) { 1004 if memAttribs.TRFC2MinPs == 0 { 1005 memAttribs.TRFC2MinPs = DDR4TRFC2Encoding[memAttribs.CapacityPerDieGb] 1006 } 1007} 1008 1009func DDR4UpdateTRFC4Min(memAttribs *DDR4MemAttributes) { 1010 if memAttribs.TRFC4MinPs == 0 { 1011 memAttribs.TRFC4MinPs = DDR4TRFC4Encoding[memAttribs.CapacityPerDieGb] 1012 } 1013} 1014 1015func DDR4GetTRRDLMinPs(memAttribs *DDR4MemAttributes) int { 1016 var tRRDLFixed int 1017 1018 /* 1019 * Per JESD79-4C Tables 169 & 170, tRRD_L is based on : 1020 * Speed bin and page size 1021 */ 1022 switch DDR4PageSizefromBusWidthEncoding[memAttribs.PackageBusWidth] { 1023 case 1: 1024 switch memAttribs.SpeedMTps { 1025 case 1600: 1026 tRRDLFixed = 6000 1027 default: 1028 tRRDLFixed = 5300 1029 } 1030 case 2: 1031 switch memAttribs.SpeedMTps { 1032 case 1600: 1033 tRRDLFixed = 7500 1034 default: 1035 tRRDLFixed = 6400 1036 } 1037 } 1038 1039 return tRRDLFixed 1040} 1041 1042func DDR4UpdateTRRDLMin(memAttribs *DDR4MemAttributes) { 1043 var tRRDLFromTck int 1044 1045 if memAttribs.TRRDLMinPs == 0 { 1046 memAttribs.TRRDLMinPs = DDR4GetTRRDLMinPs(memAttribs) 1047 } 1048 1049 tRRDLFromTck = 4 * memAttribs.TCKMinPs 1050 1051 if memAttribs.TRRDLMinPs < tRRDLFromTck { 1052 memAttribs.TRRDLMinPs = tRRDLFromTck 1053 } 1054} 1055 1056func DDR4GetTRRDSMinPs(memAttribs *DDR4MemAttributes) int { 1057 var tRRDFixed int 1058 1059 switch DDR4PageSizefromBusWidthEncoding[memAttribs.PackageBusWidth] { 1060 case 1: 1061 tRRDFixed = DDR4SpeedToTRRDSMinPsOneKPageSize[memAttribs.SpeedMTps] 1062 case 2: 1063 tRRDFixed = DDR4SpeedToTRRDSMinPsTwoKPageSize[memAttribs.SpeedMTps] 1064 } 1065 1066 return tRRDFixed 1067} 1068 1069func DDR4UpdateTRRDSMin(memAttribs *DDR4MemAttributes) { 1070 var tRRDFromTck int 1071 1072 if memAttribs.TRRDSMinPs == 0 { 1073 memAttribs.TRRDSMinPs = DDR4GetTRRDSMinPs(memAttribs) 1074 } 1075 1076 tRRDFromTck = 4 * memAttribs.TCKMinPs 1077 1078 if memAttribs.TRRDSMinPs < tRRDFromTck { 1079 memAttribs.TRRDSMinPs = tRRDFromTck 1080 } 1081} 1082 1083/* 1084 * Per JESD79-4C Tables 169 and 170, 1085 * tCCD_L is based on : 1086 * Speed Bin 1087 */ 1088func DDR4GetTCCDLMinPs(memAttribs *DDR4MemAttributes) int { 1089 var tCCDLFixed int 1090 1091 switch memAttribs.SpeedMTps { 1092 case 1600: 1093 tCCDLFixed = 6250 1094 case 1866: 1095 tCCDLFixed = 5355 1096 case 2133: 1097 tCCDLFixed = 5355 1098 default: 1099 tCCDLFixed = 5000 1100 } 1101 1102 return tCCDLFixed 1103} 1104 1105func DDR4UpdateTCCDLMin(memAttribs *DDR4MemAttributes) { 1106 var tCCDLFromTck int 1107 1108 if memAttribs.TCCDLMinPs == 0 { 1109 memAttribs.TCCDLMinPs = DDR4GetTCCDLMinPs(memAttribs) 1110 } 1111 1112 tCCDLFromTck = 5 * memAttribs.TCKMinPs 1113 1114 if memAttribs.TCCDLMinPs < tCCDLFromTck { 1115 memAttribs.TCCDLMinPs = tCCDLFromTck 1116 } 1117} 1118 1119func DDR4UpdateMemoryAttributes(memAttribs *DDR4MemAttributes) { 1120 DDR4UpdateDieBusWidth(memAttribs) 1121 DDR4UpdateTCK(memAttribs) 1122 DDR4UpdateTAAMin(memAttribs) 1123 DDR4UpdateTRCDMin(memAttribs) 1124 DDR4UpdateTRPMin(memAttribs) 1125 DDR4UpdateTRASMin(memAttribs) 1126 DDR4UpdateTRCMin(memAttribs) 1127 DDR4UpdateTWRMin(memAttribs) 1128 DDR4UpdateTWTRMin(memAttribs) 1129 DDR4UpdateCAS(memAttribs) 1130 DDR4UpdateTRFC1Min(memAttribs) 1131 DDR4UpdateTRFC2Min(memAttribs) 1132 DDR4UpdateTRFC4Min(memAttribs) 1133 DDR4UpdateTCCDLMin(memAttribs) 1134 DDR4UpdateTRRDSMin(memAttribs) 1135 DDR4UpdateTRRDLMin(memAttribs) 1136 DDR4UpdateTFAWMin(memAttribs) 1137} 1138 1139func DDR4ValidateSpeedMTps(speedBin int) error { 1140 if _, ok := DDR4SpeedBinToSPDEncoding[speedBin]; ok == false { 1141 return fmt.Errorf("Incorrect speed bin: DDR4-%d", speedBin) 1142 } 1143 return nil 1144} 1145 1146func DDR4ValidateCapacityPerDie(capacityPerDieGb int) error { 1147 if _, ok := DDR4DensityGbToSPDEncoding[capacityPerDieGb]; ok == false { 1148 return fmt.Errorf("Incorrect capacity per die: %d", capacityPerDieGb) 1149 } 1150 return nil 1151} 1152 1153func DDR4ValidateDiesPerPackage(dieCount int) error { 1154 if dieCount >= 1 && dieCount <= 2 { 1155 return nil 1156 } 1157 return fmt.Errorf("Incorrect dies per package count: %d", dieCount) 1158} 1159 1160func DDR4ValidatePackageBusWidth(width int) error { 1161 if width != 8 && width != 16 { 1162 return fmt.Errorf("Incorrect device bus width: %d", width) 1163 } 1164 return nil 1165} 1166 1167func DDR4ValidateRanksPerPackage(ranks int) error { 1168 if ranks >= 1 && ranks <= 2 { 1169 return nil 1170 } 1171 return fmt.Errorf("Incorrect package ranks: %d", ranks) 1172} 1173 1174func DDR4ValidateCASLatency(CL int) error { 1175 if CL >= 10 && CL <= 24 && CL != 23 { 1176 return nil 1177 } 1178 return fmt.Errorf("Incorrect CAS latency: %d", CL) 1179} 1180 1181func DDR4VerifySupportedCASLatencies(name string, memAttribs *DDR4MemAttributes) error { 1182 if memAttribs.CASLatencies == DDR4GetDefaultCASLatencies(memAttribs) { 1183 return fmt.Errorf("CASLatencies for %s already matches default,\nPlease remove CASLatencies override line from the %s part attributes in the global part list and regenerate SPD Manifest", name, name) 1184 } 1185 1186 return nil 1187} 1188 1189func DDR4ValidateMemPartAttributes(name string, memAttribs *DDR4MemAttributes) error { 1190 if err := DDR4ValidateSpeedMTps(memAttribs.SpeedMTps); err != nil { 1191 return err 1192 } 1193 if err := DDR4ValidateCapacityPerDie(memAttribs.CapacityPerDieGb); err != nil { 1194 return err 1195 } 1196 if err := DDR4ValidateDiesPerPackage(memAttribs.DiesPerPackage); err != nil { 1197 return err 1198 } 1199 if err := DDR4ValidatePackageBusWidth(memAttribs.PackageBusWidth); err != nil { 1200 return err 1201 } 1202 if err := DDR4ValidateRanksPerPackage(memAttribs.RanksPerPackage); err != nil { 1203 return err 1204 } 1205 if err := DDR4ValidateCASLatency(memAttribs.CL_nRCD_nRP); err != nil { 1206 return err 1207 } 1208 1209 /* If CAS Latency was supplied, make sure it doesn't match default value */ 1210 if len(memAttribs.CASLatencies) != 0 { 1211 if err := DDR4VerifySupportedCASLatencies(name, memAttribs); err != nil { 1212 return err 1213 } 1214 } 1215 1216 return nil 1217} 1218 1219func DDR4IsManufacturerPartNumberByte(index int) bool { 1220 if index >= DDR4SPDIndexManufacturerPartNumberStartByte && index <= DDR4SPDIndexManufacturerPartNumberEndByte { 1221 return true 1222 } 1223 return false 1224} 1225 1226/* ------------------------------------------------------------------------------------------ */ 1227/* Interface Functions */ 1228/* ------------------------------------------------------------------------------------------ */ 1229 1230func (ddr4) getSetMap() map[int][]int { 1231 return DDR4PlatformSetMap 1232} 1233 1234func (ddr4) addNewPart(name string, attribs interface{}) error { 1235 var ddr4MemAttribs DDR4MemAttributes 1236 eByte, err := json.Marshal(attribs) 1237 if err != nil { 1238 return err 1239 } 1240 1241 if err := json.Unmarshal(eByte, &ddr4MemAttribs); err != nil { 1242 return err 1243 } 1244 1245 if err := DDR4ValidateMemPartAttributes(name, &ddr4MemAttribs); err != nil { 1246 return err 1247 } 1248 1249 DDR4PartAttributeMap[name] = ddr4MemAttribs 1250 return nil 1251} 1252 1253func (ddr4) getSPDAttribs(name string, set int) (interface{}, error) { 1254 ddr4Attributes := DDR4PartAttributeMap[name] 1255 1256 DDR4CurrSet = set 1257 1258 DDR4UpdateMemoryAttributes(&ddr4Attributes) 1259 1260 return ddr4Attributes, nil 1261} 1262 1263func (ddr4) getSPDLen() int { 1264 return 512 1265} 1266 1267func (ddr4) getSPDByte(index int, attribs interface{}) byte { 1268 e, ok := DDR4SPDAttribTable[index] 1269 if ok == false { 1270 if DDR4IsManufacturerPartNumberByte(index) { 1271 return DDR4SPDValueManufacturerPartNumberBlank 1272 } 1273 return 0x00 1274 } 1275 1276 if e.getVal != nil { 1277 var ddr4Attribs DDR4MemAttributes 1278 ddr4Attribs = attribs.(DDR4MemAttributes) 1279 return e.getVal(&ddr4Attribs) 1280 1281 } 1282 1283 return e.constVal 1284} 1285