/* SPDX-License-Identifier: GPL-2.0-or-later */ package main import ( "encoding/json" "fmt" "strconv" "strings" ) /* ------------------------------------------------------------------------------------------ */ /* LP4x-defined types */ /* ------------------------------------------------------------------------------------------ */ type lp4x struct { } type LP4xMemAttributes struct { /* Primary attributes - must be provided by JSON file for each part */ DensityPerChannelGb int Banks int ChannelsPerDie int DiesPerPackage int BitWidthPerChannel int RanksPerChannel int SpeedMbps int /* * All the following parameters are optional and required only if the part requires * special parameters as per the datasheet. */ /* Timing parameters */ TRFCABNs int TRFCPBNs int TRPABMinNs int TRPPBMinNs int TCKMinPs int TCKMaxPs int TAAMinPs int TRCDMinNs int /* CAS */ CASLatencies string CASFirstByte byte CASSecondByte byte CASThirdByte byte } type LP4xSpeedParams struct { TCKMinPs int TCKMaxPs int CASLatenciesx16Channel string CASLatenciesx8Channel string } type LP4xRefreshTimings struct { TRFCABNs int TRFCPBNs int } type LP4xSPDAttribFunc func(*LP4xMemAttributes) byte type LP4xSPDAttribTableEntry struct { constVal byte getVal LP4xSPDAttribFunc } type LP4xSetFunc func(*LP4xMemAttributes) int type LP4xSet struct { getMRCDensity LP4xSetFunc getDiesPerPackage LP4xSetFunc busWidthEncoding byte normalizeAttribs LP4xSetFunc } /* ------------------------------------------------------------------------------------------ */ /* Constants */ /* ------------------------------------------------------------------------------------------ */ const ( /* SPD Byte Index */ LP4xSPDIndexSize = 0 LP4xSPDIndexRevision = 1 LP4xSPDIndexMemoryType = 2 LP4xSPDIndexModuleType = 3 LP4xSPDIndexDensityBanks = 4 LP4xSPDIndexAddressing = 5 LP4xSPDIndexPackageType = 6 LP4xSPDIndexOptionalFeatures = 7 LP4xSPDIndexModuleOrganization = 12 LP4xSPDIndexBusWidth = 13 LP4xSPDIndexTimebases = 17 LP4xSPDIndexTCKMin = 18 LP4xSPDIndexTCKMax = 19 LP4xSPDIndexCASFirstByte = 20 LP4xSPDIndexCASSecondByte = 21 LP4xSPDIndexCASThirdByte = 22 LP4xSPDIndexCASFourthByte = 23 LP4xSPDIndexTAAMin = 24 LP4xSPDIndexReadWriteLatency = 25 LP4xSPDIndexTRCDMin = 26 LP4xSPDIndexTRPABMin = 27 LP4xSPDIndexTRPPBMin = 28 LP4xSPDIndexTRFCABMinLSB = 29 LP4xSPDIndexTRFCABMinMSB = 30 LP4xSPDIndexTRFCPBMinLSB = 31 LP4xSPDIndexTRFCPBMinMSB = 32 LP4xSPDIndexTRPPBMinFineOffset = 120 LP4xSPDIndexTRPABMinFineOffset = 121 LP4xSPDIndexTRCDMinFineOffset = 122 LP4xSPDIndexTAAMinFineOffset = 123 LP4xSPDIndexTCKMaxFineOffset = 124 LP4xSPDIndexTCKMinFineOffset = 125 LP4xSPDIndexManufacturerPartNumberStartByte = 329 LP4xSPDIndexManufacturerPartNumberEndByte = 348 /* SPD Byte Value */ /* * From JEDEC spec: * 6:4 (Bytes total) = 2 (512 bytes) * 3:0 (Bytes used) = 3 (384 bytes) * Set to 0x23 for LPDDR4x. */ LP4xSPDValueSize = 0x23 /* * From JEDEC spec: Revision 1.1 * Set to 0x11. */ LP4xSPDValueRevision = 0x11 /* LPDDR4x memory type = 0x11 */ LP4xSPDValueMemoryType = 0x11 /* * From JEDEC spec: * 7:7 (Hybrid) = 0 (Not hybrid) * 6:4 (Hybrid media) = 000 (Not hybrid) * 3:0 (Base Module Type) = 1110 (Non-DIMM solution) * * This is dependent on hardware design. LPDDR4x only has memory down solution. * Hence this is not hybrid non-DIMM solution. * Set to 0x0E. */ LP4xSPDValueModuleType = 0x0e /* * From JEDEC spec: * 5:4 (Maximum Activate Window) = 00 (8192 * tREFI) * 3:0 (Maximum Activate Count) = 1000 (Unlimited MAC) * * Needs to come from datasheet, but most parts seem to support unlimited MAC. * MR#24 OP3 */ LP4xSPDValueOptionalFeatures = 0x08 /* * From JEDEC spec: * 3:2 (MTB) = 00 (0.125ns) * 1:0 (FTB) = 00 (1ps) * Set to 0x00. */ LP4xSPDValueTimebases = 0x00 /* CAS fourth byte: All bits are reserved */ LP4xSPDValueCASFourthByte = 0x00 /* Write Latency Set A and Read Latency DBI-RD disabled. */ LP4xSPDValueReadWriteLatency = 0x00 /* As per JEDEC spec, unused digits of manufacturer part number are left as blank. */ LP4xSPDValueManufacturerPartNumberBlank = 0x20 ) const ( /* First Byte */ LP4xCAS6 = 1 << 1 LP4xCAS10 = 1 << 4 LP4xCAS14 = 1 << 7 /* Second Byte */ LP4xCAS16 = 1 << 0 LP4xCAS20 = 1 << 2 LP4xCAS22 = 1 << 3 LP4xCAS24 = 1 << 4 LP4xCAS26 = 1 << 5 LP4xCAS28 = 1 << 6 /* Third Byte */ LP4xCAS32 = 1 << 0 LP4xCAS36 = 1 << 2 LP4xCAS40 = 1 << 4 ) const ( /* * JEDEC spec says that TCKmax should be 100ns for all speed grades. * 100ns in MTB units comes out to be 0x320. But since this is a byte field, set it to * 0xFF i.e. 31.875ns. */ LP4xTCKMaxPsDefault = 31875 ) /* ------------------------------------------------------------------------------------------ */ /* Global variables */ /* ------------------------------------------------------------------------------------------ */ var LP4xPlatformSetMap = map[int][]int{ 0: {PlatformTGL, PlatformADL}, 1: {PlatformJSL, PlatformCZN}, } var LP4xSetInfo = map[int]LP4xSet{ 0: { getMRCDensity: LP4xGetMRCDensitySet0, getDiesPerPackage: LP4xGetDiesPerPackageSet0, /* * As per advisory 616599: * 7:5 (Number of system channels) = 000 (1 channel always) * 2:0 (Bus width) = 001 (x16 always) * Set to 0x01. */ busWidthEncoding: 0x01, normalizeAttribs: LP4xNormalizeAttribsSet0, }, 1: { getMRCDensity: LP4xGetMRCDensitySet1, getDiesPerPackage: LP4xGetDiesPerPackageSet1, /* * As per advisory 610202: * 7:5 (Number of system channels) = 001 (2 channel always) * 2:0 (Bus width) = 010 (x32 always) * Set to 0x22. */ busWidthEncoding: 0x22, }, } var LP4xPartAttributeMap = map[string]LP4xMemAttributes{} var LP4xCurrSet int /* This encodes the density in Gb to SPD values as per JESD 21-C */ var LP4xDensityGbToSPDEncoding = map[int]byte{ 4: 0x4, 6: 0xb, 8: 0x5, 12: 0x8, 16: 0x6, 24: 0x9, 32: 0x7, } /* * Table 5 from JESD209-4C. * Maps density per physical channel to row-column encoding as per JESD 21-C for a device with * x8 physical channel. */ var LP4xDensityGbx8ChannelToRowColumnEncoding = map[int]byte{ 3: 0x21, /* 16 rows, 10 columns */ 4: 0x21, /* 16 rows, 10 columns */ 6: 0x29, /* 17 rows, 10 columns */ 8: 0x29, /* 17 rows, 10 columns */ 12: 0x31, /* 18 rows, 10 columns */ 16: 0x31, /* 18 rows, 10 columns */ } /* * Table 3 from JESD209-4C. * Maps density per physical channel to row-column encoding as per JESD 21-C for a device with * x16 physical channel. */ var LP4xDensityGbx16ChannelToRowColumnEncoding = map[int]byte{ 4: 0x19, /* 15 rows, 10 columns */ 6: 0x21, /* 16 rows, 10 columns */ 8: 0x21, /* 16 rows, 10 columns */ 12: 0x29, /* 17 rows, 10 columns */ 16: 0x29, /* 17 rows, 10 columns */ } /* * Table 112 from JESD209-4C * Maps density per physical channel to refresh timings. This is the same for x8 and x16 * devices. */ var LP4xDensityGbPhysicalChannelToRefreshEncoding = map[int]LP4xRefreshTimings{ 3: { TRFCABNs: 180, TRFCPBNs: 90, }, 4: { TRFCABNs: 180, TRFCPBNs: 90, }, 6: { TRFCABNs: 280, TRFCPBNs: 140, }, 8: { TRFCABNs: 280, TRFCPBNs: 140, }, 12: { TRFCABNs: 380, TRFCPBNs: 190, }, 16: { TRFCABNs: 380, TRFCPBNs: 190, }, } var LP4xBankEncoding = map[int]byte{ 4: 0 << 4, 8: 1 << 4, } var LP4xSpeedMbpsToSPDEncoding = map[int]LP4xSpeedParams{ 4267: { TCKMinPs: 468, /* 1/4267 * 2 */ TCKMaxPs: LP4xTCKMaxPsDefault, CASLatenciesx16Channel: "6 10 14 20 24 28 32 36", CASLatenciesx8Channel: "6 10 16 22 26 32 36 40", }, 3733: { TCKMinPs: 535, /* 1/3733 * 2 */ TCKMaxPs: LP4xTCKMaxPsDefault, CASLatenciesx16Channel: "6 10 14 20 24 28 32", CASLatenciesx8Channel: "6 10 16 22 26 32 36", }, 3200: { TCKMinPs: 625, /* 1/3200 * 2 */ TCKMaxPs: LP4xTCKMaxPsDefault, CASLatenciesx16Channel: "6 10 14 20 24 28", CASLatenciesx8Channel: "6 10 16 22 26 32", }, } var LP4xSPDAttribTable = map[int]LP4xSPDAttribTableEntry{ LP4xSPDIndexSize: {constVal: LP4xSPDValueSize}, LP4xSPDIndexRevision: {constVal: LP4xSPDValueRevision}, LP4xSPDIndexMemoryType: {constVal: LP4xSPDValueMemoryType}, LP4xSPDIndexModuleType: {constVal: LP4xSPDValueModuleType}, LP4xSPDIndexDensityBanks: {getVal: LP4xEncodeDensityBanks}, LP4xSPDIndexAddressing: {getVal: LP4xEncodeSdramAddressing}, LP4xSPDIndexPackageType: {getVal: LP4xEncodePackageType}, LP4xSPDIndexOptionalFeatures: {constVal: LP4xSPDValueOptionalFeatures}, LP4xSPDIndexModuleOrganization: {getVal: LP4xEncodeModuleOrganization}, LP4xSPDIndexBusWidth: {getVal: LP4xEncodeBusWidth}, LP4xSPDIndexTimebases: {constVal: LP4xSPDValueTimebases}, LP4xSPDIndexTCKMin: {getVal: LP4xEncodeTCKMin}, LP4xSPDIndexTCKMax: {getVal: LP4xEncodeTCKMax}, LP4xSPDIndexTCKMaxFineOffset: {getVal: LP4xEncodeTCKMaxFineOffset}, LP4xSPDIndexTCKMinFineOffset: {getVal: LP4xEncodeTCKMinFineOffset}, LP4xSPDIndexCASFirstByte: {getVal: LP4xEncodeCASFirstByte}, LP4xSPDIndexCASSecondByte: {getVal: LP4xEncodeCASSecondByte}, LP4xSPDIndexCASThirdByte: {getVal: LP4xEncodeCASThirdByte}, LP4xSPDIndexCASFourthByte: {constVal: LP4xSPDValueCASFourthByte}, LP4xSPDIndexTAAMin: {getVal: LP4xEncodeTAAMin}, LP4xSPDIndexTAAMinFineOffset: {getVal: LP4xEncodeTAAMinFineOffset}, LP4xSPDIndexReadWriteLatency: {constVal: LP4xSPDValueReadWriteLatency}, LP4xSPDIndexTRCDMin: {getVal: LP4xEncodeTRCDMin}, LP4xSPDIndexTRCDMinFineOffset: {getVal: LP4xEncodeTRCDMinFineOffset}, LP4xSPDIndexTRPABMin: {getVal: LP4xEncodeTRPABMin}, LP4xSPDIndexTRPABMinFineOffset: {getVal: LP4xEncodeTRPABMinFineOffset}, LP4xSPDIndexTRPPBMin: {getVal: LP4xEncodeTRPPBMin}, LP4xSPDIndexTRPPBMinFineOffset: {getVal: LP4xEncodeTRPPBMinFineOffset}, LP4xSPDIndexTRFCABMinLSB: {getVal: LP4xEncodeTRFCABMinLsb}, LP4xSPDIndexTRFCABMinMSB: {getVal: LP4xEncodeTRFCABMinMsb}, LP4xSPDIndexTRFCPBMinLSB: {getVal: LP4xEncodeTRFCPBMinLsb}, LP4xSPDIndexTRFCPBMinMSB: {getVal: LP4xEncodeTRFCPBMinMsb}, } /* ------------------------------------------------------------------------------------------ */ /* Functions */ /* ------------------------------------------------------------------------------------------ */ func LP4xGetMRCDensitySet0(memAttribs *LP4xMemAttributes) int { /* * Intel MRC on TGL/ADL expects density per logical channel to be encoded in * SPDIndexDensityBanks. Logical channel on TGL/ADL is an x16 channel. */ return memAttribs.DensityPerChannelGb * 16 / memAttribs.BitWidthPerChannel } func LP4xGetMRCDensitySet1(memAttribs *LP4xMemAttributes) int { /* * Intel MRC on JSL expects density per die to be encoded in * SPDIndexDensityBanks. */ return memAttribs.DensityPerChannelGb * memAttribs.ChannelsPerDie } func LP4xGetMRCDensity(memAttribs *LP4xMemAttributes) int { f, ok := LP4xSetInfo[LP4xCurrSet] if ok == false || f.getMRCDensity == nil { return 0 } return f.getMRCDensity(memAttribs) } func LP4xEncodeDensityBanks(memAttribs *LP4xMemAttributes) byte { var b byte b = LP4xDensityGbToSPDEncoding[LP4xGetMRCDensity(memAttribs)] b |= LP4xBankEncoding[memAttribs.Banks] return b } func LP4xEncodeSdramAddressing(memAttribs *LP4xMemAttributes) byte { densityPerChannelGb := memAttribs.DensityPerChannelGb if memAttribs.BitWidthPerChannel == 8 { return LP4xDensityGbx8ChannelToRowColumnEncoding[densityPerChannelGb] } else { return LP4xDensityGbx16ChannelToRowColumnEncoding[densityPerChannelGb] } return 0 } func LP4xEncodePackage(dies int) byte { var temp byte if dies > 1 { /* If more than one die, then this is a non-monolithic device. */ temp = 1 } else { /* If only single die, then this is a monolithic device. */ temp = 0 } return temp << 7 } func LP4xEncodeChannelsPerDie(channels int) byte { var temp byte temp = byte(channels >> 1) return temp << 2 } func LP4xGetDiesPerPackageSet0(memAttribs *LP4xMemAttributes) int { /* Intel MRC expects logical dies to be encoded for TGL/ADL. */ return memAttribs.ChannelsPerDie * memAttribs.RanksPerChannel * memAttribs.BitWidthPerChannel / 16 } func LP4xGetDiesPerPackageSet1(memAttribs *LP4xMemAttributes) int { /* Intel MRC expects physical dies to be encoded for JSL. */ /* AMD PSP expects physical dies (ZQ balls) */ return memAttribs.DiesPerPackage } /* Per JESD209-4C Dies = ZQ balls on the package */ /* Note that this can be different than the part's die count */ func LP4xEncodeDiesPerPackage(memAttribs *LP4xMemAttributes) byte { var dies int = 0 f, ok := LP4xSetInfo[LP4xCurrSet] if ok != false && f.getDiesPerPackage != nil { dies = f.getDiesPerPackage(memAttribs) } b := LP4xEncodePackage(dies) /* Monolithic / Non-monolithic device */ b |= (byte(dies) - 1) << 4 return b } func LP4xEncodePackageType(memAttribs *LP4xMemAttributes) byte { var b byte b |= LP4xEncodeChannelsPerDie(memAttribs.ChannelsPerDie) b |= LP4xEncodeDiesPerPackage(memAttribs) return b } func LP4xEncodeDataWidth(bitWidthPerChannel int) byte { return byte(bitWidthPerChannel / 8) } func LP4xEncodeRanks(ranks int) byte { var b byte b = byte(ranks - 1) return b << 3 } func LP4xEncodeModuleOrganization(memAttribs *LP4xMemAttributes) byte { var b byte b = LP4xEncodeDataWidth(memAttribs.BitWidthPerChannel) b |= LP4xEncodeRanks(memAttribs.RanksPerChannel) return b } func LP4xEncodeBusWidth(memAttribs *LP4xMemAttributes) byte { f, ok := LP4xSetInfo[LP4xCurrSet] if ok == false { return 0 } return f.busWidthEncoding } func LP4xEncodeTCKMin(memAttribs *LP4xMemAttributes) byte { return convPsToMtbByte(memAttribs.TCKMinPs) } func LP4xEncodeTCKMinFineOffset(memAttribs *LP4xMemAttributes) byte { return convPsToFtbByte(memAttribs.TCKMinPs) } func LP4xEncodeTCKMax(memAttribs *LP4xMemAttributes) byte { return convPsToMtbByte(memAttribs.TCKMaxPs) } func LP4xEncodeTCKMaxFineOffset(memAttribs *LP4xMemAttributes) byte { return convPsToFtbByte(memAttribs.TCKMaxPs) } func LP4xEncodeCASFirstByte(memAttribs *LP4xMemAttributes) byte { return memAttribs.CASFirstByte } func LP4xEncodeCASSecondByte(memAttribs *LP4xMemAttributes) byte { return memAttribs.CASSecondByte } func LP4xEncodeCASThirdByte(memAttribs *LP4xMemAttributes) byte { return memAttribs.CASThirdByte } func LP4xEncodeTAAMin(memAttribs *LP4xMemAttributes) byte { return convPsToMtbByte(memAttribs.TAAMinPs) } func LP4xEncodeTAAMinFineOffset(memAttribs *LP4xMemAttributes) byte { return convPsToFtbByte(memAttribs.TAAMinPs) } func LP4xEncodeTRCDMin(memAttribs *LP4xMemAttributes) byte { return convNsToMtbByte(memAttribs.TRCDMinNs) } func LP4xEncodeTRCDMinFineOffset(memAttribs *LP4xMemAttributes) byte { return convNsToFtbByte(memAttribs.TRCDMinNs) } func LP4xEncodeTRPABMin(memAttribs *LP4xMemAttributes) byte { return convNsToMtbByte(memAttribs.TRPABMinNs) } func LP4xEncodeTRPABMinFineOffset(memAttribs *LP4xMemAttributes) byte { return convNsToFtbByte(memAttribs.TRPABMinNs) } func LP4xEncodeTRPPBMin(memAttribs *LP4xMemAttributes) byte { return convNsToMtbByte(memAttribs.TRPPBMinNs) } func LP4xEncodeTRPPBMinFineOffset(memAttribs *LP4xMemAttributes) byte { return convNsToFtbByte(memAttribs.TRPPBMinNs) } func LP4xEncodeTRFCABMinMsb(memAttribs *LP4xMemAttributes) byte { return byte((convNsToMtb(memAttribs.TRFCABNs) >> 8) & 0xff) } func LP4xEncodeTRFCABMinLsb(memAttribs *LP4xMemAttributes) byte { return byte(convNsToMtb(memAttribs.TRFCABNs) & 0xff) } func LP4xEncodeTRFCPBMinMsb(memAttribs *LP4xMemAttributes) byte { return byte((convNsToMtb(memAttribs.TRFCPBNs) >> 8) & 0xff) } func LP4xEncodeTRFCPBMinLsb(memAttribs *LP4xMemAttributes) byte { return byte(convNsToMtb(memAttribs.TRFCPBNs) & 0xff) } func LP4xEncodeLatencies(latency int, memAttribs *LP4xMemAttributes) error { switch latency { case 6: memAttribs.CASFirstByte |= LP4xCAS6 case 10: memAttribs.CASFirstByte |= LP4xCAS10 case 14: memAttribs.CASFirstByte |= LP4xCAS14 case 16: memAttribs.CASSecondByte |= LP4xCAS16 case 20: memAttribs.CASSecondByte |= LP4xCAS20 case 22: memAttribs.CASSecondByte |= LP4xCAS22 case 24: memAttribs.CASSecondByte |= LP4xCAS24 case 26: memAttribs.CASSecondByte |= LP4xCAS26 case 28: memAttribs.CASSecondByte |= LP4xCAS28 case 32: memAttribs.CASThirdByte |= LP4xCAS32 case 36: memAttribs.CASThirdByte |= LP4xCAS36 case 40: memAttribs.CASThirdByte |= LP4xCAS40 default: fmt.Errorf("Incorrect CAS Latency: ", latency) } return nil } func LP4xUpdateTCK(memAttribs *LP4xMemAttributes) { if memAttribs.TCKMinPs == 0 { memAttribs.TCKMinPs = LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].TCKMinPs } if memAttribs.TCKMaxPs == 0 { memAttribs.TCKMaxPs = LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].TCKMaxPs } } func LP4xGetCASLatencies(memAttribs *LP4xMemAttributes) string { if memAttribs.BitWidthPerChannel == 16 { return LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].CASLatenciesx16Channel } else if memAttribs.BitWidthPerChannel == 8 { return LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].CASLatenciesx8Channel } return "" } func LP4xUpdateCAS(memAttribs *LP4xMemAttributes) error { if len(memAttribs.CASLatencies) == 0 { memAttribs.CASLatencies = LP4xGetCASLatencies(memAttribs) } latencies := strings.Fields(memAttribs.CASLatencies) for i := 0; i < len(latencies); i++ { latency, err := strconv.Atoi(latencies[i]) if err != nil { return fmt.Errorf("Unable to convert latency ", latencies[i]) } if err := LP4xEncodeLatencies(latency, memAttribs); err != nil { return err } } return nil } func LP4xGetMinCAS(memAttribs *LP4xMemAttributes) (int, error) { if (memAttribs.CASThirdByte & LP4xCAS40) != 0 { return 40, nil } if (memAttribs.CASThirdByte & LP4xCAS36) != 0 { return 36, nil } if (memAttribs.CASThirdByte & LP4xCAS32) != 0 { return 32, nil } if (memAttribs.CASSecondByte & LP4xCAS28) != 0 { return 28, nil } return 0, fmt.Errorf("Unexpected min CAS") } func LP4xUpdateTAAMin(memAttribs *LP4xMemAttributes) error { if memAttribs.TAAMinPs == 0 { minCAS, err := LP4xGetMinCAS(memAttribs) if err != nil { return err } memAttribs.TAAMinPs = memAttribs.TCKMinPs * minCAS } return nil } func LP4xUpdateTRFCAB(memAttribs *LP4xMemAttributes) { if memAttribs.TRFCABNs == 0 { memAttribs.TRFCABNs = LP4xDensityGbPhysicalChannelToRefreshEncoding[memAttribs.DensityPerChannelGb].TRFCABNs } } func LP4xUpdateTRFCPB(memAttribs *LP4xMemAttributes) { if memAttribs.TRFCPBNs == 0 { memAttribs.TRFCPBNs = LP4xDensityGbPhysicalChannelToRefreshEncoding[memAttribs.DensityPerChannelGb].TRFCPBNs } } func LP4xUpdateTRCD(memAttribs *LP4xMemAttributes) { if memAttribs.TRCDMinNs == 0 { /* JEDEC spec says max of 18ns */ memAttribs.TRCDMinNs = 18 } } func LP4xUpdateTRPAB(memAttribs *LP4xMemAttributes) { if memAttribs.TRPABMinNs == 0 { /* JEDEC spec says max of 21ns */ memAttribs.TRPABMinNs = 21 } } func LP4xUpdateTRPPB(memAttribs *LP4xMemAttributes) { if memAttribs.TRPPBMinNs == 0 { /* JEDEC spec says max of 18ns */ memAttribs.TRPPBMinNs = 18 } } func LP4xNormalizeAttribsSet0(memAttribs *LP4xMemAttributes) int { /* * TGL does not really use physical organization of dies per package when * generating the SPD. So, set it to 0 here so that deduplication ignores * that field. */ memAttribs.DiesPerPackage = 0 return 0 } func LP4xNormalizeMemoryAttributes(memAttribs *LP4xMemAttributes) { f, ok := LP4xSetInfo[LP4xCurrSet] if ok == false || f.normalizeAttribs == nil { return } f.normalizeAttribs(memAttribs) } func Lp4xUpdateMemoryAttributes(memAttribs *LP4xMemAttributes) error { LP4xUpdateTCK(memAttribs) if err := LP4xUpdateCAS(memAttribs); err != nil { return err } if err := LP4xUpdateTAAMin(memAttribs); err != nil { return err } LP4xUpdateTRFCAB(memAttribs) LP4xUpdateTRFCPB(memAttribs) LP4xUpdateTRCD(memAttribs) LP4xUpdateTRPAB(memAttribs) LP4xUpdateTRPPB(memAttribs) LP4xNormalizeMemoryAttributes(memAttribs) return nil } func LP4xValidateDensityx8Channel(densityPerChannelGb int) error { if _, ok := LP4xDensityGbx8ChannelToRowColumnEncoding[densityPerChannelGb]; ok == false { return fmt.Errorf("Incorrect x8 density: %d Gb", densityPerChannelGb) } return nil } func LP4xValidateDensityx16Channel(densityPerChannelGb int) error { if _, ok := LP4xDensityGbx16ChannelToRowColumnEncoding[densityPerChannelGb]; ok == false { return fmt.Errorf("Incorrect x16 density: %d Gb", densityPerChannelGb) } return nil } func LP4xValidateDensity(memAttribs *LP4xMemAttributes) error { if memAttribs.BitWidthPerChannel == 8 { return LP4xValidateDensityx8Channel(memAttribs.DensityPerChannelGb) } else if memAttribs.BitWidthPerChannel == 16 { return LP4xValidateDensityx16Channel(memAttribs.DensityPerChannelGb) } return fmt.Errorf("No density table for this bit width: %d", memAttribs.BitWidthPerChannel) } func LP4xValidateBanks(banks int) error { if banks != 4 && banks != 8 { return fmt.Errorf("Incorrect banks: %d", banks) } return nil } func LP4xValidateChannels(channels int) error { if channels != 1 && channels != 2 && channels != 4 { return fmt.Errorf("Incorrect channels per die: %d ", channels) } return nil } func LP4xValidateDataWidth(width int) error { if width != 8 && width != 16 { return fmt.Errorf("Incorrect bit width: %d", width) } return nil } func LP4xValidateRanks(ranks int) error { if ranks != 1 && ranks != 2 { return fmt.Errorf("Incorrect ranks: %d", ranks) } return nil } func LP4xValidateSpeed(speed int) error { if _, ok := LP4xSpeedMbpsToSPDEncoding[speed]; ok == false { return fmt.Errorf("Incorrect speed: %d Mbps", speed) } return nil } func Lp4xValidateMemPartAttributes(memAttribs *LP4xMemAttributes) error { if err := LP4xValidateBanks(memAttribs.Banks); err != nil { return err } if err := LP4xValidateChannels(memAttribs.ChannelsPerDie); err != nil { return err } if err := LP4xValidateDataWidth(memAttribs.BitWidthPerChannel); err != nil { return err } if err := LP4xValidateDensity(memAttribs); err != nil { return err } if err := LP4xValidateRanks(memAttribs.RanksPerChannel); err != nil { return err } if err := LP4xValidateSpeed(memAttribs.SpeedMbps); err != nil { return err } return nil } func LP4xIsManufacturerPartNumberByte(index int) bool { if index >= LP4xSPDIndexManufacturerPartNumberStartByte && index <= LP4xSPDIndexManufacturerPartNumberEndByte { return true } return false } /* ------------------------------------------------------------------------------------------ */ /* Interface Functions */ /* ------------------------------------------------------------------------------------------ */ func (lp4x) getSetMap() map[int][]int { return LP4xPlatformSetMap } func (lp4x) addNewPart(name string, attribs interface{}) error { var lp4xAttributes LP4xMemAttributes eByte, err := json.Marshal(attribs) if err != nil { return err } if err := json.Unmarshal(eByte, &lp4xAttributes); err != nil { return err } if err := Lp4xValidateMemPartAttributes(&lp4xAttributes); err != nil { return err } LP4xPartAttributeMap[name] = lp4xAttributes return nil } func (lp4x) getSPDAttribs(name string, set int) (interface{}, error) { lp4xAttributes := LP4xPartAttributeMap[name] LP4xCurrSet = set if err := Lp4xUpdateMemoryAttributes(&lp4xAttributes); err != nil { return lp4xAttributes, err } return lp4xAttributes, nil } func (lp4x) getSPDLen() int { return 512 } func (lp4x) getSPDByte(index int, attribs interface{}) byte { e, ok := LP4xSPDAttribTable[index] if ok == false { if LP4xIsManufacturerPartNumberByte(index) { return LP4xSPDValueManufacturerPartNumberBlank } return 0x00 } if e.getVal != nil { var lp4xAttribs LP4xMemAttributes lp4xAttribs = attribs.(LP4xMemAttributes) return e.getVal(&lp4xAttribs) } return e.constVal }