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/* LP4x-defined types */ 13/* ------------------------------------------------------------------------------------------ */ 14 15type lp4x struct { 16} 17 18type LP4xMemAttributes struct { 19 /* Primary attributes - must be provided by JSON file for each part */ 20 DensityPerChannelGb int 21 Banks int 22 ChannelsPerDie int 23 DiesPerPackage int 24 BitWidthPerChannel int 25 RanksPerChannel int 26 SpeedMbps int 27 28 /* 29 * All the following parameters are optional and required only if the part requires 30 * special parameters as per the datasheet. 31 */ 32 /* Timing parameters */ 33 TRFCABNs int 34 TRFCPBNs int 35 TRPABMinNs int 36 TRPPBMinNs int 37 TCKMinPs int 38 TCKMaxPs int 39 TAAMinPs int 40 TRCDMinNs int 41 42 /* CAS */ 43 CASLatencies string 44 CASFirstByte byte 45 CASSecondByte byte 46 CASThirdByte byte 47} 48 49type LP4xSpeedParams struct { 50 TCKMinPs int 51 TCKMaxPs int 52 CASLatenciesx16Channel string 53 CASLatenciesx8Channel string 54} 55 56type LP4xRefreshTimings struct { 57 TRFCABNs int 58 TRFCPBNs int 59} 60 61type LP4xSPDAttribFunc func(*LP4xMemAttributes) byte 62 63type LP4xSPDAttribTableEntry struct { 64 constVal byte 65 getVal LP4xSPDAttribFunc 66} 67 68type LP4xSetFunc func(*LP4xMemAttributes) int 69 70type LP4xSet struct { 71 getMRCDensity LP4xSetFunc 72 getDiesPerPackage LP4xSetFunc 73 busWidthEncoding byte 74 normalizeAttribs LP4xSetFunc 75} 76 77/* ------------------------------------------------------------------------------------------ */ 78/* Constants */ 79/* ------------------------------------------------------------------------------------------ */ 80 81const ( 82 /* SPD Byte Index */ 83 LP4xSPDIndexSize = 0 84 LP4xSPDIndexRevision = 1 85 LP4xSPDIndexMemoryType = 2 86 LP4xSPDIndexModuleType = 3 87 LP4xSPDIndexDensityBanks = 4 88 LP4xSPDIndexAddressing = 5 89 LP4xSPDIndexPackageType = 6 90 LP4xSPDIndexOptionalFeatures = 7 91 LP4xSPDIndexModuleOrganization = 12 92 LP4xSPDIndexBusWidth = 13 93 LP4xSPDIndexTimebases = 17 94 LP4xSPDIndexTCKMin = 18 95 LP4xSPDIndexTCKMax = 19 96 LP4xSPDIndexCASFirstByte = 20 97 LP4xSPDIndexCASSecondByte = 21 98 LP4xSPDIndexCASThirdByte = 22 99 LP4xSPDIndexCASFourthByte = 23 100 LP4xSPDIndexTAAMin = 24 101 LP4xSPDIndexReadWriteLatency = 25 102 LP4xSPDIndexTRCDMin = 26 103 LP4xSPDIndexTRPABMin = 27 104 LP4xSPDIndexTRPPBMin = 28 105 LP4xSPDIndexTRFCABMinLSB = 29 106 LP4xSPDIndexTRFCABMinMSB = 30 107 LP4xSPDIndexTRFCPBMinLSB = 31 108 LP4xSPDIndexTRFCPBMinMSB = 32 109 LP4xSPDIndexTRPPBMinFineOffset = 120 110 LP4xSPDIndexTRPABMinFineOffset = 121 111 LP4xSPDIndexTRCDMinFineOffset = 122 112 LP4xSPDIndexTAAMinFineOffset = 123 113 LP4xSPDIndexTCKMaxFineOffset = 124 114 LP4xSPDIndexTCKMinFineOffset = 125 115 LP4xSPDIndexManufacturerPartNumberStartByte = 329 116 LP4xSPDIndexManufacturerPartNumberEndByte = 348 117 118 /* SPD Byte Value */ 119 120 /* 121 * From JEDEC spec: 122 * 6:4 (Bytes total) = 2 (512 bytes) 123 * 3:0 (Bytes used) = 3 (384 bytes) 124 * Set to 0x23 for LPDDR4x. 125 */ 126 LP4xSPDValueSize = 0x23 127 128 /* 129 * From JEDEC spec: Revision 1.1 130 * Set to 0x11. 131 */ 132 LP4xSPDValueRevision = 0x11 133 134 /* LPDDR4x memory type = 0x11 */ 135 LP4xSPDValueMemoryType = 0x11 136 137 /* 138 * From JEDEC spec: 139 * 7:7 (Hybrid) = 0 (Not hybrid) 140 * 6:4 (Hybrid media) = 000 (Not hybrid) 141 * 3:0 (Base Module Type) = 1110 (Non-DIMM solution) 142 * 143 * This is dependent on hardware design. LPDDR4x only has memory down solution. 144 * Hence this is not hybrid non-DIMM solution. 145 * Set to 0x0E. 146 */ 147 LP4xSPDValueModuleType = 0x0e 148 149 /* 150 * From JEDEC spec: 151 * 5:4 (Maximum Activate Window) = 00 (8192 * tREFI) 152 * 3:0 (Maximum Activate Count) = 1000 (Unlimited MAC) 153 * 154 * Needs to come from datasheet, but most parts seem to support unlimited MAC. 155 * MR#24 OP3 156 */ 157 LP4xSPDValueOptionalFeatures = 0x08 158 159 /* 160 * From JEDEC spec: 161 * 3:2 (MTB) = 00 (0.125ns) 162 * 1:0 (FTB) = 00 (1ps) 163 * Set to 0x00. 164 */ 165 LP4xSPDValueTimebases = 0x00 166 167 /* CAS fourth byte: All bits are reserved */ 168 LP4xSPDValueCASFourthByte = 0x00 169 170 /* Write Latency Set A and Read Latency DBI-RD disabled. */ 171 LP4xSPDValueReadWriteLatency = 0x00 172 173 /* As per JEDEC spec, unused digits of manufacturer part number are left as blank. */ 174 LP4xSPDValueManufacturerPartNumberBlank = 0x20 175) 176 177const ( 178 /* First Byte */ 179 LP4xCAS6 = 1 << 1 180 LP4xCAS10 = 1 << 4 181 LP4xCAS14 = 1 << 7 182 /* Second Byte */ 183 LP4xCAS16 = 1 << 0 184 LP4xCAS20 = 1 << 2 185 LP4xCAS22 = 1 << 3 186 LP4xCAS24 = 1 << 4 187 LP4xCAS26 = 1 << 5 188 LP4xCAS28 = 1 << 6 189 /* Third Byte */ 190 LP4xCAS32 = 1 << 0 191 LP4xCAS36 = 1 << 2 192 LP4xCAS40 = 1 << 4 193) 194 195const ( 196 /* 197 * JEDEC spec says that TCKmax should be 100ns for all speed grades. 198 * 100ns in MTB units comes out to be 0x320. But since this is a byte field, set it to 199 * 0xFF i.e. 31.875ns. 200 */ 201 LP4xTCKMaxPsDefault = 31875 202) 203 204/* ------------------------------------------------------------------------------------------ */ 205/* Global variables */ 206/* ------------------------------------------------------------------------------------------ */ 207 208var LP4xPlatformSetMap = map[int][]int{ 209 0: {PlatformTGL, PlatformADL}, 210 1: {PlatformJSL, PlatformCZN}, 211} 212 213var LP4xSetInfo = map[int]LP4xSet{ 214 0: { 215 getMRCDensity: LP4xGetMRCDensitySet0, 216 getDiesPerPackage: LP4xGetDiesPerPackageSet0, 217 /* 218 * As per advisory 616599: 219 * 7:5 (Number of system channels) = 000 (1 channel always) 220 * 2:0 (Bus width) = 001 (x16 always) 221 * Set to 0x01. 222 */ 223 busWidthEncoding: 0x01, 224 normalizeAttribs: LP4xNormalizeAttribsSet0, 225 }, 226 1: { 227 getMRCDensity: LP4xGetMRCDensitySet1, 228 getDiesPerPackage: LP4xGetDiesPerPackageSet1, 229 /* 230 * As per advisory 610202: 231 * 7:5 (Number of system channels) = 001 (2 channel always) 232 * 2:0 (Bus width) = 010 (x32 always) 233 * Set to 0x22. 234 */ 235 busWidthEncoding: 0x22, 236 }, 237} 238 239var LP4xPartAttributeMap = map[string]LP4xMemAttributes{} 240var LP4xCurrSet int 241 242/* This encodes the density in Gb to SPD values as per JESD 21-C */ 243var LP4xDensityGbToSPDEncoding = map[int]byte{ 244 4: 0x4, 245 6: 0xb, 246 8: 0x5, 247 12: 0x8, 248 16: 0x6, 249 24: 0x9, 250 32: 0x7, 251} 252 253/* 254 * Table 5 from JESD209-4C. 255 * Maps density per physical channel to row-column encoding as per JESD 21-C for a device with 256 * x8 physical channel. 257 */ 258var LP4xDensityGbx8ChannelToRowColumnEncoding = map[int]byte{ 259 3: 0x21, /* 16 rows, 10 columns */ 260 4: 0x21, /* 16 rows, 10 columns */ 261 6: 0x29, /* 17 rows, 10 columns */ 262 8: 0x29, /* 17 rows, 10 columns */ 263 12: 0x31, /* 18 rows, 10 columns */ 264 16: 0x31, /* 18 rows, 10 columns */ 265} 266 267/* 268 * Table 3 from JESD209-4C. 269 * Maps density per physical channel to row-column encoding as per JESD 21-C for a device with 270 * x16 physical channel. 271 */ 272var LP4xDensityGbx16ChannelToRowColumnEncoding = map[int]byte{ 273 4: 0x19, /* 15 rows, 10 columns */ 274 6: 0x21, /* 16 rows, 10 columns */ 275 8: 0x21, /* 16 rows, 10 columns */ 276 12: 0x29, /* 17 rows, 10 columns */ 277 16: 0x29, /* 17 rows, 10 columns */ 278} 279 280/* 281 * Table 112 from JESD209-4C 282 * Maps density per physical channel to refresh timings. This is the same for x8 and x16 283 * devices. 284 */ 285var LP4xDensityGbPhysicalChannelToRefreshEncoding = map[int]LP4xRefreshTimings{ 286 3: { 287 TRFCABNs: 180, 288 TRFCPBNs: 90, 289 }, 290 4: { 291 TRFCABNs: 180, 292 TRFCPBNs: 90, 293 }, 294 6: { 295 TRFCABNs: 280, 296 TRFCPBNs: 140, 297 }, 298 8: { 299 TRFCABNs: 280, 300 TRFCPBNs: 140, 301 }, 302 12: { 303 TRFCABNs: 380, 304 TRFCPBNs: 190, 305 }, 306 16: { 307 TRFCABNs: 380, 308 TRFCPBNs: 190, 309 }, 310} 311 312var LP4xBankEncoding = map[int]byte{ 313 4: 0 << 4, 314 8: 1 << 4, 315} 316 317var LP4xSpeedMbpsToSPDEncoding = map[int]LP4xSpeedParams{ 318 4267: { 319 TCKMinPs: 468, /* 1/4267 * 2 */ 320 TCKMaxPs: LP4xTCKMaxPsDefault, 321 CASLatenciesx16Channel: "6 10 14 20 24 28 32 36", 322 CASLatenciesx8Channel: "6 10 16 22 26 32 36 40", 323 }, 324 3733: { 325 TCKMinPs: 535, /* 1/3733 * 2 */ 326 TCKMaxPs: LP4xTCKMaxPsDefault, 327 CASLatenciesx16Channel: "6 10 14 20 24 28 32", 328 CASLatenciesx8Channel: "6 10 16 22 26 32 36", 329 }, 330 3200: { 331 TCKMinPs: 625, /* 1/3200 * 2 */ 332 TCKMaxPs: LP4xTCKMaxPsDefault, 333 CASLatenciesx16Channel: "6 10 14 20 24 28", 334 CASLatenciesx8Channel: "6 10 16 22 26 32", 335 }, 336} 337 338var LP4xSPDAttribTable = map[int]LP4xSPDAttribTableEntry{ 339 LP4xSPDIndexSize: {constVal: LP4xSPDValueSize}, 340 LP4xSPDIndexRevision: {constVal: LP4xSPDValueRevision}, 341 LP4xSPDIndexMemoryType: {constVal: LP4xSPDValueMemoryType}, 342 LP4xSPDIndexModuleType: {constVal: LP4xSPDValueModuleType}, 343 LP4xSPDIndexDensityBanks: {getVal: LP4xEncodeDensityBanks}, 344 LP4xSPDIndexAddressing: {getVal: LP4xEncodeSdramAddressing}, 345 LP4xSPDIndexPackageType: {getVal: LP4xEncodePackageType}, 346 LP4xSPDIndexOptionalFeatures: {constVal: LP4xSPDValueOptionalFeatures}, 347 LP4xSPDIndexModuleOrganization: {getVal: LP4xEncodeModuleOrganization}, 348 LP4xSPDIndexBusWidth: {getVal: LP4xEncodeBusWidth}, 349 LP4xSPDIndexTimebases: {constVal: LP4xSPDValueTimebases}, 350 LP4xSPDIndexTCKMin: {getVal: LP4xEncodeTCKMin}, 351 LP4xSPDIndexTCKMax: {getVal: LP4xEncodeTCKMax}, 352 LP4xSPDIndexTCKMaxFineOffset: {getVal: LP4xEncodeTCKMaxFineOffset}, 353 LP4xSPDIndexTCKMinFineOffset: {getVal: LP4xEncodeTCKMinFineOffset}, 354 LP4xSPDIndexCASFirstByte: {getVal: LP4xEncodeCASFirstByte}, 355 LP4xSPDIndexCASSecondByte: {getVal: LP4xEncodeCASSecondByte}, 356 LP4xSPDIndexCASThirdByte: {getVal: LP4xEncodeCASThirdByte}, 357 LP4xSPDIndexCASFourthByte: {constVal: LP4xSPDValueCASFourthByte}, 358 LP4xSPDIndexTAAMin: {getVal: LP4xEncodeTAAMin}, 359 LP4xSPDIndexTAAMinFineOffset: {getVal: LP4xEncodeTAAMinFineOffset}, 360 LP4xSPDIndexReadWriteLatency: {constVal: LP4xSPDValueReadWriteLatency}, 361 LP4xSPDIndexTRCDMin: {getVal: LP4xEncodeTRCDMin}, 362 LP4xSPDIndexTRCDMinFineOffset: {getVal: LP4xEncodeTRCDMinFineOffset}, 363 LP4xSPDIndexTRPABMin: {getVal: LP4xEncodeTRPABMin}, 364 LP4xSPDIndexTRPABMinFineOffset: {getVal: LP4xEncodeTRPABMinFineOffset}, 365 LP4xSPDIndexTRPPBMin: {getVal: LP4xEncodeTRPPBMin}, 366 LP4xSPDIndexTRPPBMinFineOffset: {getVal: LP4xEncodeTRPPBMinFineOffset}, 367 LP4xSPDIndexTRFCABMinLSB: {getVal: LP4xEncodeTRFCABMinLsb}, 368 LP4xSPDIndexTRFCABMinMSB: {getVal: LP4xEncodeTRFCABMinMsb}, 369 LP4xSPDIndexTRFCPBMinLSB: {getVal: LP4xEncodeTRFCPBMinLsb}, 370 LP4xSPDIndexTRFCPBMinMSB: {getVal: LP4xEncodeTRFCPBMinMsb}, 371} 372 373/* ------------------------------------------------------------------------------------------ */ 374/* Functions */ 375/* ------------------------------------------------------------------------------------------ */ 376 377func LP4xGetMRCDensitySet0(memAttribs *LP4xMemAttributes) int { 378 /* 379 * Intel MRC on TGL/ADL expects density per logical channel to be encoded in 380 * SPDIndexDensityBanks. Logical channel on TGL/ADL is an x16 channel. 381 */ 382 return memAttribs.DensityPerChannelGb * 16 / memAttribs.BitWidthPerChannel 383} 384 385func LP4xGetMRCDensitySet1(memAttribs *LP4xMemAttributes) int { 386 /* 387 * Intel MRC on JSL expects density per die to be encoded in 388 * SPDIndexDensityBanks. 389 */ 390 return memAttribs.DensityPerChannelGb * memAttribs.ChannelsPerDie 391} 392 393func LP4xGetMRCDensity(memAttribs *LP4xMemAttributes) int { 394 f, ok := LP4xSetInfo[LP4xCurrSet] 395 396 if ok == false || f.getMRCDensity == nil { 397 return 0 398 } 399 400 return f.getMRCDensity(memAttribs) 401} 402 403func LP4xEncodeDensityBanks(memAttribs *LP4xMemAttributes) byte { 404 var b byte 405 406 b = LP4xDensityGbToSPDEncoding[LP4xGetMRCDensity(memAttribs)] 407 b |= LP4xBankEncoding[memAttribs.Banks] 408 409 return b 410} 411 412func LP4xEncodeSdramAddressing(memAttribs *LP4xMemAttributes) byte { 413 densityPerChannelGb := memAttribs.DensityPerChannelGb 414 if memAttribs.BitWidthPerChannel == 8 { 415 return LP4xDensityGbx8ChannelToRowColumnEncoding[densityPerChannelGb] 416 } else { 417 return LP4xDensityGbx16ChannelToRowColumnEncoding[densityPerChannelGb] 418 } 419 return 0 420} 421 422func LP4xEncodePackage(dies int) byte { 423 var temp byte 424 425 if dies > 1 { 426 /* If more than one die, then this is a non-monolithic device. */ 427 temp = 1 428 } else { 429 /* If only single die, then this is a monolithic device. */ 430 temp = 0 431 } 432 433 return temp << 7 434} 435 436func LP4xEncodeChannelsPerDie(channels int) byte { 437 var temp byte 438 439 temp = byte(channels >> 1) 440 441 return temp << 2 442} 443 444func LP4xGetDiesPerPackageSet0(memAttribs *LP4xMemAttributes) int { 445 /* Intel MRC expects logical dies to be encoded for TGL/ADL. */ 446 return memAttribs.ChannelsPerDie * memAttribs.RanksPerChannel * memAttribs.BitWidthPerChannel / 16 447} 448 449func LP4xGetDiesPerPackageSet1(memAttribs *LP4xMemAttributes) int { 450 /* Intel MRC expects physical dies to be encoded for JSL. */ 451 /* AMD PSP expects physical dies (ZQ balls) */ 452 return memAttribs.DiesPerPackage 453} 454 455/* Per JESD209-4C Dies = ZQ balls on the package */ 456/* Note that this can be different than the part's die count */ 457func LP4xEncodeDiesPerPackage(memAttribs *LP4xMemAttributes) byte { 458 var dies int = 0 459 460 f, ok := LP4xSetInfo[LP4xCurrSet] 461 if ok != false && f.getDiesPerPackage != nil { 462 dies = f.getDiesPerPackage(memAttribs) 463 } 464 465 b := LP4xEncodePackage(dies) /* Monolithic / Non-monolithic device */ 466 b |= (byte(dies) - 1) << 4 467 468 return b 469} 470 471func LP4xEncodePackageType(memAttribs *LP4xMemAttributes) byte { 472 var b byte 473 474 b |= LP4xEncodeChannelsPerDie(memAttribs.ChannelsPerDie) 475 b |= LP4xEncodeDiesPerPackage(memAttribs) 476 477 return b 478} 479 480func LP4xEncodeDataWidth(bitWidthPerChannel int) byte { 481 return byte(bitWidthPerChannel / 8) 482} 483 484func LP4xEncodeRanks(ranks int) byte { 485 var b byte 486 b = byte(ranks - 1) 487 return b << 3 488} 489 490func LP4xEncodeModuleOrganization(memAttribs *LP4xMemAttributes) byte { 491 var b byte 492 493 b = LP4xEncodeDataWidth(memAttribs.BitWidthPerChannel) 494 b |= LP4xEncodeRanks(memAttribs.RanksPerChannel) 495 496 return b 497} 498 499func LP4xEncodeBusWidth(memAttribs *LP4xMemAttributes) byte { 500 f, ok := LP4xSetInfo[LP4xCurrSet] 501 502 if ok == false { 503 return 0 504 } 505 506 return f.busWidthEncoding 507} 508 509func LP4xEncodeTCKMin(memAttribs *LP4xMemAttributes) byte { 510 return convPsToMtbByte(memAttribs.TCKMinPs) 511} 512 513func LP4xEncodeTCKMinFineOffset(memAttribs *LP4xMemAttributes) byte { 514 return convPsToFtbByte(memAttribs.TCKMinPs) 515} 516 517func LP4xEncodeTCKMax(memAttribs *LP4xMemAttributes) byte { 518 return convPsToMtbByte(memAttribs.TCKMaxPs) 519} 520 521func LP4xEncodeTCKMaxFineOffset(memAttribs *LP4xMemAttributes) byte { 522 return convPsToFtbByte(memAttribs.TCKMaxPs) 523} 524 525func LP4xEncodeCASFirstByte(memAttribs *LP4xMemAttributes) byte { 526 return memAttribs.CASFirstByte 527} 528 529func LP4xEncodeCASSecondByte(memAttribs *LP4xMemAttributes) byte { 530 return memAttribs.CASSecondByte 531} 532 533func LP4xEncodeCASThirdByte(memAttribs *LP4xMemAttributes) byte { 534 return memAttribs.CASThirdByte 535} 536 537func LP4xEncodeTAAMin(memAttribs *LP4xMemAttributes) byte { 538 return convPsToMtbByte(memAttribs.TAAMinPs) 539} 540 541func LP4xEncodeTAAMinFineOffset(memAttribs *LP4xMemAttributes) byte { 542 return convPsToFtbByte(memAttribs.TAAMinPs) 543} 544 545func LP4xEncodeTRCDMin(memAttribs *LP4xMemAttributes) byte { 546 return convNsToMtbByte(memAttribs.TRCDMinNs) 547} 548 549func LP4xEncodeTRCDMinFineOffset(memAttribs *LP4xMemAttributes) byte { 550 return convNsToFtbByte(memAttribs.TRCDMinNs) 551} 552 553func LP4xEncodeTRPABMin(memAttribs *LP4xMemAttributes) byte { 554 return convNsToMtbByte(memAttribs.TRPABMinNs) 555} 556 557func LP4xEncodeTRPABMinFineOffset(memAttribs *LP4xMemAttributes) byte { 558 return convNsToFtbByte(memAttribs.TRPABMinNs) 559} 560 561func LP4xEncodeTRPPBMin(memAttribs *LP4xMemAttributes) byte { 562 return convNsToMtbByte(memAttribs.TRPPBMinNs) 563} 564 565func LP4xEncodeTRPPBMinFineOffset(memAttribs *LP4xMemAttributes) byte { 566 return convNsToFtbByte(memAttribs.TRPPBMinNs) 567} 568 569func LP4xEncodeTRFCABMinMsb(memAttribs *LP4xMemAttributes) byte { 570 return byte((convNsToMtb(memAttribs.TRFCABNs) >> 8) & 0xff) 571} 572 573func LP4xEncodeTRFCABMinLsb(memAttribs *LP4xMemAttributes) byte { 574 return byte(convNsToMtb(memAttribs.TRFCABNs) & 0xff) 575} 576 577func LP4xEncodeTRFCPBMinMsb(memAttribs *LP4xMemAttributes) byte { 578 return byte((convNsToMtb(memAttribs.TRFCPBNs) >> 8) & 0xff) 579} 580 581func LP4xEncodeTRFCPBMinLsb(memAttribs *LP4xMemAttributes) byte { 582 return byte(convNsToMtb(memAttribs.TRFCPBNs) & 0xff) 583} 584 585func LP4xEncodeLatencies(latency int, memAttribs *LP4xMemAttributes) error { 586 switch latency { 587 case 6: 588 memAttribs.CASFirstByte |= LP4xCAS6 589 case 10: 590 memAttribs.CASFirstByte |= LP4xCAS10 591 case 14: 592 memAttribs.CASFirstByte |= LP4xCAS14 593 case 16: 594 memAttribs.CASSecondByte |= LP4xCAS16 595 case 20: 596 memAttribs.CASSecondByte |= LP4xCAS20 597 case 22: 598 memAttribs.CASSecondByte |= LP4xCAS22 599 case 24: 600 memAttribs.CASSecondByte |= LP4xCAS24 601 case 26: 602 memAttribs.CASSecondByte |= LP4xCAS26 603 case 28: 604 memAttribs.CASSecondByte |= LP4xCAS28 605 case 32: 606 memAttribs.CASThirdByte |= LP4xCAS32 607 case 36: 608 memAttribs.CASThirdByte |= LP4xCAS36 609 case 40: 610 memAttribs.CASThirdByte |= LP4xCAS40 611 default: 612 fmt.Errorf("Incorrect CAS Latency: ", latency) 613 } 614 615 return nil 616} 617 618func LP4xUpdateTCK(memAttribs *LP4xMemAttributes) { 619 if memAttribs.TCKMinPs == 0 { 620 memAttribs.TCKMinPs = LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].TCKMinPs 621 } 622 if memAttribs.TCKMaxPs == 0 { 623 memAttribs.TCKMaxPs = LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].TCKMaxPs 624 } 625} 626 627func LP4xGetCASLatencies(memAttribs *LP4xMemAttributes) string { 628 if memAttribs.BitWidthPerChannel == 16 { 629 return LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].CASLatenciesx16Channel 630 } else if memAttribs.BitWidthPerChannel == 8 { 631 return LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].CASLatenciesx8Channel 632 } 633 634 return "" 635} 636 637func LP4xUpdateCAS(memAttribs *LP4xMemAttributes) error { 638 if len(memAttribs.CASLatencies) == 0 { 639 memAttribs.CASLatencies = LP4xGetCASLatencies(memAttribs) 640 } 641 642 latencies := strings.Fields(memAttribs.CASLatencies) 643 for i := 0; i < len(latencies); i++ { 644 latency, err := strconv.Atoi(latencies[i]) 645 if err != nil { 646 return fmt.Errorf("Unable to convert latency ", latencies[i]) 647 } 648 if err := LP4xEncodeLatencies(latency, memAttribs); err != nil { 649 return err 650 } 651 } 652 return nil 653} 654 655func LP4xGetMinCAS(memAttribs *LP4xMemAttributes) (int, error) { 656 if (memAttribs.CASThirdByte & LP4xCAS40) != 0 { 657 return 40, nil 658 } 659 if (memAttribs.CASThirdByte & LP4xCAS36) != 0 { 660 return 36, nil 661 } 662 if (memAttribs.CASThirdByte & LP4xCAS32) != 0 { 663 return 32, nil 664 } 665 if (memAttribs.CASSecondByte & LP4xCAS28) != 0 { 666 return 28, nil 667 } 668 669 return 0, fmt.Errorf("Unexpected min CAS") 670} 671 672func LP4xUpdateTAAMin(memAttribs *LP4xMemAttributes) error { 673 if memAttribs.TAAMinPs == 0 { 674 minCAS, err := LP4xGetMinCAS(memAttribs) 675 if err != nil { 676 return err 677 } 678 memAttribs.TAAMinPs = memAttribs.TCKMinPs * minCAS 679 } 680 681 return nil 682} 683 684func LP4xUpdateTRFCAB(memAttribs *LP4xMemAttributes) { 685 if memAttribs.TRFCABNs == 0 { 686 memAttribs.TRFCABNs = LP4xDensityGbPhysicalChannelToRefreshEncoding[memAttribs.DensityPerChannelGb].TRFCABNs 687 } 688} 689 690func LP4xUpdateTRFCPB(memAttribs *LP4xMemAttributes) { 691 if memAttribs.TRFCPBNs == 0 { 692 memAttribs.TRFCPBNs = LP4xDensityGbPhysicalChannelToRefreshEncoding[memAttribs.DensityPerChannelGb].TRFCPBNs 693 } 694} 695 696func LP4xUpdateTRCD(memAttribs *LP4xMemAttributes) { 697 if memAttribs.TRCDMinNs == 0 { 698 /* JEDEC spec says max of 18ns */ 699 memAttribs.TRCDMinNs = 18 700 } 701} 702 703func LP4xUpdateTRPAB(memAttribs *LP4xMemAttributes) { 704 if memAttribs.TRPABMinNs == 0 { 705 /* JEDEC spec says max of 21ns */ 706 memAttribs.TRPABMinNs = 21 707 } 708} 709 710func LP4xUpdateTRPPB(memAttribs *LP4xMemAttributes) { 711 if memAttribs.TRPPBMinNs == 0 { 712 /* JEDEC spec says max of 18ns */ 713 memAttribs.TRPPBMinNs = 18 714 } 715} 716 717func LP4xNormalizeAttribsSet0(memAttribs *LP4xMemAttributes) int { 718 /* 719 * TGL does not really use physical organization of dies per package when 720 * generating the SPD. So, set it to 0 here so that deduplication ignores 721 * that field. 722 */ 723 memAttribs.DiesPerPackage = 0 724 725 return 0 726} 727 728func LP4xNormalizeMemoryAttributes(memAttribs *LP4xMemAttributes) { 729 f, ok := LP4xSetInfo[LP4xCurrSet] 730 731 if ok == false || f.normalizeAttribs == nil { 732 return 733 } 734 735 f.normalizeAttribs(memAttribs) 736} 737 738func Lp4xUpdateMemoryAttributes(memAttribs *LP4xMemAttributes) error { 739 LP4xUpdateTCK(memAttribs) 740 if err := LP4xUpdateCAS(memAttribs); err != nil { 741 return err 742 } 743 if err := LP4xUpdateTAAMin(memAttribs); err != nil { 744 return err 745 } 746 LP4xUpdateTRFCAB(memAttribs) 747 LP4xUpdateTRFCPB(memAttribs) 748 LP4xUpdateTRCD(memAttribs) 749 LP4xUpdateTRPAB(memAttribs) 750 LP4xUpdateTRPPB(memAttribs) 751 752 LP4xNormalizeMemoryAttributes(memAttribs) 753 754 return nil 755} 756 757func LP4xValidateDensityx8Channel(densityPerChannelGb int) error { 758 if _, ok := LP4xDensityGbx8ChannelToRowColumnEncoding[densityPerChannelGb]; ok == false { 759 return fmt.Errorf("Incorrect x8 density: %d Gb", densityPerChannelGb) 760 } 761 return nil 762} 763 764func LP4xValidateDensityx16Channel(densityPerChannelGb int) error { 765 if _, ok := LP4xDensityGbx16ChannelToRowColumnEncoding[densityPerChannelGb]; ok == false { 766 return fmt.Errorf("Incorrect x16 density: %d Gb", densityPerChannelGb) 767 } 768 return nil 769} 770 771func LP4xValidateDensity(memAttribs *LP4xMemAttributes) error { 772 if memAttribs.BitWidthPerChannel == 8 { 773 return LP4xValidateDensityx8Channel(memAttribs.DensityPerChannelGb) 774 } else if memAttribs.BitWidthPerChannel == 16 { 775 return LP4xValidateDensityx16Channel(memAttribs.DensityPerChannelGb) 776 } 777 778 return fmt.Errorf("No density table for this bit width: %d", memAttribs.BitWidthPerChannel) 779} 780 781func LP4xValidateBanks(banks int) error { 782 if banks != 4 && banks != 8 { 783 return fmt.Errorf("Incorrect banks: %d", banks) 784 } 785 return nil 786} 787 788func LP4xValidateChannels(channels int) error { 789 if channels != 1 && channels != 2 && channels != 4 { 790 return fmt.Errorf("Incorrect channels per die: %d ", channels) 791 } 792 return nil 793} 794 795func LP4xValidateDataWidth(width int) error { 796 if width != 8 && width != 16 { 797 return fmt.Errorf("Incorrect bit width: %d", width) 798 } 799 return nil 800} 801 802func LP4xValidateRanks(ranks int) error { 803 if ranks != 1 && ranks != 2 { 804 return fmt.Errorf("Incorrect ranks: %d", ranks) 805 } 806 return nil 807} 808 809func LP4xValidateSpeed(speed int) error { 810 if _, ok := LP4xSpeedMbpsToSPDEncoding[speed]; ok == false { 811 return fmt.Errorf("Incorrect speed: %d Mbps", speed) 812 } 813 return nil 814} 815 816func Lp4xValidateMemPartAttributes(memAttribs *LP4xMemAttributes) error { 817 if err := LP4xValidateBanks(memAttribs.Banks); err != nil { 818 return err 819 } 820 if err := LP4xValidateChannels(memAttribs.ChannelsPerDie); err != nil { 821 return err 822 } 823 if err := LP4xValidateDataWidth(memAttribs.BitWidthPerChannel); err != nil { 824 return err 825 } 826 if err := LP4xValidateDensity(memAttribs); err != nil { 827 return err 828 } 829 if err := LP4xValidateRanks(memAttribs.RanksPerChannel); err != nil { 830 return err 831 } 832 if err := LP4xValidateSpeed(memAttribs.SpeedMbps); err != nil { 833 return err 834 } 835 836 return nil 837} 838 839func LP4xIsManufacturerPartNumberByte(index int) bool { 840 if index >= LP4xSPDIndexManufacturerPartNumberStartByte && 841 index <= LP4xSPDIndexManufacturerPartNumberEndByte { 842 return true 843 } 844 return false 845} 846 847/* ------------------------------------------------------------------------------------------ */ 848/* Interface Functions */ 849/* ------------------------------------------------------------------------------------------ */ 850 851func (lp4x) getSetMap() map[int][]int { 852 return LP4xPlatformSetMap 853} 854 855func (lp4x) addNewPart(name string, attribs interface{}) error { 856 var lp4xAttributes LP4xMemAttributes 857 eByte, err := json.Marshal(attribs) 858 if err != nil { 859 return err 860 } 861 862 if err := json.Unmarshal(eByte, &lp4xAttributes); err != nil { 863 return err 864 } 865 866 if err := Lp4xValidateMemPartAttributes(&lp4xAttributes); err != nil { 867 return err 868 } 869 870 LP4xPartAttributeMap[name] = lp4xAttributes 871 return nil 872} 873 874func (lp4x) getSPDAttribs(name string, set int) (interface{}, error) { 875 lp4xAttributes := LP4xPartAttributeMap[name] 876 877 LP4xCurrSet = set 878 879 if err := Lp4xUpdateMemoryAttributes(&lp4xAttributes); err != nil { 880 return lp4xAttributes, err 881 } 882 883 return lp4xAttributes, nil 884} 885 886func (lp4x) getSPDLen() int { 887 return 512 888} 889 890func (lp4x) getSPDByte(index int, attribs interface{}) byte { 891 e, ok := LP4xSPDAttribTable[index] 892 if ok == false { 893 if LP4xIsManufacturerPartNumberByte(index) { 894 return LP4xSPDValueManufacturerPartNumberBlank 895 } 896 return 0x00 897 } 898 899 if e.getVal != nil { 900 var lp4xAttribs LP4xMemAttributes 901 lp4xAttribs = attribs.(LP4xMemAttributes) 902 return e.getVal(&lp4xAttribs) 903 } 904 905 return e.constVal 906} 907