diff options
Diffstat (limited to 'util/spd_tools/intel/lp4x/gen_spd.go')
-rw-r--r-- | util/spd_tools/intel/lp4x/gen_spd.go | 986 |
1 files changed, 0 insertions, 986 deletions
diff --git a/util/spd_tools/intel/lp4x/gen_spd.go b/util/spd_tools/intel/lp4x/gen_spd.go deleted file mode 100644 index 2465815e49..0000000000 --- a/util/spd_tools/intel/lp4x/gen_spd.go +++ /dev/null @@ -1,986 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -package main - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "log" - "os" - "path/filepath" - "reflect" - "strconv" - "strings" -) - -/* - * This program generates de-duplicated SPD files for LPDDR4x memory using the global memory - * part list provided in CSV format. In addition to that, it also generates SPD manifest in CSV - * format that contains entries of type (DRAM part name, SPD file name) which provides the SPD - * file name used by a given DRAM part. - * - * It takes as input: - * Pointer to directory where the generated SPD files will be placed. - * JSON file containing a list of memory parts with their attributes as per datasheet. - */ -const ( - SPDManifestFileName = "spd_manifest.generated.txt" - - PlatformTGL = 0 - PlatformJSL = 1 -) - -var platformMap = map[string]int { - "TGL": PlatformTGL, - "JSL": PlatformJSL, -} - -var currPlatform int - -type memAttributes 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 -} - -/* This encodes the density in Gb to SPD values as per JESD 21-C */ -var densityGbToSPDEncoding = map[int]byte { - 4: 0x4, - 6: 0xb, - 8: 0x5, - 12: 0x8, - 16: 0x6, - 24: 0x9, - 32: 0x7, -} - -/* - * 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 densityGbx16ChannelToRowColumnEncoding = 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 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 densityGbx8ChannelToRowColumnEncoding = 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 */ -} - -type refreshTimings struct { - TRFCABNs int - TRFCPBNs int -} - -/* - * Table 112 from JESD209-4C - * Maps density per physical channel to refresh timings. This is the same for x8 and x16 - * devices. - */ -var densityGbPhysicalChannelToRefreshEncoding = map[int]refreshTimings { - 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, - }, -} - -type speedParams struct { - TCKMinPs int - TCKMaxPs int - CASLatenciesx16Channel string - CASLatenciesx8Channel string -} - -const ( - /* First Byte */ - CAS6 = 1 << 1 - CAS10 = 1 << 4 - CAS14 = 1 << 7 - /* Second Byte */ - CAS16 = 1 << 0 - CAS20 = 1 << 2 - CAS22 = 1 << 3 - CAS24 = 1 << 4 - CAS26 = 1 << 5 - CAS28 = 1 << 6 - /* Third Byte */ - CAS32 = 1 << 0 - CAS36 = 1 << 2 - CAS40 = 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. - */ - TCKMaxPsDefault = 31875 -) - -var speedMbpsToSPDEncoding = map[int]speedParams { - 4267: { - TCKMinPs: 468, /* 1/4267 * 2 */ - TCKMaxPs: TCKMaxPsDefault, - 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: TCKMaxPsDefault, - CASLatenciesx16Channel: "6 10 14 20 24 28 32", - CASLatenciesx8Channel: "6 10 16 22 26 32 36", - }, - 3200: { - TCKMinPs: 625, /* 1/3200 * 2 */ - TCKMaxPs: TCKMaxPsDefault, - CASLatenciesx16Channel: "6 10 14 20 24 28", - CASLatenciesx8Channel: "6 10 16 22 26 32", - }, -} - -var bankEncoding = map[int]byte { - 4: 0 << 4, - 8: 1 << 4, -} - -const ( - TGLLogicalChannelWidth = 16 -) - -/* Returns density to encode as per Intel MRC expectations. */ -func getMRCDensity(memAttribs *memAttributes) int { - if currPlatform == PlatformTGL { - /* - * Intel MRC on TGL expects density per logical channel to be encoded in - * SPDIndexDensityBanks. Logical channel on TGL is an x16 channel. - */ - return memAttribs.DensityPerChannelGb * TGLLogicalChannelWidth / memAttribs.BitWidthPerChannel - } else if currPlatform == PlatformJSL { - /* - * Intel MRC on JSL expects density per die to be encoded in - * SPDIndexDensityBanks. - */ - return memAttribs.DensityPerChannelGb * memAttribs.ChannelsPerDie - } - - return 0 -} - -func encodeDensityBanks(memAttribs *memAttributes) byte { - var b byte - - b = densityGbToSPDEncoding[getMRCDensity(memAttribs)] - b |= bankEncoding[memAttribs.Banks] - - return b -} - -func encodeSdramAddressing(memAttribs *memAttributes) byte { - densityPerChannelGb := memAttribs.DensityPerChannelGb - if memAttribs.BitWidthPerChannel == 8 { - return densityGbx8ChannelToRowColumnEncoding[densityPerChannelGb] - } else { - return densityGbx16ChannelToRowColumnEncoding[densityPerChannelGb] - } - return 0 -} - -func encodeChannelsPerDie(channels int) byte { - var temp byte - - temp = byte(channels >> 1) - - return temp << 2 -} - -func encodePackage(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 encodeDiesPerPackage(memAttribs *memAttributes) byte { - var dies int = 0 - if currPlatform == PlatformTGL { - /* Intel MRC expects logical dies to be encoded for TGL. */ - dies = memAttribs.ChannelsPerDie * memAttribs.RanksPerChannel * memAttribs.BitWidthPerChannel / 16 - } else if currPlatform == PlatformJSL { - /* Intel MRC expects physical dies to be encoded for JSL. */ - dies = memAttribs.DiesPerPackage - } - - b := encodePackage(dies) /* Monolithic / Non-monolithic device */ - b |= (byte(dies) - 1) << 4 - - return b -} - -func encodePackageType(memAttribs *memAttributes) byte { - var b byte - - b |= encodeChannelsPerDie(memAttribs.ChannelsPerDie) - b |= encodeDiesPerPackage(memAttribs) - - return b -} - -func encodeDataWidth(bitWidthPerChannel int) byte { - return byte(bitWidthPerChannel / 8) -} - -func encodeRanks(ranks int) byte { - var b byte - b = byte(ranks - 1) - return b << 3 -} - -func encodeModuleOrganization(memAttribs *memAttributes) byte { - var b byte - - b = encodeDataWidth(memAttribs.BitWidthPerChannel) - b |= encodeRanks(memAttribs.RanksPerChannel) - - return b -} - -const ( - /* - * As per advisory 616599: - * 7:5 (Number of system channels) = 000 (1 channel always) - * 2:0 (Bus width) = 001 (x16 always) - * Set to 0x01. - */ - SPDValueBusWidthTGL = 0x01 - /* - * As per advisory 610202: - * 7:5 (Number of system channels) = 001 (2 channel always) - * 2:0 (Bus width) = 010 (x32 always) - * Set to 0x01. - */ - SPDValueBusWidthJSL = 0x22 -) - -func encodeBusWidth(memAttribs *memAttributes) byte { - if currPlatform == PlatformTGL { - return SPDValueBusWidthTGL - } else if currPlatform == PlatformJSL { - return SPDValueBusWidthJSL - } - return 0 -} - -func encodeTCKMin(memAttribs *memAttributes) byte { - return convPsToMtbByte(memAttribs.TCKMinPs) -} - -func encodeTCKMinFineOffset(memAttribs *memAttributes) byte { - return convPsToFtbByte(memAttribs.TCKMinPs) -} - -func encodeTCKMax(memAttribs *memAttributes) byte { - return convPsToMtbByte(memAttribs.TCKMaxPs) -} - -func encodeTCKMaxFineOffset(memAttribs *memAttributes) byte { - return convPsToFtbByte(memAttribs.TCKMaxPs) -} - -func encodeCASFirstByte(memAttribs *memAttributes) byte { - return memAttribs.CASFirstByte -} - -func encodeCASSecondByte(memAttribs *memAttributes) byte { - return memAttribs.CASSecondByte -} - -func encodeCASThirdByte(memAttribs *memAttributes) byte { - return memAttribs.CASThirdByte -} - -func divRoundUp(dividend int, divisor int) int { - return (dividend + divisor - 1) / divisor -} - -func convNsToPs(timeNs int) int { - return timeNs * 1000 -} - -func convMtbToPs(mtb int) int { - return mtb * 125 -} - -func convPsToMtb(timePs int) int { - return divRoundUp(timePs, 125) -} - -func convPsToMtbByte(timePs int) byte { - return byte(convPsToMtb(timePs) & 0xff) -} - -func convPsToFtbByte(timePs int) byte { - mtb := convPsToMtb(timePs) - ftb := timePs - convMtbToPs(mtb) - - return byte(ftb) -} - -func convNsToMtb(timeNs int) int { - return convPsToMtb(convNsToPs(timeNs)) -} - -func convNsToMtbByte(timeNs int) byte { - return convPsToMtbByte(convNsToPs(timeNs)) -} - -func convNsToFtbByte(timeNs int) byte { - return convPsToFtbByte(convNsToPs(timeNs)) -} - -func encodeTAAMin(memAttribs *memAttributes) byte { - return convPsToMtbByte(memAttribs.TAAMinPs) -} - -func encodeTAAMinFineOffset(memAttribs *memAttributes) byte { - return convPsToFtbByte(memAttribs.TAAMinPs) -} - -func encodeTRCDMin(memAttribs *memAttributes) byte { - return convNsToMtbByte(memAttribs.TRCDMinNs) -} - -func encodeTRCDMinFineOffset(memAttribs *memAttributes) byte { - return convNsToFtbByte(memAttribs.TRCDMinNs) -} - -func encodeTRPABMin(memAttribs *memAttributes) byte { - return convNsToMtbByte(memAttribs.TRPABMinNs) -} - -func encodeTRPABMinFineOffset(memAttribs *memAttributes) byte { - return convNsToFtbByte(memAttribs.TRPABMinNs) -} - -func encodeTRPPBMin(memAttribs *memAttributes) byte { - return convNsToMtbByte(memAttribs.TRPPBMinNs) -} - -func encodeTRPPBMinFineOffset(memAttribs *memAttributes) byte { - return convNsToFtbByte(memAttribs.TRPPBMinNs) -} - -func encodeTRFCABMinMsb(memAttribs *memAttributes) byte { - return byte((convNsToMtb(memAttribs.TRFCABNs) >> 8) & 0xff) -} - -func encodeTRFCABMinLsb(memAttribs *memAttributes) byte { - return byte(convNsToMtb(memAttribs.TRFCABNs) & 0xff) -} - -func encodeTRFCPBMinMsb(memAttribs *memAttributes) byte { - return byte((convNsToMtb(memAttribs.TRFCPBNs) >> 8) & 0xff) -} - -func encodeTRFCPBMinLsb(memAttribs *memAttributes) byte { - return byte(convNsToMtb(memAttribs.TRFCPBNs) & 0xff) -} - -type SPDAttribFunc func (*memAttributes) byte - -type SPDAttribTableEntry struct { - constVal byte - getVal SPDAttribFunc -} - -const ( - /* SPD Byte Index */ - SPDIndexSize = 0 - SPDIndexRevision = 1 - SPDIndexMemoryType = 2 - SPDIndexModuleType = 3 - SPDIndexDensityBanks = 4 - SPDIndexAddressing = 5 - SPDIndexPackageType = 6 - SPDIndexOptionalFeatures = 7 - SPDIndexModuleOrganization = 12 - SPDIndexBusWidth = 13 - SPDIndexTimebases = 17 - SPDIndexTCKMin = 18 - SPDIndexTCKMax = 19 - SPDIndexCASFirstByte = 20 - SPDIndexCASSecondByte = 21 - SPDIndexCASThirdByte = 22 - SPDIndexCASFourthByte = 23 - SPDIndexTAAMin = 24 - SPDIndexReadWriteLatency = 25 - SPDIndexTRCDMin = 26 - SPDIndexTRPABMin = 27 - SPDIndexTRPPBMin = 28 - SPDIndexTRFCABMinLSB = 29 - SPDIndexTRFCABMinMSB = 30 - SPDIndexTRFCPBMinLSB = 31 - SPDIndexTRFCPBMinMSB = 32 - SPDIndexTRPPBMinFineOffset = 120 - SPDIndexTRPABMinFineOffset = 121 - SPDIndexTRCDMinFineOffset = 122 - SPDIndexTAAMinFineOffset = 123 - SPDIndexTCKMaxFineOffset = 124 - SPDIndexTCKMinFineOffset = 125 - SPDIndexManufacturerPartNumberStartByte = 329 - SPDIndexManufacturerPartNumberEndByte = 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. - */ - SPDValueSize = 0x23 - - /* - * From JEDEC spec: Revision 1.1 - * Set to 0x11. - */ - SPDValueRevision = 0x11 - - /* LPDDR4x memory type = 0x11 */ - SPDValueMemoryType = 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. - */ - SPDValueModuleType = 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 - */ - SPDValueOptionalFeatures = 0x08 - - /* - * From JEDEC spec: - * 3:2 (MTB) = 00 (0.125ns) - * 1:0 (FTB) = 00 (1ps) - * Set to 0x00. - */ - SPDValueTimebases = 0x00 - - /* CAS fourth byte: All bits are reserved */ - SPDValueCASFourthByte = 0x00 - - /* Write Latency Set A and Read Latency DBI-RD disabled. */ - SPDValueReadWriteLatency = 0x00 - - /* As per JEDEC spec, unused digits of manufacturer part number are left as blank. */ - SPDValueManufacturerPartNumberBlank = 0x20 -) - -var SPDAttribTable = map[int]SPDAttribTableEntry { - SPDIndexSize: { constVal: SPDValueSize }, - SPDIndexRevision: { constVal: SPDValueRevision }, - SPDIndexMemoryType: { constVal: SPDValueMemoryType }, - SPDIndexModuleType: { constVal: SPDValueModuleType }, - SPDIndexDensityBanks: { getVal: encodeDensityBanks }, - SPDIndexAddressing: { getVal: encodeSdramAddressing }, - SPDIndexPackageType: { getVal: encodePackageType }, - SPDIndexOptionalFeatures: { constVal: SPDValueOptionalFeatures }, - SPDIndexModuleOrganization: { getVal: encodeModuleOrganization }, - SPDIndexBusWidth: { getVal: encodeBusWidth }, - SPDIndexTimebases: { constVal: SPDValueTimebases }, - SPDIndexTCKMin: { getVal: encodeTCKMin }, - SPDIndexTCKMax: { getVal: encodeTCKMax }, - SPDIndexTCKMaxFineOffset: { getVal: encodeTCKMaxFineOffset }, - SPDIndexTCKMinFineOffset: { getVal: encodeTCKMinFineOffset }, - SPDIndexCASFirstByte: { getVal: encodeCASFirstByte }, - SPDIndexCASSecondByte: { getVal: encodeCASSecondByte }, - SPDIndexCASThirdByte: { getVal: encodeCASThirdByte }, - SPDIndexCASFourthByte: { constVal: SPDValueCASFourthByte }, - SPDIndexTAAMin: { getVal: encodeTAAMin }, - SPDIndexTAAMinFineOffset: { getVal: encodeTAAMinFineOffset }, - SPDIndexReadWriteLatency: { constVal: SPDValueReadWriteLatency }, - SPDIndexTRCDMin: { getVal: encodeTRCDMin }, - SPDIndexTRCDMinFineOffset: { getVal: encodeTRCDMinFineOffset }, - SPDIndexTRPABMin: { getVal: encodeTRPABMin }, - SPDIndexTRPABMinFineOffset: { getVal: encodeTRPABMinFineOffset }, - SPDIndexTRPPBMin: { getVal: encodeTRPPBMin }, - SPDIndexTRPPBMinFineOffset: { getVal: encodeTRPPBMinFineOffset }, - SPDIndexTRFCABMinLSB: { getVal: encodeTRFCABMinLsb }, - SPDIndexTRFCABMinMSB: { getVal: encodeTRFCABMinMsb }, - SPDIndexTRFCPBMinLSB: { getVal: encodeTRFCPBMinLsb }, - SPDIndexTRFCPBMinMSB: { getVal: encodeTRFCPBMinMsb }, -} - -type memParts struct { - MemParts []memPart `json:"parts"` -} - -type memPart struct { - Name string - Attribs memAttributes - SPDFileName string -} - -func writeSPDManifest(memParts *memParts, SPDDirName string) error { - var s string - - fmt.Printf("Generating SPD Manifest with following entries:\n") - - for i := 0; i < len(memParts.MemParts); i++ { - fmt.Printf("%-40s %s\n", memParts.MemParts[i].Name, memParts.MemParts[i].SPDFileName) - s += fmt.Sprintf("%s,%s\n", memParts.MemParts[i].Name, memParts.MemParts[i].SPDFileName) - } - - return ioutil.WriteFile(filepath.Join(SPDDirName, SPDManifestFileName), []byte(s), 0644) -} - -func isManufacturerPartNumberByte(index int) bool { - if index >= SPDIndexManufacturerPartNumberStartByte && index <= SPDIndexManufacturerPartNumberEndByte { - return true - } - return false -} - -func getSPDByte(index int, memAttribs *memAttributes) byte { - e, ok := SPDAttribTable[index] - if ok == false { - if isManufacturerPartNumberByte(index) { - return SPDValueManufacturerPartNumberBlank - } - return 0x00 - } - - if e.getVal != nil { - return e.getVal(memAttribs) - } - - return e.constVal -} - -func createSPD(memAttribs *memAttributes) string { - var s string - - for i := 0; i < 512; i++ { - b := getSPDByte(i, memAttribs) - - if (i + 1) % 16 == 0 { - s += fmt.Sprintf("%02X\n", b) - } else { - s += fmt.Sprintf("%02X ", b) - } - } - - return s -} - -func dedupeMemoryPart(dedupedParts []*memPart, memPart *memPart) bool { - for i := 0; i < len(dedupedParts); i++ { - if reflect.DeepEqual(dedupedParts[i].Attribs, memPart.Attribs) { - memPart.SPDFileName = dedupedParts[i].SPDFileName - return true - } - } - - return false -} - -func generateSPD(memPart *memPart, SPDId int, SPDDirName string) { - s := createSPD(&memPart.Attribs) - memPart.SPDFileName = fmt.Sprintf("spd-%d.hex", SPDId) - ioutil.WriteFile(filepath.Join(SPDDirName, memPart.SPDFileName), []byte(s), 0644) -} - -func readMemoryParts(memParts *memParts, memPartsFileName string) error { - databytes, err := ioutil.ReadFile(memPartsFileName) - if err != nil { - return err - } - - return json.Unmarshal(databytes, memParts) -} - -func validateDensityx8Channel(densityPerChannelGb int) error { - if _, ok := densityGbx8ChannelToRowColumnEncoding[densityPerChannelGb]; ok == false { - return fmt.Errorf("Incorrect x8 density: ", densityPerChannelGb, "Gb") - } - return nil -} - -func validateDensityx16Channel(densityPerChannelGb int) error { - if _, ok := densityGbx16ChannelToRowColumnEncoding[densityPerChannelGb]; ok == false { - return fmt.Errorf("Incorrect x16 density: ", densityPerChannelGb, "Gb") - } - return nil -} - -func validateDensity(memAttribs *memAttributes) error { - if memAttribs.BitWidthPerChannel == 8 { - return validateDensityx8Channel(memAttribs.DensityPerChannelGb) - } else if memAttribs.BitWidthPerChannel == 16 { - return validateDensityx16Channel(memAttribs.DensityPerChannelGb) - } - - return fmt.Errorf("No density table for this bit width: ", memAttribs.BitWidthPerChannel) -} - -func validateBanks(banks int) error { - if banks != 4 && banks != 8 { - return fmt.Errorf("Incorrect banks: ", banks) - } - return nil -} - -func validateChannels(channels int) error { - if channels != 1 && channels != 2 && channels != 4 { - return fmt.Errorf("Incorrect channels per die: ", channels) - } - return nil -} - -func validateDataWidth(width int) error { - if width != 8 && width != 16 { - return fmt.Errorf("Incorrect bit width: ", width) - } - return nil -} - -func validateRanks(ranks int) error { - if ranks != 1 && ranks != 2 { - return fmt.Errorf("Incorrect ranks: ", ranks) - } - return nil -} - -func validateSpeed(speed int) error { - if _, ok := speedMbpsToSPDEncoding[speed]; ok == false { - return fmt.Errorf("Incorrect speed: ", speed, " Mbps") - } - return nil -} - -func validateMemoryParts(memParts *memParts) error { - for i := 0; i < len(memParts.MemParts); i++ { - if err := validateBanks(memParts.MemParts[i].Attribs.Banks); err != nil { - return err - } - if err := validateChannels(memParts.MemParts[i].Attribs.ChannelsPerDie); err != nil { - return err - } - if err := validateDataWidth(memParts.MemParts[i].Attribs.BitWidthPerChannel); err != nil { - return err - } - if err := validateDensity(&memParts.MemParts[i].Attribs); err != nil { - return err - } - if err := validateRanks(memParts.MemParts[i].Attribs.RanksPerChannel); err != nil { - return err - } - if err := validateSpeed(memParts.MemParts[i].Attribs.SpeedMbps); err != nil { - return err - } - } - return nil -} - -func encodeLatencies(latency int, memAttribs *memAttributes) error { - switch latency { - case 6: - memAttribs.CASFirstByte |= CAS6 - case 10: - memAttribs.CASFirstByte |= CAS10 - case 14: - memAttribs.CASFirstByte |= CAS14 - case 16: - memAttribs.CASSecondByte |= CAS16 - case 20: - memAttribs.CASSecondByte |= CAS20 - case 22: - memAttribs.CASSecondByte |= CAS22 - case 24: - memAttribs.CASSecondByte |= CAS24 - case 26: - memAttribs.CASSecondByte |= CAS26 - case 28: - memAttribs.CASSecondByte |= CAS28 - case 32: - memAttribs.CASThirdByte |= CAS32 - case 36: - memAttribs.CASThirdByte |= CAS36 - case 40: - memAttribs.CASThirdByte |= CAS40 - default: - fmt.Errorf("Incorrect CAS Latency: ", latency) - } - - return nil -} - -func updateTCK(memAttribs *memAttributes) { - if memAttribs.TCKMinPs == 0 { - memAttribs.TCKMinPs = speedMbpsToSPDEncoding[memAttribs.SpeedMbps].TCKMinPs - } - if memAttribs.TCKMaxPs == 0 { - memAttribs.TCKMaxPs = speedMbpsToSPDEncoding[memAttribs.SpeedMbps].TCKMaxPs - } -} - -func getCASLatencies(memAttribs *memAttributes) string { - if memAttribs.BitWidthPerChannel == 16 { - return speedMbpsToSPDEncoding[memAttribs.SpeedMbps].CASLatenciesx16Channel - } else if memAttribs.BitWidthPerChannel == 8 { - return speedMbpsToSPDEncoding[memAttribs.SpeedMbps].CASLatenciesx8Channel - } - - return "" -} - -func updateCAS(memAttribs *memAttributes) error { - if len(memAttribs.CASLatencies) == 0 { - memAttribs.CASLatencies = getCASLatencies(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 := encodeLatencies(latency, memAttribs); err != nil { - return err - } - } - return nil -} - -func getMinCAS(memAttribs *memAttributes) (int, error) { - if (memAttribs.CASThirdByte & CAS40) != 0 { - return 40, nil - } - if (memAttribs.CASThirdByte & CAS36) != 0 { - return 36, nil - } - if (memAttribs.CASThirdByte & CAS32) != 0 { - return 32, nil - } - if (memAttribs.CASSecondByte & CAS28) != 0 { - return 28, nil - } - - return 0, fmt.Errorf("Unexpected min CAS") -} - -func updateTAAMin(memAttribs *memAttributes) error { - if memAttribs.TAAMinPs == 0 { - minCAS, err := getMinCAS(memAttribs) - if err != nil { - return err - } - memAttribs.TAAMinPs = memAttribs.TCKMinPs * minCAS - } - - return nil -} - -func updateTRFCAB(memAttribs *memAttributes) { - if memAttribs.TRFCABNs == 0 { - memAttribs.TRFCABNs = densityGbPhysicalChannelToRefreshEncoding[memAttribs.DensityPerChannelGb].TRFCABNs - } -} - -func updateTRFCPB(memAttribs *memAttributes) { - if memAttribs.TRFCPBNs == 0 { - memAttribs.TRFCPBNs = densityGbPhysicalChannelToRefreshEncoding[memAttribs.DensityPerChannelGb].TRFCPBNs - } -} - -func updateTRCD(memAttribs *memAttributes) { - if memAttribs.TRCDMinNs == 0 { - /* JEDEC spec says max of 18ns */ - memAttribs.TRCDMinNs = 18 - } -} - -func updateTRPAB(memAttribs *memAttributes) { - if memAttribs.TRPABMinNs == 0 { - /* JEDEC spec says max of 21ns */ - memAttribs.TRPABMinNs = 21 - } -} - -func updateTRPPB(memAttribs *memAttributes) { - if memAttribs.TRPPBMinNs == 0 { - /* JEDEC spec says max of 18ns */ - memAttribs.TRPPBMinNs = 18 - } -} - -func normalizeMemoryAttributes(memAttribs *memAttributes) { - if currPlatform == PlatformTGL { - /* - * 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 - } -} - -func updateMemoryAttributes(memAttribs *memAttributes) error { - updateTCK(memAttribs) - if err := updateCAS(memAttribs); err != nil { - return err - } - if err := updateTAAMin(memAttribs); err != nil { - return err - } - updateTRFCAB(memAttribs) - updateTRFCPB(memAttribs) - updateTRCD(memAttribs) - updateTRPAB(memAttribs) - updateTRPPB(memAttribs) - - normalizeMemoryAttributes(memAttribs) - - return nil -} - -func isPlatformSupported(platform string) error { - var ok bool - - currPlatform, ok = platformMap[platform] - if ok == false { - return fmt.Errorf("Unsupported platform: ", platform) - } - - return nil -} - -func usage() { - fmt.Printf("\nUsage: %s <spd_dir> <mem_parts_list_json> <platform>\n\n", os.Args[0]) - fmt.Printf(" where,\n") - fmt.Printf(" spd_dir = Directory path containing SPD files and manifest generated by gen_spd.go\n") - fmt.Printf(" mem_parts_list_json = JSON File containing list of memory parts and attributes\n") - fmt.Printf(" platform = SoC Platform for which the SPDs are being generated\n\n\n") -} - -func main() { - if len(os.Args) != 4 { - usage() - log.Fatal("Incorrect number of arguments") - } - - var memParts memParts - var dedupedParts []*memPart - - SPDDir, GlobalMemPartsFile, Platform := os.Args[1], os.Args[2], strings.ToUpper(os.Args[3]) - - if err := isPlatformSupported(Platform); err != nil { - log.Fatal(err) - } - - if err := readMemoryParts(&memParts, GlobalMemPartsFile); err != nil { - log.Fatal(err) - } - - if err := validateMemoryParts(&memParts); err != nil { - log.Fatal(err) - } - - SPDId := 1 - - for i := 0; i < len(memParts.MemParts); i++ { - if err := updateMemoryAttributes(&memParts.MemParts[i].Attribs); err != nil { - log.Fatal(err) - } - - if dedupeMemoryPart(dedupedParts, &memParts.MemParts[i]) == false { - generateSPD(&memParts.MemParts[i], SPDId, SPDDir) - SPDId++ - dedupedParts = append(dedupedParts, &memParts.MemParts[i]) - } - } - - if err := writeSPDManifest(&memParts, SPDDir); err != nil { - log.Fatal(err) - } -} |