xref: /aosp_15_r20/external/coreboot/util/spd_tools/src/spd_gen/ddr4.go (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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