util/spd_tools/spd_gen/lp5: Encode Optional SDRAM features
[coreboot.git] / util / spd_tools / src / spd_gen / lp5.go
blob351aba301320ddfbbd316fd96743f2fb9be4ed18
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 package main
4 import (
5 "encoding/json"
6 "fmt"
9 /* ------------------------------------------------------------------------------------------ */
10 /* LP5-defined types */
11 /* ------------------------------------------------------------------------------------------ */
13 type lp5 struct {
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
25 * All the following parameters are optional and required only if the part requires
26 * special parameters as per the datasheet.
28 /* Timing parameters */
29 TRFCABNs int
30 TRFCPBNs int
31 TRPABMinNs int
32 TRPPBMinNs int
33 TCKMinPs int
34 TAAMinPs int
35 TRCDMinNs int
38 type LP5DensityParams struct {
39 DensityEncoding byte
40 RowAddressBitsx8Channel int
41 RowAddressBitsx16Channel int
42 TRFCABNs int
43 TRFCPBNs int
46 type LP5SpeedParams struct {
47 TCKMinPs int
48 MaxCASLatency int
51 type LP5SPDAttribFunc func(*LP5MemAttributes) byte
53 type LP5SPDAttribTableEntry struct {
54 constVal byte
55 getVal LP5SPDAttribFunc
58 type LP5Set struct {
59 SPDRevision byte
60 optionalFeatures byte
61 otherOptionalFeatures byte
62 busWidthEncoding byte
65 /* ------------------------------------------------------------------------------------------ */
66 /* Constants */
67 /* ------------------------------------------------------------------------------------------ */
69 const (
70 /* SPD Byte Index */
71 LP5SPDIndexSize = 0
72 LP5SPDIndexRevision = 1
73 LP5SPDIndexMemoryType = 2
74 LP5SPDIndexModuleType = 3
75 LP5SPDIndexDensityBanks = 4
76 LP5SPDIndexAddressing = 5
77 LP5SPDIndexPackageType = 6
78 LP5SPDIndexOptionalFeatures = 7
79 LP5SPDIndexOtherOptionalFeatures = 9
80 LP5SPDIndexModuleOrganization = 12
81 LP5SPDIndexBusWidth = 13
82 LP5SPDIndexTimebases = 17
83 LP5SPDIndexTCKMin = 18
84 LP5SPDIndexTAAMin = 24
85 LP5SPDIndexTRCDMin = 26
86 LP5SPDIndexTRPABMin = 27
87 LP5SPDIndexTRPPBMin = 28
88 LP5SPDIndexTRFCABMinLSB = 29
89 LP5SPDIndexTRFCABMinMSB = 30
90 LP5SPDIndexTRFCPBMinLSB = 31
91 LP5SPDIndexTRFCPBMinMSB = 32
92 LP5SPDIndexTRPPBMinFineOffset = 120
93 LP5SPDIndexTRPABMinFineOffset = 121
94 LP5SPDIndexTRCDMinFineOffset = 122
95 LP5SPDIndexTAAMinFineOffset = 123
96 LP5SPDIndexTCKMinFineOffset = 125
97 LP5SPDIndexManufacturerPartNumberStartByte = 329
98 LP5SPDIndexManufacturerPartNumberEndByte = 348
100 /* SPD Byte Value */
103 * From JEDEC spec:
104 * 6:4 (Bytes total) = 2 (512 bytes)
105 * 3:0 (Bytes used) = 3 (384 bytes)
106 * Set to 0x23 for LPDDR5.
108 LP5SPDValueSize = 0x23
111 * Revision 1.0. Expected by ADL
113 LP5SPDValueRevision1_0 = 0x10
115 * Revision 1.1. Expected by Sabrina
117 LP5SPDValueRevision1_1 = 0x11
120 * As per advisory #616599, ADL MRC expects LPDDR5 memory type = 0x13.
122 LP5SPDValueMemoryType = 0x13
125 * From JEDEC spec:
126 * 7:7 (Hybrid) = 0 (Not hybrid)
127 * 6:4 (Hybrid media) = 000 (Not hybrid)
128 * 3:0 (Base Module Type) = 1110 (Non-DIMM solution)
130 * This is dependent on hardware design. LPDDR5 only has memory down solution.
131 * Hence this is not hybrid non-DIMM solution.
132 * Set to 0x0E.
134 LP5SPDValueModuleType = 0x0e
137 * From JEDEC spec:
138 * 3:2 (MTB) = 00 (0.125ns)
139 * 1:0 (FTB) = 00 (1ps)
140 * Set to 0x00.
142 LP5SPDValueTimebases = 0x00
144 /* As per JEDEC spec, unused digits of manufacturer part number are left as blank. */
145 LP5SPDValueManufacturerPartNumberBlank = 0x20
148 const (
150 * LPDDR5 has a flexible bank architecture with three programmable bank modes: BG, 8B, 16B.
151 * ADL will use 8B mode for all parts.
153 * From JEDEC spec:
154 * 7:6 (Bank Group Bits) = 00 (no bank groups)
155 * 5:4 (Bank Address Bits) = 01 (8 banks)
156 * Set bits 7:4 to 0b0001.
158 LP5BankGroupsBanks = 0x1
161 * Tables 8 and 9 from JESD209-5B.
162 * ADL uses 8B mode for all parts. The column addresses are the same for x8 and x16.
163 * Effective column address bits = column address bits + burst address bits = 6 + 5 = 11.
164 * As per JESD 21-C, this is encoded as 0b010.
166 LP5ColumnAddressBits = 0x2
169 /* ------------------------------------------------------------------------------------------ */
170 /* Global variables */
171 /* ------------------------------------------------------------------------------------------ */
173 var LP5PlatformSetMap = map[int][]int{
174 0: {PlatformADL},
175 1: {PlatformSBR},
178 var LP5SetInfo = map[int]LP5Set{
179 0: {
180 SPDRevision: LP5SPDValueRevision1_0,
182 * From JEDEC spec:
183 * 5:4 (Maximum Activate Window) = 00 (8192 * tREFI)
184 * 3:0 (Maximum Activate Count) = 1000 (Unlimited MAC)
185 * Set to 0x08.
187 optionalFeatures: 0x08,
189 * For ADL (as per advisory #616599):
190 * 7:5 (Number of system channels) = 000 (1 channel always)
191 * 4:3 (Bus width extension) = 00 (no ECC)
192 * 2:0 (Bus width) = 001 (x16 always)
193 * Set to 0x01.
195 busWidthEncoding: 0x01,
197 1: {
198 SPDRevision: LP5SPDValueRevision1_1,
200 * For Sabrina (as per advisory b/211510456):
201 * 5:4 (Maximum Activate Window) = 01 (4096 * tREFI)
202 * 3:0 (Maximum Activate Count) = 1000 (Unlimited MAC)
203 * Set to 0x18.
205 optionalFeatures: 0x18,
207 * For Sabrina (as per advisory b/211510456):
208 * 7:6 (PPR) = 1 (Post Package Repair is supported)
209 * Set to 0x40.
211 otherOptionalFeatures: 0x40,
213 * For Sabrina (as per advisory b/211510456):
214 * 7:5 (Number of system channels) = 000 (1 channel always)
215 * 4:3 (Bus width extension) = 00 (no ECC)
216 * 2:0 (Bus width) = 010 (x32 always)
217 * Set to 0x02.
219 busWidthEncoding: 0x02,
223 var LP5PartAttributeMap = map[string]LP5MemAttributes{}
224 var LP5CurrSet int
227 * DensityEncoding: Maps the die density in Gb to the SPD encoding of the die density
228 * as per JESD 21-C.
230 * RowAddressBits: Maps the die density to the number of row address bits.
231 * Tables 6-11 in JESD209-5B (same for all three bank modes).
233 * TRFCABNs/TRFCPBNs: Maps the die density to the refresh timings.
234 * Tables 235 and 236 in JESD209-5B (same for all three bank modes).
236 var LP5DensityGbToSPDEncoding = map[int]LP5DensityParams{
237 4: {
238 DensityEncoding: 0x4,
239 RowAddressBitsx8Channel: 15,
240 RowAddressBitsx16Channel: 14,
241 TRFCABNs: 180,
242 TRFCPBNs: 90,
244 6: {
245 DensityEncoding: 0xb,
246 RowAddressBitsx8Channel: 16,
247 RowAddressBitsx16Channel: 15,
248 TRFCABNs: 210,
249 TRFCPBNs: 120,
251 8: {
252 DensityEncoding: 0x5,
253 RowAddressBitsx8Channel: 16,
254 RowAddressBitsx16Channel: 15,
255 TRFCABNs: 210,
256 TRFCPBNs: 120,
258 12: {
259 DensityEncoding: 0x8,
260 RowAddressBitsx8Channel: 17,
261 RowAddressBitsx16Channel: 16,
262 TRFCABNs: 280,
263 TRFCPBNs: 140,
265 16: {
266 DensityEncoding: 0x6,
267 RowAddressBitsx8Channel: 17,
268 RowAddressBitsx16Channel: 16,
269 TRFCABNs: 280,
270 TRFCPBNs: 140,
272 24: {
273 DensityEncoding: 0x9,
274 RowAddressBitsx8Channel: 18,
275 RowAddressBitsx16Channel: 17,
276 TRFCABNs: 380,
277 TRFCPBNs: 190,
279 32: {
280 DensityEncoding: 0x7,
281 RowAddressBitsx8Channel: 18,
282 RowAddressBitsx16Channel: 17,
283 TRFCABNs: 380,
284 TRFCPBNs: 190,
289 * Maps the number of row address bits to the SPD encoding as per JESD 21-C.
291 var LP5RowAddressBitsEncoding = map[int]byte{
292 14: 0x2,
293 15: 0x3,
294 16: 0x4,
295 17: 0x5,
296 18: 0x6,
300 * TCKMinPs:
301 * LPDDR5 has two clocks: the command/address clock (CK) and the data clock (WCK). They are
302 * related by the WCK:CK ratio, which can be either 4:1 or 2:1. On ADL, 4:1 is used.
303 * For ADL, the MRC expects the tCKmin to encode the CK period. This is calculated as:
304 * tCKmin = 1 / CK rate
305 * = 1 / (WCK rate / WCK:CK)
306 * = 1 / (speed grade / 2 / WCK:CK) // "double data rate"
308 * MaxCASLatency:
309 * From Table 220 of JESD209-5B, using a 4:1 WCK:CK ratio and Set 0.
311 var LP5SpeedMbpsToSPDEncoding = map[int]LP5SpeedParams{
312 6400: {
313 TCKMinPs: 1250, /* 1 / (6400 / 2 / 4) */
314 MaxCASLatency: 17,
316 5500: {
317 TCKMinPs: 1455, /* 1 / (5500 / 2 / 4) */
318 MaxCASLatency: 15,
322 var LP5SPDAttribTable = map[int]LP5SPDAttribTableEntry{
323 LP5SPDIndexSize: {constVal: LP5SPDValueSize},
324 LP5SPDIndexRevision: {getVal: LP5EncodeSPDRevision},
325 LP5SPDIndexMemoryType: {constVal: LP5SPDValueMemoryType},
326 LP5SPDIndexModuleType: {constVal: LP5SPDValueModuleType},
327 LP5SPDIndexDensityBanks: {getVal: LP5EncodeDensityBanks},
328 LP5SPDIndexAddressing: {getVal: LP5EncodeSdramAddressing},
329 LP5SPDIndexPackageType: {getVal: LP5EncodePackageType},
330 LP5SPDIndexOptionalFeatures: {getVal: LP5EncodeOptionalFeatures},
331 LP5SPDIndexOtherOptionalFeatures: {getVal: LP5EncodeOtherOptionalFeatures},
332 LP5SPDIndexModuleOrganization: {getVal: LP5EncodeModuleOrganization},
333 LP5SPDIndexBusWidth: {getVal: LP5EncodeBusWidth},
334 LP5SPDIndexTimebases: {constVal: LP5SPDValueTimebases},
335 LP5SPDIndexTCKMin: {getVal: LP5EncodeTCKMin},
336 LP5SPDIndexTCKMinFineOffset: {getVal: LP5EncodeTCKMinFineOffset},
337 LP5SPDIndexTAAMin: {getVal: LP5EncodeTAAMin},
338 LP5SPDIndexTAAMinFineOffset: {getVal: LP5EncodeTAAMinFineOffset},
339 LP5SPDIndexTRCDMin: {getVal: LP5EncodeTRCDMin},
340 LP5SPDIndexTRCDMinFineOffset: {getVal: LP5EncodeTRCDMinFineOffset},
341 LP5SPDIndexTRPABMin: {getVal: LP5EncodeTRPABMin},
342 LP5SPDIndexTRPABMinFineOffset: {getVal: LP5EncodeTRPABMinFineOffset},
343 LP5SPDIndexTRPPBMin: {getVal: LP5EncodeTRPPBMin},
344 LP5SPDIndexTRPPBMinFineOffset: {getVal: LP5EncodeTRPPBMinFineOffset},
345 LP5SPDIndexTRFCABMinLSB: {getVal: LP5EncodeTRFCABMinLsb},
346 LP5SPDIndexTRFCABMinMSB: {getVal: LP5EncodeTRFCABMinMsb},
347 LP5SPDIndexTRFCPBMinLSB: {getVal: LP5EncodeTRFCPBMinLsb},
348 LP5SPDIndexTRFCPBMinMSB: {getVal: LP5EncodeTRFCPBMinMsb},
351 /* ------------------------------------------------------------------------------------------ */
352 /* Functions */
353 /* ------------------------------------------------------------------------------------------ */
354 func LP5EncodeSPDRevision(memAttribs *LP5MemAttributes) byte {
355 f, ok := LP5SetInfo[LP5CurrSet]
357 if ok == false {
358 return 0
361 return f.SPDRevision
364 func LP5EncodeDensityBanks(memAttribs *LP5MemAttributes) byte {
365 var b byte
367 // 3:0 Density per die.
368 b = LP5DensityGbToSPDEncoding[memAttribs.DensityPerDieGb].DensityEncoding
370 // 5:4 Bank address bits.
371 // 7:6 Bank group bits.
372 b |= LP5BankGroupsBanks << 4
374 return b
377 func LP5EncodeSdramAddressing(memAttribs *LP5MemAttributes) byte {
378 var b byte
380 // 2:0 Column address bits.
381 b = LP5ColumnAddressBits
383 // 5:3 Row address bits.
384 density := memAttribs.DensityPerDieGb
385 var rowAddressBits int
386 if memAttribs.BitWidthPerChannel == 8 {
387 rowAddressBits = LP5DensityGbToSPDEncoding[density].RowAddressBitsx8Channel
388 } else {
389 rowAddressBits = LP5DensityGbToSPDEncoding[density].RowAddressBitsx16Channel
391 b |= LP5RowAddressBitsEncoding[rowAddressBits] << 3
393 return b
396 func LP5EncodePackageType(memAttribs *LP5MemAttributes) byte {
397 var b byte
399 // 1:0 Signal loading index.
400 b = 1
402 // 3:2 Channels per package.
403 // Channels per package = package width (e.g. x32) / bitWidthPerChannel (x8 or x16).
404 // This can equivalently be calculated as diesPerPackage / ranksPerChannel.
405 // This calculation is used to avoid adding a redundant attribute for package width.
406 channels := memAttribs.DiesPerPackage / memAttribs.RanksPerChannel
407 b |= byte(channels>>1) << 2
409 // 6:4 Dies per package.
410 b |= (byte(memAttribs.DiesPerPackage) - 1) << 4
412 // 7:7 Package type.
413 var packageType byte
414 if memAttribs.DiesPerPackage > 1 {
415 packageType = 1 // Non-Monolithic
416 } else {
417 packageType = 0 // Monolithic
419 b |= packageType << 7
421 return b
424 func LP5EncodeModuleOrganization(memAttribs *LP5MemAttributes) byte {
425 var b byte
427 // 2:0 Device data width per channel
428 b = byte(memAttribs.BitWidthPerChannel / 8)
430 // 5:3 Package ranks per channel
431 b |= byte(memAttribs.RanksPerChannel-1) << 3
433 return b
436 func LP5EncodeOptionalFeatures(memAttribs *LP5MemAttributes) byte {
437 f, ok := LP5SetInfo[LP5CurrSet]
439 if ok == false {
440 return 0
443 return f.optionalFeatures
446 func LP5EncodeOtherOptionalFeatures(memAttribs *LP5MemAttributes) byte {
447 f, ok := LP5SetInfo[LP5CurrSet]
449 if ok == false {
450 return 0
453 return f.otherOptionalFeatures
456 func LP5EncodeBusWidth(memAttribs *LP5MemAttributes) byte {
457 f, ok := LP5SetInfo[LP5CurrSet]
459 if ok == false {
460 return 0
463 return f.busWidthEncoding
466 func LP5EncodeTCKMin(memAttribs *LP5MemAttributes) byte {
467 return convPsToMtbByte(memAttribs.TCKMinPs)
470 func LP5EncodeTCKMinFineOffset(memAttribs *LP5MemAttributes) byte {
471 return convPsToFtbByte(memAttribs.TCKMinPs)
474 func LP5EncodeTAAMin(memAttribs *LP5MemAttributes) byte {
475 return convPsToMtbByte(memAttribs.TAAMinPs)
478 func LP5EncodeTAAMinFineOffset(memAttribs *LP5MemAttributes) byte {
479 return convPsToFtbByte(memAttribs.TAAMinPs)
482 func LP5EncodeTRCDMin(memAttribs *LP5MemAttributes) byte {
483 return convNsToMtbByte(memAttribs.TRCDMinNs)
486 func LP5EncodeTRCDMinFineOffset(memAttribs *LP5MemAttributes) byte {
487 return convNsToFtbByte(memAttribs.TRCDMinNs)
490 func LP5EncodeTRPABMin(memAttribs *LP5MemAttributes) byte {
491 return convNsToMtbByte(memAttribs.TRPABMinNs)
494 func LP5EncodeTRPABMinFineOffset(memAttribs *LP5MemAttributes) byte {
495 return convNsToFtbByte(memAttribs.TRPABMinNs)
498 func LP5EncodeTRPPBMin(memAttribs *LP5MemAttributes) byte {
499 return convNsToMtbByte(memAttribs.TRPPBMinNs)
502 func LP5EncodeTRPPBMinFineOffset(memAttribs *LP5MemAttributes) byte {
503 return convNsToFtbByte(memAttribs.TRPPBMinNs)
506 func LP5EncodeTRFCABMinMsb(memAttribs *LP5MemAttributes) byte {
507 return byte((convNsToMtb(memAttribs.TRFCABNs) >> 8) & 0xff)
510 func LP5EncodeTRFCABMinLsb(memAttribs *LP5MemAttributes) byte {
511 return byte(convNsToMtb(memAttribs.TRFCABNs) & 0xff)
514 func LP5EncodeTRFCPBMinMsb(memAttribs *LP5MemAttributes) byte {
515 return byte((convNsToMtb(memAttribs.TRFCPBNs) >> 8) & 0xff)
518 func LP5EncodeTRFCPBMinLsb(memAttribs *LP5MemAttributes) byte {
519 return byte(convNsToMtb(memAttribs.TRFCPBNs) & 0xff)
522 func LP5UpdateTCKMin(memAttribs *LP5MemAttributes) {
523 if memAttribs.TCKMinPs == 0 {
524 memAttribs.TCKMinPs = LP5SpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].TCKMinPs
528 func LP5UpdateTAAMin(memAttribs *LP5MemAttributes) {
529 if memAttribs.TAAMinPs == 0 {
530 maxCAS := LP5SpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].MaxCASLatency
531 memAttribs.TAAMinPs = memAttribs.TCKMinPs * maxCAS
535 func LP5UpdateTRFCAB(memAttribs *LP5MemAttributes) {
536 if memAttribs.TRFCABNs == 0 {
537 memAttribs.TRFCABNs = LP5DensityGbToSPDEncoding[memAttribs.DensityPerDieGb].TRFCABNs
541 func LP5UpdateTRFCPB(memAttribs *LP5MemAttributes) {
542 if memAttribs.TRFCPBNs == 0 {
543 memAttribs.TRFCPBNs = LP5DensityGbToSPDEncoding[memAttribs.DensityPerDieGb].TRFCPBNs
547 func LP5UpdateTRCD(memAttribs *LP5MemAttributes) {
548 if memAttribs.TRCDMinNs == 0 {
549 /* Table 372 from JESD209-5B */
550 memAttribs.TRCDMinNs = 18
554 func LP5UpdateTRPAB(memAttribs *LP5MemAttributes) {
555 if memAttribs.TRPABMinNs == 0 {
556 /* Table 372 from JESD209-5B */
557 memAttribs.TRPABMinNs = 21
561 func LP5UpdateTRPPB(memAttribs *LP5MemAttributes) {
562 if memAttribs.TRPPBMinNs == 0 {
563 /* Table 372 from JESD209-5B */
564 memAttribs.TRPPBMinNs = 18
568 func lp5UpdateMemoryAttributes(memAttribs *LP5MemAttributes) {
569 LP5UpdateTCKMin(memAttribs)
570 LP5UpdateTAAMin(memAttribs)
571 LP5UpdateTRFCAB(memAttribs)
572 LP5UpdateTRFCPB(memAttribs)
573 LP5UpdateTRCD(memAttribs)
574 LP5UpdateTRPAB(memAttribs)
575 LP5UpdateTRPPB(memAttribs)
578 func LP5ValidateDensity(density int) error {
579 if _, ok := LP5DensityGbToSPDEncoding[density]; !ok {
580 return fmt.Errorf("Incorrect density per die: %d Gb", density)
582 return nil
585 func LP5ValidateDies(dies int) error {
586 if dies != 2 && dies != 4 && dies != 8 {
587 return fmt.Errorf("Incorrect dies: %d", dies)
589 return nil
592 func LP5ValidateDataWidth(width int) error {
593 if width != 8 && width != 16 {
594 return fmt.Errorf("Incorrect bit width: %d", width)
596 return nil
599 func LP5ValidateRanks(ranks int) error {
600 if ranks != 1 && ranks != 2 {
601 return fmt.Errorf("Incorrect ranks: %d", ranks)
603 return nil
606 func LP5ValidateSpeed(speed int) error {
607 if _, ok := LP5SpeedMbpsToSPDEncoding[speed]; !ok {
608 return fmt.Errorf("Incorrect speed: %d Mbps", speed)
610 return nil
613 func lp5ValidateMemPartAttributes(memAttribs *LP5MemAttributes) error {
614 if err := LP5ValidateDensity(memAttribs.DensityPerDieGb); err != nil {
615 return err
617 if err := LP5ValidateDies(memAttribs.DiesPerPackage); err != nil {
618 return err
620 if err := LP5ValidateDataWidth(memAttribs.BitWidthPerChannel); err != nil {
621 return err
623 if err := LP5ValidateRanks(memAttribs.RanksPerChannel); err != nil {
624 return err
626 if err := LP5ValidateSpeed(memAttribs.SpeedMbps); err != nil {
627 return err
630 return nil
633 func LP5IsManufacturerPartNumberByte(index int) bool {
634 if index >= LP5SPDIndexManufacturerPartNumberStartByte &&
635 index <= LP5SPDIndexManufacturerPartNumberEndByte {
636 return true
638 return false
641 /* ------------------------------------------------------------------------------------------ */
642 /* Interface Functions */
643 /* ------------------------------------------------------------------------------------------ */
645 func (lp5) getSetMap() map[int][]int {
646 return LP5PlatformSetMap
649 func (lp5) addNewPart(name string, attribs interface{}) error {
650 var lp5Attributes LP5MemAttributes
651 eByte, err := json.Marshal(attribs)
652 if err != nil {
653 return err
656 if err := json.Unmarshal(eByte, &lp5Attributes); err != nil {
657 return err
660 if err := lp5ValidateMemPartAttributes(&lp5Attributes); err != nil {
661 return err
664 LP5PartAttributeMap[name] = lp5Attributes
665 return nil
668 func (lp5) getSPDAttribs(name string, set int) (interface{}, error) {
669 lp5Attributes := LP5PartAttributeMap[name]
671 LP5CurrSet = set
673 lp5UpdateMemoryAttributes(&lp5Attributes)
675 return lp5Attributes, nil
678 func (lp5) getSPDLen() int {
679 return 512
682 func (lp5) getSPDByte(index int, attribs interface{}) byte {
683 e, ok := LP5SPDAttribTable[index]
684 if !ok {
685 if LP5IsManufacturerPartNumberByte(index) {
686 return LP5SPDValueManufacturerPartNumberBlank
688 return 0x00
691 if e.getVal != nil {
692 var lp5Attribs LP5MemAttributes
693 lp5Attribs = attribs.(LP5MemAttributes)
694 return e.getVal(&lp5Attribs)
697 return e.constVal