/ util / spd_tools / src / spd_gen / lp5.go
lp5.go
  1  /* SPDX-License-Identifier: GPL-2.0-or-later */
  2  package main
  3  
  4  import (
  5  	"encoding/json"
  6  	"fmt"
  7  )
  8  
  9  /* ------------------------------------------------------------------------------------------ */
 10  /*                                     LP5-defined types                                      */
 11  /* ------------------------------------------------------------------------------------------ */
 12  
 13  type lp5 struct {
 14  }
 15  
 16  type LP5MemAttributes struct {
 17  	/* Primary attributes - must be provided by JSON file for each part */
 18  	DensityPerDieGb    int
 19  	DiesPerPackage     int
 20  	BitWidthPerChannel int
 21  	RanksPerChannel    int
 22  	SpeedMbps          int
 23  
 24  	/*
 25  	 * All the following parameters are optional and required only if the part requires
 26  	 * special parameters as per the datasheet.
 27  	 */
 28  	LP5X bool
 29  
 30  	/* Timing parameters */
 31  	TRFCABNs   int
 32  	TRFCPBNs   int
 33  	TRPABMinNs int
 34  	TRPPBMinNs int
 35  	TCKMinPs   int
 36  	TAAMinPs   int
 37  	TRCDMinNs  int
 38  }
 39  
 40  type LP5DensityParams struct {
 41  	DensityEncoding          byte
 42  	RowAddressBitsx8Channel  int
 43  	RowAddressBitsx16Channel int
 44  	TRFCABNs                 int
 45  	TRFCPBNs                 int
 46  }
 47  
 48  type LP5SpeedParams struct {
 49  	defaultTCKMinPs int
 50  	MaxCASLatency   int
 51  }
 52  
 53  type LP5BankArchParams struct {
 54  	NumBanks         int
 55  	BankGroups       int
 56  	BurstAddressBits int
 57  }
 58  
 59  type LP5SPDAttribFunc func(*LP5MemAttributes) byte
 60  
 61  type LP5SPDAttribTableEntry struct {
 62  	constVal byte
 63  	getVal   LP5SPDAttribFunc
 64  }
 65  
 66  type LP5SetFunc func(*LP5MemAttributes) int
 67  
 68  type LP5Set struct {
 69  	SPDRevision           byte
 70  	getBankArch           LP5SetFunc
 71  	optionalFeatures      byte
 72  	otherOptionalFeatures byte
 73  	busWidthEncoding      byte
 74  	speedToTCKMinPs       map[int]int
 75  }
 76  
 77  /* ------------------------------------------------------------------------------------------ */
 78  /*                                         Constants                                          */
 79  /* ------------------------------------------------------------------------------------------ */
 80  
 81  const (
 82  	/* SPD Byte Index */
 83  	LP5SPDIndexSize                            = 0
 84  	LP5SPDIndexRevision                        = 1
 85  	LP5SPDIndexMemoryType                      = 2
 86  	LP5SPDIndexModuleType                      = 3
 87  	LP5SPDIndexDensityBanks                    = 4
 88  	LP5SPDIndexAddressing                      = 5
 89  	LP5SPDIndexPackageType                     = 6
 90  	LP5SPDIndexOptionalFeatures                = 7
 91  	LP5SPDIndexOtherOptionalFeatures           = 9
 92  	LP5SPDIndexModuleOrganization              = 12
 93  	LP5SPDIndexBusWidth                        = 13
 94  	LP5SPDIndexTimebases                       = 17
 95  	LP5SPDIndexTCKMin                          = 18
 96  	LP5SPDIndexTAAMin                          = 24
 97  	LP5SPDIndexTRCDMin                         = 26
 98  	LP5SPDIndexTRPABMin                        = 27
 99  	LP5SPDIndexTRPPBMin                        = 28
100  	LP5SPDIndexTRFCABMinLSB                    = 29
101  	LP5SPDIndexTRFCABMinMSB                    = 30
102  	LP5SPDIndexTRFCPBMinLSB                    = 31
103  	LP5SPDIndexTRFCPBMinMSB                    = 32
104  	LP5SPDIndexTRPPBMinFineOffset              = 120
105  	LP5SPDIndexTRPABMinFineOffset              = 121
106  	LP5SPDIndexTRCDMinFineOffset               = 122
107  	LP5SPDIndexTAAMinFineOffset                = 123
108  	LP5SPDIndexTCKMinFineOffset                = 125
109  	LP5SPDIndexManufacturerPartNumberStartByte = 329
110  	LP5SPDIndexManufacturerPartNumberEndByte   = 348
111  
112  	/* SPD Byte Value */
113  
114  	/*
115  	 * From JEDEC spec:
116  	 * 6:4 (Bytes total) = 2 (512 bytes)
117  	 * 3:0 (Bytes used) = 3 (384 bytes)
118  	 * Set to 0x23 for LPDDR5.
119  	 */
120  	LP5SPDValueSize = 0x23
121  
122  	/*
123  	 * Revision 1.0. Expected by ADL
124  	 */
125  	LP5SPDValueRevision1_0 = 0x10
126  	/*
127  	 * Revision 1.1. Expected by Mendocino
128  	 */
129  	LP5SPDValueRevision1_1 = 0x11
130  
131  	/*
132  	 * As per advisory #616599, ADL MRC expects LPDDR5 memory type = 0x13.
133  	 * From JEDEC spec, LPDDR5X memory type = 0x15.
134  	 */
135  	LP5SPDValueMemoryType  = 0x13
136  	LP5XSPDValueMemoryType = 0x15
137  
138  	/*
139  	 * From JEDEC spec:
140  	 * 7:7 (Hybrid) = 0 (Not hybrid)
141  	 * 6:4 (Hybrid media) = 000 (Not hybrid)
142  	 * 3:0 (Base Module Type) = 1110 (Non-DIMM solution)
143  	 *
144  	 * This is dependent on hardware design. LPDDR5 only has memory down solution.
145  	 * Hence this is not hybrid non-DIMM solution.
146  	 * Set to 0x0E.
147  	 */
148  	LP5SPDValueModuleType = 0x0e
149  
150  	/*
151  	 * From JEDEC spec:
152  	 * 3:2 (MTB) = 00 (0.125ns)
153  	 * 1:0 (FTB) = 00 (1ps)
154  	 * Set to 0x00.
155  	 */
156  	LP5SPDValueTimebases = 0x00
157  
158  	/* As per JEDEC spec, unused digits of manufacturer part number are left as blank. */
159  	LP5SPDValueManufacturerPartNumberBlank = 0x20
160  )
161  
162  const (
163  	// The column addresses are the same for x8 & x16 and for all Bank Architectures.
164  	LP5ColAddressBits = 6
165  )
166  
167  const (
168  	// LPDDR5 has a flexible bank architecture with three programmable bank modes: BG, 8B, 16B.
169  	LP5BGBankArch = iota
170  	LP58BBankArch
171  	LP516BBankArch
172  )
173  
174  /* ------------------------------------------------------------------------------------------ */
175  /*                                    Global variables                                        */
176  /* ------------------------------------------------------------------------------------------ */
177  
178  var LP5PlatformSetMap = map[int][]int{
179  	0: {PlatformPTL, PlatformMTL, PlatformADL},
180  	1: {PlatformPHX, PlatformMDN},
181  }
182  
183  var LP5SetInfo = map[int]LP5Set{
184  	0: {
185  		SPDRevision: LP5SPDValueRevision1_0,
186  		getBankArch: LP5GetBankArchSet0,
187  		/*
188  		 * From JEDEC spec:
189  		 * 5:4 (Maximum Activate Window) = 00 (8192 * tREFI)
190  		 * 3:0 (Maximum Activate Count) = 1000 (Unlimited MAC)
191  		 * Set to 0x08.
192  		 */
193  		optionalFeatures: 0x08,
194  		/*
195  		 * For ADL (as per advisory #616599):
196  		 * 7:5 (Number of system channels) = 000 (1 channel always)
197  		 * 4:3 (Bus width extension) = 00 (no ECC)
198  		 * 2:0 (Bus width) = 001 (x16 always)
199  		 * Set to 0x01.
200  		 */
201  		busWidthEncoding: 0x01,
202  		/*
203  		 * TCKMinPs:
204  		 * LPDDR5 has two clocks: the command/address clock (CK) and the data clock (WCK). They are
205  		 * related by the WCK:CK ratio, which can be either 4:1 or 2:1. On ADL, 4:1 is used.
206  		 * For ADL, the MRC expects the tCKmin to encode the CK cycle time.
207  		 *   tCKmin   = 1 / CK rate
208  		 *            = 1 / (WCK rate / WCK:CK)
209  		 *            = 1 / (speed grade / 2 / WCK:CK)      // "double data rate"
210  		 */
211  		speedToTCKMinPs: map[int]int{
212  			8533: 937,  /* 1 / (8533 / 2 / 4) */
213  			7500: 1066, /* 1 / (7500 / 2 / 4) */
214  			6400: 1250, /* 1 / (6400 / 2 / 4) */
215  			5500: 1455, /* 1 / (5500 / 2 / 4) */
216  		},
217  	},
218  	1: {
219  		SPDRevision: LP5SPDValueRevision1_1,
220  		getBankArch: LP5GetBankArchSet1,
221  		/*
222  		 * For Mendocino (as per advisory b/211510456):
223  		 * 5:4 (Maximum Activate Window) = 01 (4096 * tREFI)
224  		 * 3:0 (Maximum Activate Count) = 1000 (Unlimited MAC)
225  		 * Set to 0x18.
226  		 */
227  		optionalFeatures: 0x18,
228  		/*
229  		 * For Mendocino (as per advisory b/211510456):
230  		 * 7:6 (PPR) = 1 (Post Package Repair is supported)
231  		 * Set to 0x40.
232  		 */
233  		otherOptionalFeatures: 0x40,
234  		/*
235  		 * For Mendocino (as per advisory b/211510456):
236  		 * 7:5 (Number of system channels) = 000 (1 channel always)
237  		 * 4:3 (Bus width extension) = 00 (no ECC)
238  		 * 2:0 (Bus width) = 010 (x32 always)
239  		 * Set to 0x02.
240  		 */
241  		busWidthEncoding: 0x02,
242  	},
243  }
244  
245  var LP5PartAttributeMap = map[string]LP5MemAttributes{}
246  var LP5CurrSet int
247  
248  /*
249   * DensityEncoding: Maps the die density in Gb to the SPD encoding of the die density
250   * as per JESD 21-C.
251   *
252   * RowAddressBits: Maps the die density to the number of row address bits.
253   * Tables 6-11 in JESD209-5B (same for all three bank modes).
254   *
255   * TRFCABNs/TRFCPBNs: Maps the die density to the refresh timings.
256   * Tables 235 and 236 in JESD209-5B (same for all three bank modes).
257   */
258  var LP5DensityGbToSPDEncoding = map[int]LP5DensityParams{
259  	4: {
260  		DensityEncoding:          0x4,
261  		RowAddressBitsx8Channel:  15,
262  		RowAddressBitsx16Channel: 14,
263  		TRFCABNs:                 180,
264  		TRFCPBNs:                 90,
265  	},
266  	6: {
267  		DensityEncoding:          0xb,
268  		RowAddressBitsx8Channel:  16,
269  		RowAddressBitsx16Channel: 15,
270  		TRFCABNs:                 210,
271  		TRFCPBNs:                 120,
272  	},
273  	8: {
274  		DensityEncoding:          0x5,
275  		RowAddressBitsx8Channel:  16,
276  		RowAddressBitsx16Channel: 15,
277  		TRFCABNs:                 210,
278  		TRFCPBNs:                 120,
279  	},
280  	12: {
281  		DensityEncoding:          0x8,
282  		RowAddressBitsx8Channel:  17,
283  		RowAddressBitsx16Channel: 16,
284  		TRFCABNs:                 280,
285  		TRFCPBNs:                 140,
286  	},
287  	16: {
288  		DensityEncoding:          0x6,
289  		RowAddressBitsx8Channel:  17,
290  		RowAddressBitsx16Channel: 16,
291  		TRFCABNs:                 280,
292  		TRFCPBNs:                 140,
293  	},
294  	24: {
295  		DensityEncoding:          0x9,
296  		RowAddressBitsx8Channel:  18,
297  		RowAddressBitsx16Channel: 17,
298  		TRFCABNs:                 380,
299  		TRFCPBNs:                 190,
300  	},
301  	32: {
302  		DensityEncoding:          0x7,
303  		RowAddressBitsx8Channel:  18,
304  		RowAddressBitsx16Channel: 17,
305  		TRFCABNs:                 380,
306  		TRFCPBNs:                 190,
307  	},
308  }
309  
310  /*
311   * Maps the number of banks to the SPD encoding as per JESD 21-C.
312   */
313  var LP5NumBanksEncoding = map[int]byte{
314  	4:  0x0,
315  	8:  0x1,
316  	16: 0x2,
317  }
318  
319  /*
320   * Maps the Bank Group bits to the SPD encoding as per JESD 21-C.
321   */
322  var LP5BankGroupsEncoding = map[int]byte{
323  	1: 0x0,
324  	2: 0x1,
325  	4: 0x2,
326  }
327  
328  /*
329   * Maps the number of row address bits to the SPD encoding as per JESD 21-C.
330   */
331  var LP5RowAddressBitsEncoding = map[int]byte{
332  	14: 0x2,
333  	15: 0x3,
334  	16: 0x4,
335  	17: 0x5,
336  	18: 0x6,
337  }
338  
339  /*
340   * Maps the number of column address bits to the SPD encoding as per JESD 21-C.
341   */
342  var LP5ColAddressBitsEncoding = map[int]byte{
343  	9:  0x0,
344  	10: 0x1,
345  	11: 0x2,
346  	12: 0x3,
347  }
348  
349  var LP5BankArchToSPDEncoding = map[int]LP5BankArchParams{
350  	LP5BGBankArch: {
351  		NumBanks:         4,
352  		BankGroups:       4,
353  		BurstAddressBits: 4,
354  	},
355  	LP58BBankArch: {
356  		NumBanks:         8,
357  		BankGroups:       1,
358  		BurstAddressBits: 5,
359  	},
360  	LP516BBankArch: {
361  		NumBanks:         16,
362  		BankGroups:       1,
363  		BurstAddressBits: 4,
364  	},
365  }
366  
367  /*
368   * TCKMinPs:
369   * Data sheets recommend encoding the the WCK cycle time.
370   *   tCKmin   = 1 / WCK rate
371   *            = 1 / (speed grade / 2)      // "double data rate"
372   *
373   * MaxCASLatency:
374   * From Table 220 of JESD209-5B, using a 4:1 WCK:CK ratio and Set 0.
375   */
376  var LP5SpeedMbpsToSPDEncoding = map[int]LP5SpeedParams{
377  	8533: {
378  		defaultTCKMinPs: 234, /* 1 / (8533 / 2) */
379  		MaxCASLatency:   23,
380  	},
381  	7500: {
382  		defaultTCKMinPs: 266, /* 1 / (7500 / 2) */
383  		MaxCASLatency:   20,
384  	},
385  	6400: {
386  		defaultTCKMinPs: 312, /* 1 / (6400 / 2) */
387  		MaxCASLatency:   17,
388  	},
389  	5500: {
390  		defaultTCKMinPs: 363, /* 1 / (5500 / 2) */
391  		MaxCASLatency:   15,
392  	},
393  }
394  
395  var LP5SPDAttribTable = map[int]LP5SPDAttribTableEntry{
396  	LP5SPDIndexSize:                  {constVal: LP5SPDValueSize},
397  	LP5SPDIndexRevision:              {getVal: LP5EncodeSPDRevision},
398  	LP5SPDIndexMemoryType:            {getVal: LP5EncodeMemoryType},
399  	LP5SPDIndexModuleType:            {constVal: LP5SPDValueModuleType},
400  	LP5SPDIndexDensityBanks:          {getVal: LP5EncodeDensityBanks},
401  	LP5SPDIndexAddressing:            {getVal: LP5EncodeSdramAddressing},
402  	LP5SPDIndexPackageType:           {getVal: LP5EncodePackageType},
403  	LP5SPDIndexOptionalFeatures:      {getVal: LP5EncodeOptionalFeatures},
404  	LP5SPDIndexOtherOptionalFeatures: {getVal: LP5EncodeOtherOptionalFeatures},
405  	LP5SPDIndexModuleOrganization:    {getVal: LP5EncodeModuleOrganization},
406  	LP5SPDIndexBusWidth:              {getVal: LP5EncodeBusWidth},
407  	LP5SPDIndexTimebases:             {constVal: LP5SPDValueTimebases},
408  	LP5SPDIndexTCKMin:                {getVal: LP5EncodeTCKMin},
409  	LP5SPDIndexTCKMinFineOffset:      {getVal: LP5EncodeTCKMinFineOffset},
410  	LP5SPDIndexTAAMin:                {getVal: LP5EncodeTAAMin},
411  	LP5SPDIndexTAAMinFineOffset:      {getVal: LP5EncodeTAAMinFineOffset},
412  	LP5SPDIndexTRCDMin:               {getVal: LP5EncodeTRCDMin},
413  	LP5SPDIndexTRCDMinFineOffset:     {getVal: LP5EncodeTRCDMinFineOffset},
414  	LP5SPDIndexTRPABMin:              {getVal: LP5EncodeTRPABMin},
415  	LP5SPDIndexTRPABMinFineOffset:    {getVal: LP5EncodeTRPABMinFineOffset},
416  	LP5SPDIndexTRPPBMin:              {getVal: LP5EncodeTRPPBMin},
417  	LP5SPDIndexTRPPBMinFineOffset:    {getVal: LP5EncodeTRPPBMinFineOffset},
418  	LP5SPDIndexTRFCABMinLSB:          {getVal: LP5EncodeTRFCABMinLsb},
419  	LP5SPDIndexTRFCABMinMSB:          {getVal: LP5EncodeTRFCABMinMsb},
420  	LP5SPDIndexTRFCPBMinLSB:          {getVal: LP5EncodeTRFCPBMinLsb},
421  	LP5SPDIndexTRFCPBMinMSB:          {getVal: LP5EncodeTRFCPBMinMsb},
422  }
423  
424  /* ------------------------------------------------------------------------------------------ */
425  /*                                        Functions                                           */
426  /* ------------------------------------------------------------------------------------------ */
427  func LP5EncodeSPDRevision(memAttribs *LP5MemAttributes) byte {
428  	f, ok := LP5SetInfo[LP5CurrSet]
429  
430  	if ok == false {
431  		return 0
432  	}
433  
434  	return f.SPDRevision
435  }
436  
437  func LP5GetBankArchSet0(memAttribs *LP5MemAttributes) int {
438  	// ADL will use 8B mode for all parts.
439  	return LP58BBankArch
440  }
441  
442  func LP5GetBankArchSet1(memAttribs *LP5MemAttributes) int {
443  	/*
444  	 * Mendocino does not support 8B. It uses 16B Bank Architecture for speed <= 3200 Mbps.
445  	 * It uses BG Bank Architecture for speed > 3200 Mbps.
446  	 */
447  	if memAttribs.SpeedMbps <= 3200 {
448  		return LP516BBankArch
449  	}
450  	return LP5BGBankArch
451  }
452  
453  func LP5GetBankArch(memAttribs *LP5MemAttributes) int {
454  	f, ok := LP5SetInfo[LP5CurrSet]
455  
456  	if ok == false || f.getBankArch == nil {
457  		return LP5BGBankArch
458  	}
459  
460  	return f.getBankArch(memAttribs)
461  }
462  
463  func LP5GetNumBanks(memAttribs *LP5MemAttributes) int {
464  	return LP5BankArchToSPDEncoding[LP5GetBankArch(memAttribs)].NumBanks
465  }
466  
467  func LP5GetBankGroups(memAttribs *LP5MemAttributes) int {
468  	return LP5BankArchToSPDEncoding[LP5GetBankArch(memAttribs)].BankGroups
469  }
470  
471  func LP5EncodeMemoryType(memAttribs *LP5MemAttributes) byte {
472  	var b byte
473  
474  	// Mendocino supports LP5x, but doesn't support 0x15 as a memory type currently.
475  	// Temporary workaround until it's supported with ABL changes
476  	if memAttribs.LP5X && LP5CurrSet != 1 {
477  		b = LP5XSPDValueMemoryType
478  	} else {
479  		b = LP5SPDValueMemoryType
480  	}
481  	return b
482  }
483  
484  func LP5EncodeDensityBanks(memAttribs *LP5MemAttributes) byte {
485  	var b byte
486  
487  	// 3:0 Density per die.
488  	b = LP5DensityGbToSPDEncoding[memAttribs.DensityPerDieGb].DensityEncoding
489  
490  	// 5:4 Bank address bits.
491  	b |= LP5NumBanksEncoding[LP5GetNumBanks(memAttribs)] << 4
492  	// 7:6 Bank group bits.
493  	b |= LP5BankGroupsEncoding[LP5GetBankGroups(memAttribs)] << 6
494  
495  	return b
496  }
497  
498  func LP5GetBurstAddressBits(memAttribs *LP5MemAttributes) int {
499  	return LP5BankArchToSPDEncoding[LP5GetBankArch(memAttribs)].BurstAddressBits
500  }
501  
502  func LP5EncodeSdramAddressing(memAttribs *LP5MemAttributes) byte {
503  	var b byte
504  
505  	// 2:0 Column address bits.
506  	b = LP5ColAddressBitsEncoding[LP5ColAddressBits+LP5GetBurstAddressBits(memAttribs)]
507  
508  	// 5:3 Row address bits.
509  	density := memAttribs.DensityPerDieGb
510  	var rowAddressBits int
511  	if memAttribs.BitWidthPerChannel == 8 {
512  		rowAddressBits = LP5DensityGbToSPDEncoding[density].RowAddressBitsx8Channel
513  	} else {
514  		rowAddressBits = LP5DensityGbToSPDEncoding[density].RowAddressBitsx16Channel
515  	}
516  	b |= LP5RowAddressBitsEncoding[rowAddressBits] << 3
517  
518  	return b
519  }
520  
521  func LP5EncodePackageType(memAttribs *LP5MemAttributes) byte {
522  	var b byte
523  
524  	// 1:0 Signal loading index.
525  	b = 1
526  
527  	// 3:2 Channels per package.
528  	// Channels per package = package width (e.g. x32) / bitWidthPerChannel (x8 or x16).
529  	// This can equivalently be calculated as diesPerPackage / ranksPerChannel.
530  	// This calculation is used to avoid adding a redundant attribute for package width.
531  	channels := memAttribs.DiesPerPackage / memAttribs.RanksPerChannel
532  	b |= byte(channels>>1) << 2
533  
534  	// 6:4 Dies per package.
535  	b |= (byte(memAttribs.DiesPerPackage) - 1) << 4
536  
537  	// 7:7 Package type.
538  	var packageType byte
539  	if memAttribs.DiesPerPackage > 1 {
540  		packageType = 1 // Non-Monolithic
541  	} else {
542  		packageType = 0 // Monolithic
543  	}
544  	b |= packageType << 7
545  
546  	return b
547  }
548  
549  func LP5EncodeModuleOrganization(memAttribs *LP5MemAttributes) byte {
550  	var b byte
551  
552  	// 2:0 Device data width per channel
553  	b = byte(memAttribs.BitWidthPerChannel / 8)
554  
555  	// 5:3 Package ranks per channel
556  	b |= byte(memAttribs.RanksPerChannel-1) << 3
557  
558  	return b
559  }
560  
561  func LP5EncodeOptionalFeatures(memAttribs *LP5MemAttributes) byte {
562  	f, ok := LP5SetInfo[LP5CurrSet]
563  
564  	if ok == false {
565  		return 0
566  	}
567  
568  	return f.optionalFeatures
569  }
570  
571  func LP5EncodeOtherOptionalFeatures(memAttribs *LP5MemAttributes) byte {
572  	f, ok := LP5SetInfo[LP5CurrSet]
573  
574  	if ok == false {
575  		return 0
576  	}
577  
578  	return f.otherOptionalFeatures
579  }
580  
581  func LP5EncodeBusWidth(memAttribs *LP5MemAttributes) byte {
582  	f, ok := LP5SetInfo[LP5CurrSet]
583  
584  	if ok == false {
585  		return 0
586  	}
587  
588  	return f.busWidthEncoding
589  }
590  
591  func LP5GetTCKMinPs(memAttribs *LP5MemAttributes) int {
592  	f, ok := LP5SetInfo[LP5CurrSet]
593  
594  	if ok == false || f.speedToTCKMinPs == nil {
595  		return LP5SpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].defaultTCKMinPs
596  	}
597  
598  	tCKMinPs, ok := f.speedToTCKMinPs[memAttribs.SpeedMbps]
599  	if ok == false || tCKMinPs == 0 {
600  		fmt.Printf("TCKMinPs not defined for speed %d(Mbps) in LP5Set %d\n", memAttribs.SpeedMbps, LP5CurrSet)
601  	}
602  
603  	return tCKMinPs
604  }
605  
606  func LP5EncodeTCKMin(memAttribs *LP5MemAttributes) byte {
607  	return convPsToMtbByte(memAttribs.TCKMinPs)
608  }
609  
610  func LP5EncodeTCKMinFineOffset(memAttribs *LP5MemAttributes) byte {
611  	return convPsToFtbByte(memAttribs.TCKMinPs)
612  }
613  
614  func LP5EncodeTAAMin(memAttribs *LP5MemAttributes) byte {
615  	return convPsToMtbByte(memAttribs.TAAMinPs)
616  }
617  
618  func LP5EncodeTAAMinFineOffset(memAttribs *LP5MemAttributes) byte {
619  	return convPsToFtbByte(memAttribs.TAAMinPs)
620  }
621  
622  func LP5EncodeTRCDMin(memAttribs *LP5MemAttributes) byte {
623  	return convNsToMtbByte(memAttribs.TRCDMinNs)
624  }
625  
626  func LP5EncodeTRCDMinFineOffset(memAttribs *LP5MemAttributes) byte {
627  	return convNsToFtbByte(memAttribs.TRCDMinNs)
628  }
629  
630  func LP5EncodeTRPABMin(memAttribs *LP5MemAttributes) byte {
631  	return convNsToMtbByte(memAttribs.TRPABMinNs)
632  }
633  
634  func LP5EncodeTRPABMinFineOffset(memAttribs *LP5MemAttributes) byte {
635  	return convNsToFtbByte(memAttribs.TRPABMinNs)
636  }
637  
638  func LP5EncodeTRPPBMin(memAttribs *LP5MemAttributes) byte {
639  	return convNsToMtbByte(memAttribs.TRPPBMinNs)
640  }
641  
642  func LP5EncodeTRPPBMinFineOffset(memAttribs *LP5MemAttributes) byte {
643  	return convNsToFtbByte(memAttribs.TRPPBMinNs)
644  }
645  
646  func LP5EncodeTRFCABMinMsb(memAttribs *LP5MemAttributes) byte {
647  	return byte((convNsToMtb(memAttribs.TRFCABNs) >> 8) & 0xff)
648  }
649  
650  func LP5EncodeTRFCABMinLsb(memAttribs *LP5MemAttributes) byte {
651  	return byte(convNsToMtb(memAttribs.TRFCABNs) & 0xff)
652  }
653  
654  func LP5EncodeTRFCPBMinMsb(memAttribs *LP5MemAttributes) byte {
655  	return byte((convNsToMtb(memAttribs.TRFCPBNs) >> 8) & 0xff)
656  }
657  
658  func LP5EncodeTRFCPBMinLsb(memAttribs *LP5MemAttributes) byte {
659  	return byte(convNsToMtb(memAttribs.TRFCPBNs) & 0xff)
660  }
661  
662  func LP5UpdateTCKMin(memAttribs *LP5MemAttributes) {
663  	if memAttribs.TCKMinPs == 0 {
664  		memAttribs.TCKMinPs = LP5GetTCKMinPs(memAttribs)
665  	}
666  }
667  
668  func LP5UpdateTAAMin(memAttribs *LP5MemAttributes) {
669  	if memAttribs.TAAMinPs == 0 {
670  		maxCAS := LP5SpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].MaxCASLatency
671  		memAttribs.TAAMinPs = memAttribs.TCKMinPs * maxCAS
672  	}
673  }
674  
675  func LP5UpdateTRFCAB(memAttribs *LP5MemAttributes) {
676  	if memAttribs.TRFCABNs == 0 {
677  		memAttribs.TRFCABNs = LP5DensityGbToSPDEncoding[memAttribs.DensityPerDieGb].TRFCABNs
678  	}
679  }
680  
681  func LP5UpdateTRFCPB(memAttribs *LP5MemAttributes) {
682  	if memAttribs.TRFCPBNs == 0 {
683  		memAttribs.TRFCPBNs = LP5DensityGbToSPDEncoding[memAttribs.DensityPerDieGb].TRFCPBNs
684  	}
685  }
686  
687  func LP5UpdateTRCD(memAttribs *LP5MemAttributes) {
688  	if memAttribs.TRCDMinNs == 0 {
689  		/* Table 372 from JESD209-5B */
690  		memAttribs.TRCDMinNs = 18
691  	}
692  }
693  
694  func LP5UpdateTRPAB(memAttribs *LP5MemAttributes) {
695  	if memAttribs.TRPABMinNs == 0 {
696  		/* Table 372 from JESD209-5B */
697  		memAttribs.TRPABMinNs = 21
698  	}
699  }
700  
701  func LP5UpdateTRPPB(memAttribs *LP5MemAttributes) {
702  	if memAttribs.TRPPBMinNs == 0 {
703  		/* Table 372 from JESD209-5B */
704  		memAttribs.TRPPBMinNs = 18
705  	}
706  }
707  
708  func lp5UpdateMemoryAttributes(memAttribs *LP5MemAttributes) {
709  	LP5UpdateTCKMin(memAttribs)
710  	LP5UpdateTAAMin(memAttribs)
711  	LP5UpdateTRFCAB(memAttribs)
712  	LP5UpdateTRFCPB(memAttribs)
713  	LP5UpdateTRCD(memAttribs)
714  	LP5UpdateTRPAB(memAttribs)
715  	LP5UpdateTRPPB(memAttribs)
716  }
717  
718  func LP5ValidateDensity(density int) error {
719  	if _, ok := LP5DensityGbToSPDEncoding[density]; !ok {
720  		return fmt.Errorf("Incorrect density per die: %d Gb", density)
721  	}
722  	return nil
723  }
724  
725  func LP5ValidateDies(dies int) error {
726  	if dies != 2 && dies != 4 && dies != 8 {
727  		return fmt.Errorf("Incorrect dies: %d", dies)
728  	}
729  	return nil
730  }
731  
732  func LP5ValidateDataWidth(width int) error {
733  	if width != 8 && width != 16 {
734  		return fmt.Errorf("Incorrect bit width: %d", width)
735  	}
736  	return nil
737  }
738  
739  func LP5ValidateRanks(ranks int) error {
740  	if ranks != 1 && ranks != 2 {
741  		return fmt.Errorf("Incorrect ranks: %d", ranks)
742  	}
743  	return nil
744  }
745  
746  func LP5ValidateSpeed(speed int) error {
747  	if _, ok := LP5SpeedMbpsToSPDEncoding[speed]; !ok {
748  		return fmt.Errorf("Incorrect speed: %d Mbps", speed)
749  	}
750  	return nil
751  }
752  
753  func lp5ValidateMemPartAttributes(memAttribs *LP5MemAttributes) error {
754  	if err := LP5ValidateDensity(memAttribs.DensityPerDieGb); err != nil {
755  		return err
756  	}
757  	if err := LP5ValidateDies(memAttribs.DiesPerPackage); err != nil {
758  		return err
759  	}
760  	if err := LP5ValidateDataWidth(memAttribs.BitWidthPerChannel); err != nil {
761  		return err
762  	}
763  	if err := LP5ValidateRanks(memAttribs.RanksPerChannel); err != nil {
764  		return err
765  	}
766  	if err := LP5ValidateSpeed(memAttribs.SpeedMbps); err != nil {
767  		return err
768  	}
769  
770  	return nil
771  }
772  
773  func LP5IsManufacturerPartNumberByte(index int) bool {
774  	if index >= LP5SPDIndexManufacturerPartNumberStartByte &&
775  		index <= LP5SPDIndexManufacturerPartNumberEndByte {
776  		return true
777  	}
778  	return false
779  }
780  
781  /* ------------------------------------------------------------------------------------------ */
782  /*                                  Interface Functions                                       */
783  /* ------------------------------------------------------------------------------------------ */
784  
785  func (lp5) getSetMap() map[int][]int {
786  	return LP5PlatformSetMap
787  }
788  
789  func (lp5) addNewPart(name string, attribs interface{}) error {
790  	var lp5Attributes LP5MemAttributes
791  	eByte, err := json.Marshal(attribs)
792  	if err != nil {
793  		return err
794  	}
795  
796  	if err := json.Unmarshal(eByte, &lp5Attributes); err != nil {
797  		return err
798  	}
799  
800  	if err := lp5ValidateMemPartAttributes(&lp5Attributes); err != nil {
801  		return err
802  	}
803  
804  	LP5PartAttributeMap[name] = lp5Attributes
805  	return nil
806  }
807  
808  func (lp5) getSPDAttribs(name string, set int) (interface{}, error) {
809  	lp5Attributes := LP5PartAttributeMap[name]
810  
811  	LP5CurrSet = set
812  
813  	lp5UpdateMemoryAttributes(&lp5Attributes)
814  
815  	return lp5Attributes, nil
816  }
817  
818  func (lp5) getSPDLen() int {
819  	return 512
820  }
821  
822  func (lp5) getSPDByte(index int, attribs interface{}) byte {
823  	e, ok := LP5SPDAttribTable[index]
824  	if !ok {
825  		if LP5IsManufacturerPartNumberByte(index) {
826  			return LP5SPDValueManufacturerPartNumberBlank
827  		}
828  		return 0x00
829  	}
830  
831  	if e.getVal != nil {
832  		var lp5Attribs LP5MemAttributes
833  		lp5Attribs = attribs.(LP5MemAttributes)
834  		return e.getVal(&lp5Attribs)
835  	}
836  
837  	return e.constVal
838  }