Nick Vaccaro has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
util: Add spd_tools to generate SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 6 files changed, 2,186 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/1
diff --git a/util/spd_tools/intel/ddr4/README.md b/util/spd_tools/intel/ddr4/README.md new file mode 100644 index 0000000..543e309 --- /dev/null +++ b/util/spd_tools/intel/ddr4/README.md @@ -0,0 +1,238 @@ +# DDR4 SPD tools README + +Tools for generating SPD files for DDR4 memory used in memory down +configurations on Intel Tiger Lake (TGL) based +platforms. These tools generate SPDs following JESD79-4C +and Jedec 4.1.2.L-5 R29 v103 specifications. + +There are two tools provided that assist TGL based mainboards +to generate SPDs and Makefile to integrate these SPDs in coreboot +build. These tools can also be used to allocate DRAM IDs (configure +DRAM hardware straps) for any DDR4 memory part used by the board. + +* gen_spd.go: Generates de-duplicated SPD files using a global memory + part list provided by the mainboard in JSON format. Additionally, + generates a SPD manifest file(in CSV format) with information about + what memory part from the global list uses which of the generated + SPD files. + +* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 + memory parts used by the board. Takes as input list of memory parts + used by the board (with one memory part on each line) and the SPD + manifest file generated by gen_spd.go. Generates Makefile.inc for + integrating the generated SPD files in the coreboot build. + +## Tool 1 - gen_spd.go + +This program takes as input: +* Pointer to directory where the generated SPD files and manifest will + be placed. +* JSON file containing a global list of memory parts with their + attributes as per the datasheet. This is the list of all known + DDR4 memory parts irrespective of their usage on the board. +* SoC platform name for which the SPDs are being generated. Currently + supported platform names are `TGL`. + +Input JSON file requires the following two fields for every memory part: +* `name`: Name of the memory part +* `attribs`: List of attributes of the memory part as per its + datasheet. These attributes match the part specifications and are + independent of any SoC expectations. Tool takes care of translating + the physical attributes of the memory part to match JEDEC and Intel + MRC expectations. + +`attribs` field further contains two types of sub-fields: +* Mandatory: These attributes have to be provided for a memory part. +* Optional: These attributes can be provided by memory part if it wants + to override the defaults. + +### Mandatory `attribs` + +* `name`: Name of the DDR4 memory part being described with these attributes. + +* `speedBin`: Speed bin for the part. Valid values: + `"1600J", "1600K", "1600L", "1866L", "1866M", "1866N", "2133N", "2133P", + "2133R", "2400P", "2400R", "2400T", "2400U", "2666T", "2666U", "2666V", + "2666W", "2933V", "2933W", "2933Y", "2933AA", "3200W", "3200AA", "3200AC"` + +* `bankGroups`: Number of bank groups. Valid values: + `0, 2, 4` bank groups. + +* `banksPerGroup`: Number of banks per bank group. Valid values: + `4, 8` banks per group. + +* `capacityPerDieGb`: Capacity per die in gigabits. Valid values: + `1, 2, 4, 8, 16, 32` Gb part. + +* `pageSize`: Page size represented as number of 512-byte blocks. Valid values: + * 1 : 1/2 KB page size + * 2 : 1 KB page size + * 4 : 2 KB page size + +* `diesPerPackage`: Number of dies on the part. Valid values: + `1, 2, 3, 4, 5, 6, 7, 8` dies per package. + +* `deviceBusWidth`: Number of bits of the device's address bus. Valid values: + `8, 16, 32` bit-wide bus. + +* `signalLoading`: Refers to loading on signals at the SDRAM balls. Loading on + certain signals (CKE, ODT, etc.) per specification of device stacking as + defined in JESD79-4CNumber of bits of the device's address bus. Valid values: + `"not specified", "single", "multi"` + +* `packageRanks`: From Jedec doc 4_01_02_AnnexL-1R23: + “Package ranks per DIMM” refers to the collections of devices on the module + sharing common chip select signals (across the data width of the DIMM), + either from the edge connector for unbuffered modules or from the outputs of + a registering clock driver for RDIMMs and LRDIMMs.Number of bits of the + device's address bus. Valid values: + `1, 2, 3, 4` package ranks. + +### Optional `attribs` + + FIXME - add all optional parameters + +### Example JSON file +``` +{ + "parts": [ + { + "name": "MEMORY_PART_A", + "attribs": { + "speedBin": "3200AA", + "bankGroups": 4, + "banksPerGroup": 4, + "capacityPerDieGb": 8, + "pageSize": 2, + "diesPerPackage": 2, + "deviceBusWidth": 16, + "signalLoading": "multi", + "ranksPerPackage": 1 + } + }, + { + "name": "MEMORY_PART_B", + "attribs": { + "speedBin": "3200AA", + "bankGroups": 2, + "banksPerGroup": 4, + "capacityPerDieGb": 8, + "pageSize": 2, + "diesPerPackage": 1, + "deviceBusWidth": 16, + "signalLoading": "single", + "ranksPerPackage": 2, + "casLatencies": "9 10 11 12 13 14 15 16 17 18 19 20", + "tCKMaxPs": "1250" + } + } + ] +} +``` + +### Output + +This tool generates the following files using the global list of +memory parts in JSON format as described above: + * De-duplicated SPDs required for the different memory parts. These + SPD files are named (spd_1.hex, spd_2.hex, spd_3.hex and so on) + and placed in the directory provided as an input to the tool. + * CSV file representing which of the deduplicated SPD files is used + by which memory part. This file is named as + `spd_manifest.generated.txt` and placed in the directory provided + as an input to the tool along with the generated SPD + files. Example CSV file: + ``` + MEMORY_PART_A, spd_1.hex + MEMORY_PART_B, spd_2.hex + MEMORY_PART_C, spd_3.hex + MEMORY_PART_D, spd_2.hex + MEMORY_PART_E, spd_2.hex + ``` + +## Tool 2 - gen_part_id.go + +This program takes as input: +* Pointer to directory where the SPD files and the manifest file + `spd_manifest.generated.txt` (in CSV format) are placed by + gen_spd.go +* File containing list of memory parts used by the board. Each line of + the file is supposed to contain one memory part `name` as present in + the global list of memory parts provided to gen_spd.go +* Pointer to directory where the generated Makefile.inc should be + placed by the tool. + +### Output + +This program provides the following: + +* Prints out the list of DRAM hardware strap IDs that should be + allocated to each memory part listed in the input file. +* Makefile.inc is generated in the provided directory to integrate + SPDs generated by gen_spd.go with the coreboot build for the board. +* dram_id.generated.txt is generated in the same directory as + Makefile. This contains the part IDs assigned to the different + memory parts. (Useful to integrate in board schematics). + +Sample output (dram_id.generated.txt): +``` +DRAM Part Name ID to assign +MEMORY_PART_A 0 (0000) +MEMORY_PART_B 1 (0001) +MEMORY_PART_C 2 (0010) +MEMORY_PART_D 1 (0001) +``` + +Sample Makefile.inc: +``` +## SPDX-License-Identifier: GPL-2.0-or-later +## This is an auto-generated file. Do not edit!! + +SPD_SOURCES = +SPD_SOURCES += spd_1.hex # ID = 0(0b0000) Parts = MEMORY_PART_A +SPD_SOURCES += spd_2.hex # ID = 1(0b0001) Parts = MEMORY_PART_B, MEMORY_PART_D +SPD_SOURCES += spd_3.hex # ID = 2(0b0010) Parts = MEMORY_PART_C +``` + +### Note of caution + +This program assigns DRAM IDs using the order of DRAM part names +provided in the input file. Thus, when adding a new memory part to the +list, it should always go to the end of the input text file. This +guarantees that the memory parts that were already assigned IDs do not +change. + +## How to build the tools? +``` +# go build gen_spd.go +# go build gen_part_id.go +``` + +## How to use the tools? +``` +# ./gen_spd <spd_dir> <mem_parts_list_json> <platform> +# ./gen_part_id <spd_dir> <makefile_dir> <mem_parts_used_file> +``` + +## Example Usage +``` +# ./gen_spd ../../../../src/soc/intel/tigerlake/spd/ddr4 ./global_ddr4_mem_parts.json.txt 'TGL' + +``` + +### Need to add a new memory part for a board? + +* If the memory part is not present in the global list of memory + parts, then add the memory part name and attributes as per the + datasheet to the file containing the global list. + * Use `gen_spd.go` with input as the file containing the global list + of memory parts to generate de-duplicated SPDs. + * If a new SPD file is generated, use `git add` to add it to the + tree and push a CL for review. +* Update the file containing memory parts used by board (variant) to + add the new memory part name at the end of the file. + * Use gen_part_id.go providing it pointer to the location where SPD + files are stored and file containing the list of memory parts used + by the board(variant). + * Use `git add` to add `Makefile.inc` and `dram_id.generated.txt` + with updated changes and push a CL for review. diff --git a/util/spd_tools/intel/ddr4/gen_part_id b/util/spd_tools/intel/ddr4/gen_part_id new file mode 100755 index 0000000..6d0061f --- /dev/null +++ b/util/spd_tools/intel/ddr4/gen_part_id Binary files differ diff --git a/util/spd_tools/intel/ddr4/gen_part_id.go b/util/spd_tools/intel/ddr4/gen_part_id.go new file mode 100644 index 0000000..6c2ca11 --- /dev/null +++ b/util/spd_tools/intel/ddr4/gen_part_id.go @@ -0,0 +1,214 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +package main + +import ( + "encoding/csv" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" +) + +/* + * This program allocates DRAM strap IDs for different parts that are being used by the variant. + * + * It expects the following inputs: + * Pointer to SPD directory. This is the location where SPD files and SPD Manifest generated by + * gen_spd.go are placed. + * Pointer to Makefile directory. Makefile.inc generated by this program is placed in this + * location. + * Text file containing a list of memory parts names used by the board. Each line in the file + * is expected to have one memory part name. + */ +const ( + SPDManifestFileName = "spd_manifest.generated.txt" + MakefileName = "Makefile.inc" + DRAMIdFileName = "dram_id.generated.txt" +) + +func usage() { + fmt.Printf("\nUsage: %s <spd_dir> <makefile_dir> <mem_parts_used_file>\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(" makefile_dir = Directory path where generated Makefile.inc should be placed\n") + fmt.Printf(" mem_parts_used_file = File containing list of memory parts used by the board\n\n\n") +} + +func checkArgs() error { + + for _, arg := range os.Args[1:] { + if _, err := os.Stat(arg); err != nil { + return err + } + } + + return nil +} + +/* + * Read input file that contains list of memory part names used by the variant (one on a line) + * and split into separate strings for each part name. + */ +func readParts(memPartsUsedFileName string) ([]string, error) { + lines, err := ioutil.ReadFile(memPartsUsedFileName) + if err != nil { + return nil, err + } + str := string(lines) + parts := strings.Split(str, "\n") + + return parts, nil +} + +/* + * Read SPD manifest file(CSV) generated by gen_spd program and generate two maps: + * 1. Part to SPD Map : This maps global memory part name to generated SPD file name + * 2. SPD to Index Map: This generates a map of deduplicated SPD file names to index assigned to + * that SPD. This function sets index for all SPDs to -1. This index gets + * updated as part of genPartIdInfo() depending upon the SPDs actually used + * by the variant. + */ +func readSPDManifest(SPDDirName string) (map[string]string, map[string]int, error) { + f, err := os.Open(filepath.Join(SPDDirName, SPDManifestFileName)) + if err != nil { + return nil, nil, err + } + defer f.Close() + r := csv.NewReader(f) + + partToSPDMap := make(map[string]string) + SPDToIndexMap := make(map[string]int) + + for { + fields, err := r.Read() + + if err == io.EOF { + break + } + + if err != nil { + return nil, nil, err + } + + if len(fields) != 2 { + return nil, nil, fmt.Errorf("CSV file is incorrectly formatted") + } + + partToSPDMap[fields[0]] = fields[1] + SPDToIndexMap[fields[1]] = -1 + } + + return partToSPDMap, SPDToIndexMap, nil +} + +/* Print information about memory part used by variant and ID assigned to it. */ +func appendPartIdInfo(s *string, partName string, index int) { + *s += fmt.Sprintf("%-30s %d (%04b)\n", partName, index, int64(index)) +} + +type partIds struct { + SPDFileName string + memParts string +} + +/* + * For each part used by variant, check if the SPD (as per the manifest) already has an ID + * assigned to it. If yes, then add the part name to the list of memory parts supported by the + * SPD entry. If not, then assign the next ID to the SPD file and add the part name to the + * list of memory parts supported by the SPD entry. + * + * Returns list of partIds that contains spdFileName and supported memory parts for each + * assigned ID. + */ +func genPartIdInfo(parts []string, partToSPDMap map[string]string, SPDToIndexMap map[string]int, makefileDirName string) ([]partIds, error) { + partIdList := []partIds{} + curId := 0 + var s string + + s += fmt.Sprintf("%-30s %s\n", "DRAM Part Name", "ID to assign") + + for _, p := range parts { + if p == "" { + continue + } + + SPDFileName,ok := partToSPDMap[p] + if !ok { + return nil, fmt.Errorf("Failed to find part ", p, " in SPD Manifest. Please add the part to global part list and regenerate SPD Manifest") + } + + index := SPDToIndexMap[SPDFileName] + if index != -1 { + partIdList[index].memParts += ", " + p + appendPartIdInfo(&s, p, index) + continue + } + + SPDToIndexMap[SPDFileName] = curId + + appendPartIdInfo(&s, p, curId) + entry := partIds{SPDFileName: SPDFileName, memParts: p} + partIdList = append(partIdList, entry) + + curId++ + } + + fmt.Printf("%s", s) + err := ioutil.WriteFile(filepath.Join(makefileDirName, DRAMIdFileName), []byte(s), 0644) + + return partIdList, err +} + +var generatedCodeLicense string = "## SPDX-License-Identifier: GPL-2.0-or-later" +var autoGeneratedInfo string = "## This is an auto-generated file. Do not edit!!" + +/* + * This function generates Makefile.inc under the variant directory path and adds assigned SPDs + * to SPD_SOURCES. + */ +func genMakefile(partIdList []partIds, makefileDirName string) error { + var s string + + s += fmt.Sprintf("%s\n%s\n\n", generatedCodeLicense, autoGeneratedInfo) + s += fmt.Sprintf("SPD_SOURCES =\n") + + for i := 0; i < len(partIdList); i++ { + s += fmt.Sprintf("SPD_SOURCES += %s ", partIdList[i].SPDFileName) + s += fmt.Sprintf(" # ID = %d(0b%04b) ", i, int64(i)) + s += fmt.Sprintf(" Parts = %04s\n", partIdList[i].memParts) + } + + return ioutil.WriteFile(filepath.Join(makefileDirName, MakefileName), []byte(s), 0644) +} + +func main() { + if len(os.Args) != 4 { + usage() + log.Fatal("Incorrect number of arguments") + } + + SPDDir, MakefileDir, MemPartsUsedFile := os.Args[1], os.Args[2], os.Args[3] + + partToSPDMap, SPDToIndexMap, err := readSPDManifest(SPDDir) + if err != nil { + log.Fatal(err) + } + + parts, err := readParts(MemPartsUsedFile) + if err != nil { + log.Fatal(err) + } + + partIdList, err := genPartIdInfo(parts, partToSPDMap, SPDToIndexMap, MakefileDir) + if err != nil { + log.Fatal(err) + } + + if err := genMakefile(partIdList, MakefileDir); err != nil { + log.Fatal(err) + } +} diff --git a/util/spd_tools/intel/ddr4/gen_spd b/util/spd_tools/intel/ddr4/gen_spd new file mode 100755 index 0000000..c52f528 --- /dev/null +++ b/util/spd_tools/intel/ddr4/gen_spd Binary files differ diff --git a/util/spd_tools/intel/ddr4/gen_spd.go b/util/spd_tools/intel/ddr4/gen_spd.go new file mode 100644 index 0000000..dc0b97c --- /dev/null +++ b/util/spd_tools/intel/ddr4/gen_spd.go @@ -0,0 +1,1716 @@ +/* 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 DDR4 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, +} + +var currPlatform int + +type memAttributes struct { + /* Primary attributes - must be provided by JSON file for each part */ + SpeedBin string + BankGroups int + BanksPerGroup int + CapacityPerDieGb int + PageSize int + DiesPerPackage int + DeviceBusWidth int + SignalLoading string + RanksPerPackage int + + /* + * All the following parameters are optional and required only if the part requires + * special parameters as per the datasheet. + */ + /* Timing parameters */ + TAAMinPs int + TRCDMinPs int + TRPMinPs int + TRASMinPs int + TRCMinPs int + TCKMinPs int + TCKMaxPs int + TFAWMinPs int + TRRDLMinPs int + TRRDSMinPs int + TCCDLMinPs int + TWRMinPs int + TWTRLMinPs int + TWTRSMinPs int + + /* CAS */ + CASLatencies string + CASFirstByte byte + CASSecondByte byte + CASThirdByte byte + CASFourthByte byte +} + +const ( + SignalLoadingNotSpecified = "not specified" + SignalLoadingSingleLoadStack = "single" + SignalLoadingMultiLoadStack = "multi" +) + +/* This encodes the density in Gb to SPD low nibble value as per JESD 4.1.2.L-5 R29 */ +var densityGbToSPDEncoding = map[int]byte { + 1: 0x2, + 2: 0x3, + 4: 0x4, + 8: 0x5, + 16: 0x6, + 32: 0x7, +} + +/* + * Tables 4 thru Table 7 from JESD79-4C. + * Maps density per physical channel to row-column encoding for a device with x8/x16 + * physical channel. + */ +var densityGbx8x16ChannelToRowColumnEncoding = map[int]byte { + 2: 0x11, /* 14 rows, 10 columns */ + 4: 0x19, /* 15 rows, 10 columns */ + 8: 0x21, /* 16 rows, 10 columns */ + 16: 0x29, /* 17 rows, 10 columns */ +} + +/* + * Table 61 from JEDEC spec 4_01_02_AnnexL-5R29 + * Maps die density to refresh timings. This is the same for x8 and x16 + * devices. + */ + +/* maps die density to rcf1 timing in pico seconds */ +var tRFC1Encoding = map[int]int { + 2: 160000, + 4: 260000, + 8: 350000, + 16: 550000, +} + +/* maps die density to rcf2 timing in pico seconds */ +var tRFC2Encoding = map[int]int { + 2: 110000, + 4: 160000, + 8: 260000, + 16: 350000, +} + +/* maps die density to rcf4 timing in pico seconds */ +var tRFC4Encoding = map[int]int { + 2: 90000, + 4: 110000, + 8: 160000, + 16: 260000, +} + +const ( + /* SDRAM Configuration Types */ + SDRAMConfig256Mbx8 = 0 + SDRAMConfig512Mbx8 = 1 + SDRAMConfig1Gbx8 = 2 + SDRAMConfig2Gbx8 = 3 + SDRAMConfig128Mbx16 = 4 + SDRAMConfig256Mbx16 = 5 + SDRAMConfig512Mbx16 = 6 + SDRAMConfig1Gbx16 = 7 +) + +const ( + /* SPEED Bin Grades */ + SpeedBin1600J = "1600J" + SpeedBin1600K = "1600K" + SpeedBin1600L = "1600L" + SpeedBin1866L = "1866L" + SpeedBin1866M = "1866M" + SpeedBin1866N = "1866N" + SpeedBin2133N = "2133N" + SpeedBin2133P = "2133P" + SpeedBin2133R = "2133R" + SpeedBin2400P = "2400P" + SpeedBin2400R = "2400R" + SpeedBin2400T = "2400T" + SpeedBin2400U = "2400U" + SpeedBin2666T = "2666T" + SpeedBin2666U = "2666U" + SpeedBin2666V = "2666V" + SpeedBin2666W = "2666W" + SpeedBin2933V = "2933V" + SpeedBin2933W = "2933W" + SpeedBin2933Y = "2933Y" + SpeedBin2933AA = "2933AA" + SpeedBin3200W = "3200W" + SpeedBin3200AA = "3200AA" + SpeedBin3200AC = "3200AC" + + /* + * FIXME - update to include all from Table 48 on Page 4.1.2.L-5 – 30: + * different min CAS times (tAAMin, RCDMin, RPMin)) + */ +) + +const ( + /* SPEED Bin Grades */ + SpeedBin1600 = 0 + SpeedBin1866 = 1 + SpeedBin2133 = 2 + SpeedBin2400 = 3 + SpeedBin2666 = 4 + SpeedBin2933 = 5 + SpeedBin3200 = 6 +) + +var speedBinMinorToMajor = map[string]int { + SpeedBin1600J: SpeedBin1600, + SpeedBin1600K: SpeedBin1600, + SpeedBin1600L: SpeedBin1600, + SpeedBin1866L: SpeedBin1866, + SpeedBin1866M: SpeedBin1866, + SpeedBin1866N: SpeedBin1866, + SpeedBin2133N: SpeedBin2133, + SpeedBin2133P: SpeedBin2133, + SpeedBin2133R: SpeedBin2133, + SpeedBin2400P: SpeedBin2400, + SpeedBin2400R: SpeedBin2400, + SpeedBin2400T: SpeedBin2400, + SpeedBin2400U: SpeedBin2400, + SpeedBin2666T: SpeedBin2666, + SpeedBin2666U: SpeedBin2666, + SpeedBin2666V: SpeedBin2666, + SpeedBin2666W: SpeedBin2666, + SpeedBin2933V: SpeedBin2933, + SpeedBin2933W: SpeedBin2933, + SpeedBin2933Y: SpeedBin2933, + SpeedBin3200W: SpeedBin3200, + SpeedBin3200AA: SpeedBin3200, + SpeedBin3200AC: SpeedBin3200, +} + + /* + * TODO: + * - Implement RFC1, RFC2, RFC4 conversion routine + * - Add updateXXX for each "type XXX struct {" + * - Add map function from speed bin sub-category to major category + * - Fix case statements for speed bins to use new map function to limit options + * - Find and address FIXMEs + * + * Question: Do we support 3DS ? + */ + +var speedBinToSPDEncoding = map[string]memAttributes { + SpeedBin1600J: { + TAAMinPs: 12500, + TRCDMinPs: 12500, + TRPMinPs: 12500, + TRASMinPs: 35000, + TRCMinPs: 47500, + TCKMinPs: 1250, + TCKMaxPs: 1500, + CASLatencies: "9 10 11 12", + }, + SpeedBin1600K: { + TAAMinPs: 13750, + TRCDMinPs: 13750, + TRPMinPs: 13750, + TRASMinPs: 35000, + TRCMinPs: 48750, + TCKMinPs: 1250, + TCKMaxPs: 1500, + CASLatencies: "9 11 12", + }, + SpeedBin1600L: { + TAAMinPs: 15000, + TRCDMinPs: 15000, + TRPMinPs: 15000, + TRASMinPs: 35000, + TRCMinPs: 50000, + TCKMinPs: 1250, + TCKMaxPs: 1500, + CASLatencies: "10 12", + }, + SpeedBin1866L: { + TAAMinPs: 12850, + TRCDMinPs: 12850, + TRPMinPs: 12850, + TRASMinPs: 34000, + TRCMinPs: 46850, + TCKMinPs: 1071, + TCKMaxPs: 1250, + CASLatencies: "9 10 12 13 14", + }, + SpeedBin1866M: { + TAAMinPs: 13920, + TRCDMinPs: 13920, + TRPMinPs: 13920, + TRASMinPs: 34000, + TRCMinPs: 47920, + TCKMinPs: 1071, + TCKMaxPs: 1250, + CASLatencies: "9 11 12 13 14", + }, + SpeedBin1866N: { + TAAMinPs: 15000, + TRCDMinPs: 15000, + TRPMinPs: 15000, + TRASMinPs: 34000, + TRCMinPs: 49000, + TCKMinPs: 1071, + TCKMaxPs: 1250, + CASLatencies: "10 12 14", + }, + SpeedBin2133N: { + TAAMinPs: 13130, + TRCDMinPs: 13130, + TRPMinPs: 13130, + TRASMinPs: 33000, + TRCMinPs: 46130, + TCKMinPs: 937, + TCKMaxPs: 1071, + CASLatencies: "9 10 12 14 15 16", + }, + SpeedBin2133P: { + TAAMinPs: 14060, + TRCDMinPs: 14060, + TRPMinPs: 14060, + TRASMinPs: 33000, + TRCMinPs: 47060, + TCKMinPs: 937, + TCKMaxPs: 1071, + CASLatencies: "9 11 12 13 14 15 16", + }, + SpeedBin2133R: { + TAAMinPs: 15000, + TRCDMinPs: 15000, + TRPMinPs: 15000, + TRASMinPs: 33000, + TRCMinPs: 48000, + TCKMinPs: 937, + TCKMaxPs: 1071, + CASLatencies: "10 12 14 16", + }, + SpeedBin2400P: { + TAAMinPs: 12500, + TRCDMinPs: 12500, + TRPMinPs: 12500, + TRASMinPs: 32000, + TRCMinPs: 44500, + TCKMinPs: 833, + TCKMaxPs: 937, + CASLatencies: "9 10 12 13 15 16 17 18", + }, + SpeedBin2400R: { + TAAMinPs: 13320, + TRCDMinPs: 13320, + TRPMinPs: 13320, + TRASMinPs: 32000, + TRCMinPs: 45320, + TCKMinPs: 833, + TCKMaxPs: 937, + CASLatencies: "9 11 12 13 14 15 16 17 18", + }, + SpeedBin2400T: { + TAAMinPs: 14160, + TRCDMinPs: 14160, + TRPMinPs: 14160, + TRASMinPs: 32000, + TRCMinPs: 46160, + TCKMinPs: 833, + TCKMaxPs: 937, + CASLatencies: "10 11 12 13 14 15 16 17 18", + }, + SpeedBin2400U: { + TAAMinPs: 15000, + TRCDMinPs: 15000, + TRPMinPs: 15000, + TRASMinPs: 32000, + TRCMinPs: 47000, + TCKMinPs: 833, + TCKMaxPs: 937, + CASLatencies: "10 12 14 16 18", + }, + SpeedBin2666T: { + TAAMinPs: 12750, + TRCDMinPs: 12750, + TRPMinPs: 12750, + TRASMinPs: 32000, + TRCMinPs: 44750, + TCKMinPs: 750, + TCKMaxPs: 833, + CASLatencies: "9 10 11 12 13 14 15 16 17 18 19 20", + }, + SpeedBin2666U: { + TAAMinPs: 13500, + TRCDMinPs: 13500, + TRPMinPs: 13500, + TRASMinPs: 32000, + TRCMinPs: 45500, + TCKMinPs: 750, + TCKMaxPs: 833, + CASLatencies: "9 10 11 12 13 14 15 16 17 18 19 20", + }, + SpeedBin2666V: { + TAAMinPs: 14250, + TRCDMinPs: 14250, + TRPMinPs: 14250, + TRASMinPs: 32000, + TRCMinPs: 46250, + TCKMinPs: 750, + TCKMaxPs: 833, + CASLatencies: "10 11 12 13 14 15 16 17 18 19 20", + }, + SpeedBin2666W: { + TAAMinPs: 15000, + TRCDMinPs: 15000, + TRPMinPs: 15000, + TRASMinPs: 32000, + TRCMinPs: 47000, + TCKMinPs: 750, + TCKMaxPs: 833, + CASLatencies: "10 12 14 16 18", + }, + SpeedBin2933V: { + TAAMinPs: 12960, + TRCDMinPs: 12960, + TRPMinPs: 12960, + TRASMinPs: 32000, + TRCMinPs: 44960, + TCKMinPs: 682, + TCKMaxPs: 750, + CASLatencies: "9 10 11 12 13 14 15 16 17 18 19 20 21 22", + }, + SpeedBin2933W: { + TAAMinPs: 13640, + TRCDMinPs: 13640, + TRPMinPs: 13640, + TRASMinPs: 32000, + TRCMinPs: 45640, + TCKMinPs: 682, + TCKMaxPs: 750, + CASLatencies: "10 11 12 13 14 15 16 17 18 19 20 21 22", + }, + SpeedBin2933Y: { + TAAMinPs: 14320, + TRCDMinPs: 14320, + TRPMinPs: 14320, + TRASMinPs: 32000, + TRCMinPs: 46320, + TCKMinPs: 682, + TCKMaxPs: 750, + CASLatencies: "10 11 12 13 14 15 16 17 18 19 20 21 22", + }, + SpeedBin2933AA: { + TAAMinPs: 15000, + TRCDMinPs: 15000, + TRPMinPs: 15000, + TRASMinPs: 32000, + TRCMinPs: 47000, + TCKMinPs: 682, + TCKMaxPs: 750, + CASLatencies: "10 12 14 16 18 20 22", + }, + SpeedBin3200W: { + TAAMinPs: 12500, + TRCDMinPs: 12500, + TRPMinPs: 12500, + TRASMinPs: 32000, + TRCMinPs: 44500, + TCKMinPs: 625, + TCKMaxPs: 682, + CASLatencies: "9 10 11 12 13 14 15 16 17 18 19 20 21 22 24", + }, + SpeedBin3200AA: { + TAAMinPs: 13750, + TRCDMinPs: 13750, + TRPMinPs: 13750, + TRASMinPs: 32000, + TRCMinPs: 45750, + TCKMinPs: 625, + TCKMaxPs: 682, + CASLatencies: "10 11 12 13 14 15 16 17 18 19 20 21 22 24", + }, + SpeedBin3200AC: { + TAAMinPs: 15000, + TRCDMinPs: 15000, + TRPMinPs: 15000, + TRASMinPs: 32000, + TRCMinPs: 47000, + TCKMinPs: 625, + TCKMaxPs: 682, + CASLatencies: "10 12 14 16 18 20 22 24", + }, +} + +var banksPerGroupEncoding = map[int]byte { + 4: 0 << 4, + 8: 1 << 4, +} + +var bankGroupsEncoding = map[int]byte { + 0: 0 << 6, + 2: 1 << 6, + 4: 2 << 6, +} + +func encodeDensityBanks(memAttribs *memAttributes) byte { + var b byte + + b = densityGbToSPDEncoding[memAttribs.CapacityPerDieGb] + b |= banksPerGroupEncoding[memAttribs.BanksPerGroup] + b |= bankGroupsEncoding[memAttribs.BankGroups] + + return b +} + +func encodeSdramAddressing(memAttribs *memAttributes) byte { + var b byte + + b = densityGbx8x16ChannelToRowColumnEncoding[memAttribs.CapacityPerDieGb] + + return b +} + +func encodePackage(dies int) byte { + var b byte + + if dies > 1 { + /* If more than one die, then this is a non-monolithic device. */ + b = 1 + } else { + /* If only single die, then this is a monolithic device. */ + b = 0 + } + + return b << 7 +} + +func encodeDiesPerPackage(dies int) byte { + var b byte + + b = encodePackage(dies) /* Monolithic / Non-monolithic device */ + b |= (byte(dies) - 1) << 4 + + return b +} + +var signalLoadingEncode = map[string]byte { + "not specified": 0, + "single": 1, + "multi": 2, +} + +func encodeSignalLoading(loading string) byte { + return(signalLoadingEncode[loading]) +} + +func encodePackageType(memAttribs *memAttributes) byte { + var b byte + + b = encodeSignalLoading(memAttribs.SignalLoading) + b |= encodeDiesPerPackage(memAttribs.DiesPerPackage) + b |= encodePackage(memAttribs.DiesPerPackage) + + return b +} + +func encodeDataWidth(bitWidthPerDevice int) byte { + return byte(bitWidthPerDevice / 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.DeviceBusWidth) + b |= encodeRanks(memAttribs.RanksPerPackage) + + 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 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 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 encodeTAAMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TAAMinPs) +} + +func encodeTAAMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TAAMinPs) +} + +func encodeTRCDMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TRCDMinPs) +} + +func encodeTRCDMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TRCDMinPs) +} + +func encodeTRPMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TRPMinPs) +} + +func encodeTRCMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TRCMinPs) +} + +func encodeTRPMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TRPMinPs) +} + +func encodeTRASRCMinMSNs(memAttribs *memAttributes) byte { + var b byte + + b = byte((convPsToMtb(memAttribs.TRASMinPs) >> 4) & 0xf0) + b |= byte((convPsToMtb(memAttribs.TRCMinPs) >> 8) & 0x0f) + + return b +} + +func encodeTRASMinLsb(memAttribs *memAttributes) byte { + return byte(convPsToMtb(memAttribs.TRASMinPs) & 0xff) +} + +func encodeTRCMinLsb(memAttribs *memAttributes) byte { + return byte(convPsToMtb(memAttribs.TRCMinPs) & 0xff) +} + + +/* + * Per Table 68 of Jedec spec 4.1.1.L-5R29 v103, + * tRRD_S is based on : + * Speed Bin (not including sub-category) + * Page Size specified in 512KB block count: + * 1 = 1/2 KB page size + * 2 = 1 KB page size + * 4 = 2 KB page size + */ + +func updateTRRDSPs(memAttribs *memAttributes) int { + var pS int + + switch speedBinMinorToMajor[memAttribs.SpeedBin] { + case SpeedBin1600: + switch memAttribs.PageSize { + case 1: + pS = 5000 + case 2: + pS = 5000 + case 4: + pS = 6000 + } + case SpeedBin1866: + switch memAttribs.PageSize { + case 1: + pS = 4200 + case 2: + pS = 4200 + case 4: + pS = 5300 + } + case SpeedBin2133: + switch memAttribs.PageSize { + case 1: + pS = 3700 + case 2: + pS = 3700 + case 4: + pS = 5300 + } + case SpeedBin2400: + switch memAttribs.PageSize { + case 1: + pS = 3300 + case 2: + pS = 3300 + case 4: + pS = 5300 + } + case SpeedBin2666: + switch memAttribs.PageSize { + case 1: + pS = 3000 + case 2: + pS = 3000 + case 4: + pS = 5300 + } + case SpeedBin2933: + switch memAttribs.PageSize { + case 1: + pS = 2700 + case 2: + pS = 2700 + case 4: + pS = 5300 + } + case SpeedBin3200: + switch memAttribs.PageSize { + case 1: + pS = 2500 + case 2: + pS = 2500 + case 4: + pS = 5300 + } + /* FIXME - Table also has 3DS settings, but > DDR4-2400-3DS is TBD */ + } + + return pS +} + +/* + * Per Table 70 of Jedec spec 4.1.1.L-5R29 v103, + * tRRD_L is based on : + * Speed Bin (not including sub-category) and + * Page Size specified in 512KB block count: + * 1 = 1/2 KB page size + * 2 = 1 KB page size + * 4 = 2 KB page size + */ +func getTRRDLPs(memAttribs *memAttributes) int { + var pS int + + switch speedBinMinorToMajor[memAttribs.SpeedBin] { + case SpeedBin1600: + switch memAttribs.PageSize { + case 1: + pS = 6000 + case 2: + pS = 6000 + case 4: + pS = 7500 + } + case SpeedBin1866: + switch memAttribs.PageSize { + case 1: + pS = 5300 + case 2: + pS = 5300 + case 4: + pS = 6400 + } + + case SpeedBin2133: + switch memAttribs.PageSize { + case 1: + pS = 5300 + case 2: + pS = 5300 + case 4: + pS = 6400 + } + case SpeedBin2400: + switch memAttribs.PageSize { + case 1: + pS = 4900 + case 2: + pS = 4900 + case 4: + pS = 6400 + } + case SpeedBin2666: + switch memAttribs.PageSize { + case 1: + pS = 4900 + case 2: + pS = 4900 + case 4: + pS = 6400 + } + case SpeedBin2933: + switch memAttribs.PageSize { + case 1: + pS = 4900 + case 2: + pS = 4900 + case 4: + pS = 6400 + } + case SpeedBin3200: + switch memAttribs.PageSize { + case 1: + pS = 4900 + case 2: + pS = 4900 + case 4: + pS = 6400 + } + /* FIXME - Table also has 3DS settings, but > DDR4-2400-3DS is TBD */ + } + + return pS +} + + +/* + * Per Table 72 of Jedec spec 4.1.1.L-5R29 v103, + * tCCD_L is based on : + * Speed Bin (not including sub-category) + */ +func getTCCDLPs(memAttribs *memAttributes) int { + var pS int + + switch speedBinMinorToMajor[memAttribs.SpeedBin] { + case SpeedBin1600: + pS = 6250 + case SpeedBin1866: + pS = 5355 + case SpeedBin2133: + pS = 5355 + default: + pS = 5000 + /* FIXME - Table also has 3DS settings, but > DDR4-2400-3DS is TBD */ + } + + return pS +} + + +/* + * Per Table 66 of Jedec spec 4.1.1.L-5R29 v103, + * FAW timing is based on : + * Speed Bin (not including sub-category) and + * Page Size specified in 512KB block count: + * 1 = 1/2 KB page size + * 2 = 1 KB page size + * 4 = 2 KB page size + */ + +func getTFAWPs(memAttribs *memAttributes) int { + var pS int + + switch speedBinMinorToMajor[memAttribs.SpeedBin] { + case SpeedBin1600: + switch memAttribs.PageSize { + case 1: + pS = 20000 + case 2: + pS = 25000 + case 4: + pS = 35000 + } + case SpeedBin1866: + switch memAttribs.PageSize { + case 1: + pS = 17000 + case 2: + pS = 23000 + case 4: + pS = 30000 + } + case SpeedBin2133: + switch memAttribs.PageSize { + case 1: + pS = 15000 + case 2: + pS = 21000 + case 4: + pS = 30000 + } + case SpeedBin2400: + switch memAttribs.PageSize { + case 1: + pS = 13000 + case 2: + pS = 21000 + case 4: + pS = 30000 + } + case SpeedBin2666: + switch memAttribs.PageSize { + case 1: + pS = 12000 + case 2: + pS = 21000 + case 4: + pS = 30000 + } + case SpeedBin2933: + switch memAttribs.PageSize { + case 1: + pS = 10875 + case 2: + pS = 21000 + case 4: + pS = 30000 + } + case SpeedBin3200: + switch memAttribs.PageSize { + case 1: + pS = 10000 + case 2: + pS = 21000 + case 4: + pS = 30000 + } + /* FIXME - Table also has 3DS settings, but > DDR4-2400-3DS, x8 is tbd */ + } + + return pS +} + + +/* Update settings based on data sheet (json) supplied memory attributes */ +func encodeTRFC1MinLsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(tRFC1Encoding[memAttribs.CapacityPerDieGb]) + + return byte(mtb & 0xff) +} + +func encodeTRFC1MinMsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(tRFC1Encoding[memAttribs.CapacityPerDieGb]) + + return byte((mtb >> 8) & 0xff) +} + +func encodeTRFC2MinLsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(tRFC2Encoding[memAttribs.CapacityPerDieGb]) + + return byte(mtb & 0xff) +} + +func encodeTRFC2MinMsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(tRFC2Encoding[memAttribs.CapacityPerDieGb]) + + return byte((mtb >> 8) & 0xff) +} + +func encodeTRFC4MinLsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(tRFC4Encoding[memAttribs.CapacityPerDieGb]) + + return byte(mtb & 0xff) +} + +func encodeTRFC4MinMsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(tRFC4Encoding[memAttribs.CapacityPerDieGb]) + + return byte((mtb >> 8) & 0xff) +} + +func encodeTFAWMinMSN(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(getTFAWPs(memAttribs)) + + return byte((mtb >> 8) & 0x0f) +} + +func encodeTFAWMinLsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(getTFAWPs(memAttribs)) + + return byte(mtb & 0xff) +} + +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 encodeCASFourthByte(memAttribs *memAttributes) byte { + return memAttribs.CASFourthByte +} + +func encodeTRRDSMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TRRDSMinPs) +} + +func encodeTRRDSMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TRRDSMinPs) +} + +func encodeTRRDLMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TRRDLMinPs) +} + +func encodeTRRDLMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TRRDLMinPs) +} + +func encodeTCCDLMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TCCDLMinPs) +} + +func encodeTCCDLMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TCCDLMinPs) +} + +func encodeTWRMinMSN(memAttribs *memAttributes) byte { + return byte((convPsToMtb(TimingValueTWRMinPs) >> 8) & 0x0f) +} + +func encodeTWRMinLsb(memAttribs *memAttributes) byte { + return byte(convPsToMtb(TimingValueTWRMinPs) & 0xff) +} + +func encodeTWTRMinMSNs(memAttribs *memAttributes) byte { + var b byte + + b = byte((convPsToMtb(memAttribs.TWTRLMinPs) >> 4) & 0xf0) + b |= byte((convPsToMtb(memAttribs.TWTRSMinPs) >> 8) & 0x0f) + + return b +} + +func encodeTWTRSMinLsb(memAttribs *memAttributes) byte { + return byte(convPsToMtb(memAttribs.TWTRSMinPs) & 0xff) +} + +func encodeTWTRLMinLsb(memAttribs *memAttributes) byte { + return byte(convPsToMtb(memAttribs.TWTRLMinPs) & 0xff) +} + +type SPDMemAttribFunc func (*memAttributes) byte +type SPDConvConstFunc func () byte + +type SPDAttribTableEntry struct { + constVal byte + getVal SPDMemAttribFunc +} + +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 + SPDIndexTRCDMin = 25 + SPDIndexTRPMin = 26 + SPDIndexTRASRCMinMSNs = 27 + SPDIndexTRASMinLsb = 28 + SPDIndexTRCMinLsb = 29 + SPDIndexTRFC1MinLsb = 30 + SPDIndexTRFC1MinMsb = 31 + SPDIndexTRFC2MinLsb = 32 + SPDIndexTRFC2MinMsb = 33 + SPDIndexTRFC4MinLsb = 34 + SPDIndexTRFC4MinMsb = 35 + SPDIndexTFAWMinMSN = 36 + SPDIndexTFAWMinLsb = 37 + SPDIndexTRRDSMin = 38 + SPDIndexTRRDLMin = 39 + SPDIndexTCCDLMin = 40 + SPDIndexTWRMinMSN = 41 + SPDIndexTWRMinLsb = 42 + SPDIndexTWTRMinMSNs = 43 + SPDIndexWTRSMinLsb = 44 + SPDIndexWTRLMinLsb = 45 + SPDIndexTCCDLMinFineOffset = 117 + SPDIndexTRRDLMinFineOffset = 118 + SPDIndexTRRDSMinFineOffset = 119 + SPDIndexTRCMinFineOffset = 120 + SPDIndexTRPMinFineOffset = 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 DDR4. + */ + SPDValueSize = 0x23 + + /* + * From JEDEC spec: Revision 1.1 + * Set to 0x11. + */ + SPDValueRevision = 0x11 + + /* DDR4 memory type = 0x0C */ + SPDValueMemoryType = 0x0C + + /* + * From JEDEC spec: + * Module Type [0:3] : + * 0 = Undefined + * 1 = RDIMM (width = 133.35 mm nom) + * 2 = UDIMM (width = 133.35 mm nom) + * 3 = SO-DIMM (width = 68.60 mm nom) + * 4 = LRDIMM (width = 133.35 mm nom) + * + * DDR4 on TGL uses SO-DIMM type for for both memory down and DIMM config. + * Set to 0x03. + */ + SPDValueModuleType = 0x03 + + /* + * 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: + * 2:0 Primary Bus Width in Bits = 011 (x64 always) + * Set to 0x03. + */ + SPDValueModuleBusWidth = 0x03 + + /* + * 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 + + /* As per JEDEC spec, unused digits of manufacturer part number are left as blank. */ + SPDValueManufacturerPartNumberBlank = 0x20 + +) + +const ( + /* + * As per Table 75 of Jedec spec 4.1.20-L-5 R29 v103: + * tWRMin = 15nS for all DDR4 Speed Bins + * Set to 15000 pS + */ + TimingValueTWRMinPs = 15000 + + /* + * As per Table 78 of Jedec spec 4.1.20-L-5 R29 v103: + * tWTR_SMin = 2.5nS for all DDR4 Speed Bins + * Set to 2500 pS + */ + TimingValueTWTRSMinPs = 2500 + + /* + * As per Table 80 of Jedec spec 4.1.20-L-5 R29 v103: + * tWTR_LMin = 7.5 nS for all DDR4 Speed Bins + * Set to 7500 pS + */ + TimingValueTWTRLMinPs = 7500 +) + +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: { constVal: SPDValueModuleBusWidth }, + SPDIndexTimebases: { constVal: SPDValueTimebases }, + SPDIndexTCKMin: { getVal: encodeTCKMin }, + SPDIndexTCKMinFineOffset: { getVal: encodeTCKMinFineOffset }, + SPDIndexTCKMax: { getVal: encodeTCKMax }, + SPDIndexTCKMaxFineOffset: { getVal: encodeTCKMaxFineOffset }, + SPDIndexCASFirstByte: { getVal: encodeCASFirstByte }, + SPDIndexCASSecondByte: { getVal: encodeCASSecondByte }, + SPDIndexCASThirdByte: { getVal: encodeCASThirdByte }, + SPDIndexCASFourthByte: { getVal: encodeCASFourthByte }, + SPDIndexTAAMin: { getVal: encodeTAAMin }, + SPDIndexTAAMinFineOffset: { getVal: encodeTAAMinFineOffset }, + SPDIndexTRCDMin: { getVal: encodeTRCDMin }, + SPDIndexTRCDMinFineOffset: { getVal: encodeTRCDMinFineOffset }, + SPDIndexTRPMin: { getVal: encodeTRPMin }, + SPDIndexTRPMinFineOffset: { getVal: encodeTRPMinFineOffset }, + SPDIndexTRASRCMinMSNs: { getVal: encodeTRASRCMinMSNs }, + SPDIndexTRASMinLsb: { getVal: encodeTRASMinLsb }, + SPDIndexTRCMinLsb: { getVal: encodeTRCMinLsb }, + SPDIndexTRCMinFineOffset: { getVal: encodeTRCMinFineOffset }, + SPDIndexTRFC1MinLsb: { getVal: encodeTRFC1MinLsb }, + SPDIndexTRFC1MinMsb: { getVal: encodeTRFC1MinMsb }, + SPDIndexTRFC2MinLsb: { getVal: encodeTRFC2MinLsb }, + SPDIndexTRFC2MinMsb: { getVal: encodeTRFC2MinMsb }, + SPDIndexTRFC4MinLsb: { getVal: encodeTRFC4MinLsb }, + SPDIndexTRFC4MinMsb: { getVal: encodeTRFC4MinMsb }, + SPDIndexTFAWMinMSN: { getVal: encodeTFAWMinMSN }, + SPDIndexTFAWMinLsb: { getVal: encodeTFAWMinLsb }, + SPDIndexTRRDSMin: { getVal: encodeTRRDSMin }, + SPDIndexTRRDSMinFineOffset: { getVal: encodeTRRDSMinFineOffset }, + SPDIndexTRRDLMin: { getVal: encodeTRRDLMin }, + SPDIndexTRRDLMinFineOffset: { getVal: encodeTRRDLMinFineOffset }, + SPDIndexTCCDLMin: { getVal: encodeTCCDLMin }, + SPDIndexTCCDLMinFineOffset: { getVal: encodeTCCDLMinFineOffset }, + SPDIndexTWRMinMSN: { getVal: encodeTWRMinMSN }, + SPDIndexTWRMinLsb: { getVal: encodeTWRMinLsb }, + SPDIndexTWTRMinMSNs: { getVal: encodeTWTRMinMSNs }, + SPDIndexWTRSMinLsb: { getVal: encodeTWTRSMinLsb }, + SPDIndexWTRLMinLsb: { getVal: encodeTWTRLMinLsb }, +} + +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 validateSpeedBin(speedBin string) error { + if _, ok := speedBinToSPDEncoding[speedBin]; ok == false { + return fmt.Errorf("Incorrect speed bin: DDR4-", speedBin) + } + return nil +} + +func validateBankGroups(bankGroups int) error { + if bankGroups != 0 && bankGroups != 2 && bankGroups != 4 { + return fmt.Errorf("Incorrect bank groups: ", bankGroups) + } + return nil +} + +func validateBanksPerGroup(banksPerGroup int) error { + if banksPerGroup != 4 && banksPerGroup != 8 { + return fmt.Errorf("Incorrect banks per group: ", banksPerGroup) + } + return nil +} + +func validateCapacityPerDie(capacityPerDieGb int) error { + switch capacityPerDieGb { + case 1: + return nil + case 2: + return nil + case 4: + return nil + case 8: + return nil + case 16: + return nil + case 32: + return nil + } + return fmt.Errorf("Incorrect capacity per die: ", capacityPerDieGb) +} + +func validatePageSize(pageSize int) error { + if pageSize != 1 && pageSize != 2 && pageSize != 4 { + return fmt.Errorf("Incorrect page size: ", pageSize) + } + return nil +} + +func validateDiesPerPackage(dieCount int) error { + if dieCount >= 1 && dieCount <= 8 { + return nil + } + return fmt.Errorf("Incorrect dies per package count: ", dieCount) +} + +func validateDeviceBusWidth(width int) error { + if width != 8 && width != 16 { + return fmt.Errorf("Incorrect device bus width: ", width) + } + return nil +} + +func validateSignalLoading(loading string) error { + if loading != "not specified" && loading != "single" && loading != "multi" { + return fmt.Errorf("Incorrect signal loading: ", loading) + } + return nil +} + +func validateRanksPerPackage(ranks int) error { + if ranks >= 1 && ranks <= 4 { + return nil + } + return fmt.Errorf("Incorrect package ranks: ", ranks) +} + +/* +1) validate memory parts +2) remove any fields that Intel does not care about +*/ + +func validateMemoryParts(memParts *memParts) error { + for i := 0; i < len(memParts.MemParts); i++ { + if err := validateSpeedBin(memParts.MemParts[i].Attribs.SpeedBin); err != nil { + return err + } + if err := validateBankGroups(memParts.MemParts[i].Attribs.BankGroups); err != nil { + return err + } + if err := validateBanksPerGroup(memParts.MemParts[i].Attribs.BanksPerGroup); err != nil { + return err + } + if err := validateCapacityPerDie(memParts.MemParts[i].Attribs.CapacityPerDieGb); err != nil { + return err + } + if err := validatePageSize(memParts.MemParts[i].Attribs.PageSize); err != nil { + return err + } + if err := validateDiesPerPackage(memParts.MemParts[i].Attribs.DiesPerPackage); err != nil { + return err + } + if err := validateDeviceBusWidth(memParts.MemParts[i].Attribs.DeviceBusWidth); err != nil { + return err + } + if err := validateSignalLoading(memParts.MemParts[i].Attribs.SignalLoading); err != nil { + return err + } + if err := validateRanksPerPackage(memParts.MemParts[i].Attribs.RanksPerPackage); err != nil { + return err + } + } + return nil +} + +const ( + /* First Byte */ + CAS9 = 1 << 2 + CAS10 = 1 << 3 + CAS11 = 1 << 4 + CAS12 = 1 << 5 + CAS13 = 1 << 6 + CAS14 = 1 << 7 + /* Second Byte */ + CAS15 = 1 << 0 + CAS16 = 1 << 1 + CAS17 = 1 << 2 + CAS18 = 1 << 3 + CAS19 = 1 << 4 + CAS20 = 1 << 5 + CAS21 = 1 << 6 + CAS22 = 1 << 7 + /* Third Byte */ + CAS24 = 1 << 1 +) + +func encodeLatencies(latency int, memAttribs *memAttributes) error { + switch latency { + case 9: + memAttribs.CASFirstByte |= CAS9 + case 10: + memAttribs.CASFirstByte |= CAS10 + case 11: + memAttribs.CASFirstByte |= CAS11 + case 12: + memAttribs.CASFirstByte |= CAS12 + case 13: + memAttribs.CASFirstByte |= CAS13 + case 14: + memAttribs.CASFirstByte |= CAS14 + case 15: + memAttribs.CASSecondByte |= CAS15 + case 16: + memAttribs.CASSecondByte |= CAS16 + case 17: + memAttribs.CASSecondByte |= CAS17 + case 18: + memAttribs.CASSecondByte |= CAS18 + case 19: + memAttribs.CASSecondByte |= CAS19 + case 20: + memAttribs.CASSecondByte |= CAS20 + case 21: + memAttribs.CASSecondByte |= CAS21 + case 22: + memAttribs.CASSecondByte |= CAS22 + case 24: + memAttribs.CASSecondByte |= CAS24 + default: + fmt.Errorf("Incorrect CAS Latency: ", latency) + } + + return nil +} + +func getCASLatencies(memAttribs *memAttributes) string { + return speedBinToSPDEncoding[memAttribs.SpeedBin].CASLatencies +} + +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 updateTAAMin(memAttribs *memAttributes) error { + if memAttribs.TAAMinPs == 0 { + memAttribs.TAAMinPs = speedBinToSPDEncoding[memAttribs.SpeedBin].TAAMinPs + } + + return nil +} + +func updateTRCDMin(memAttribs *memAttributes) error { + if memAttribs.TRCDMinPs == 0 { + memAttribs.TRCDMinPs = speedBinToSPDEncoding[memAttribs.SpeedBin].TRCDMinPs + } + + return nil +} + +func updateTRPMin(memAttribs *memAttributes) error { + if memAttribs.TRPMinPs == 0 { + memAttribs.TRPMinPs = speedBinToSPDEncoding[memAttribs.SpeedBin].TRPMinPs + } + + return nil +} + +func updateTRASMin(memAttribs *memAttributes) error { + if memAttribs.TRASMinPs == 0 { + memAttribs.TRASMinPs = speedBinToSPDEncoding[memAttribs.SpeedBin].TRASMinPs + } + + return nil +} + +func updateTRCMin(memAttribs *memAttributes) error { + if memAttribs.TRCMinPs == 0 { + memAttribs.TRCMinPs = speedBinToSPDEncoding[memAttribs.SpeedBin].TRCMinPs + } + + return nil +} + +func updateTCK(memAttribs *memAttributes) error { + if memAttribs.TCKMinPs == 0 { + memAttribs.TCKMinPs = speedBinToSPDEncoding[memAttribs.SpeedBin].TCKMinPs + } + if memAttribs.TCKMaxPs == 0 { + memAttribs.TCKMaxPs = speedBinToSPDEncoding[memAttribs.SpeedBin].TCKMaxPs + } + + return nil +} + +func updateTWRMin(memAttribs *memAttributes) error { + if memAttribs.TWRMinPs == 0 { + memAttribs.TWRMinPs = TimingValueTWRMinPs + } + + return nil +} + +func updateTWTRMin(memAttribs *memAttributes) error { + if memAttribs.TWTRLMinPs == 0 { + memAttribs.TWTRLMinPs = TimingValueTWTRLMinPs + } + if memAttribs.TWTRSMinPs == 0 { + memAttribs.TWTRSMinPs = TimingValueTWTRSMinPs + } + + return nil +} + +func updateSpeedBinAttributes(memAttribs *memAttributes) error { + updateTAAMin(memAttribs) + updateTRCDMin(memAttribs) + updateTRPMin(memAttribs) + updateTRASMin(memAttribs) + updateTRCMin(memAttribs) + updateTCK(memAttribs) + updateTWRMin(memAttribs) + updateTWTRMin(memAttribs) + updateCAS(memAttribs) + + return nil +} + +func updateMemoryAttributes(memAttribs *memAttributes) error { + /* Update Primary attributes from JSON file for each part */ + /* Update settings based on Speed Bin */ + if err := updateSpeedBinAttributes(memAttribs); err != nil { + return err + } + + 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) + } +} diff --git a/util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt b/util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt new file mode 100644 index 0000000..0f2009b --- /dev/null +++ b/util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt @@ -0,0 +1,18 @@ +{ + "parts": [ + { + "name": "H5ANAG6NCMR-XN", + "attribs": { + "speedBin": "3200AA", + "bankGroups": 4, + "banksPerGroup": 4, + "capacityPerDieGb": 8, + "pageSize": 2, + "diesPerPackage": 2, + "deviceBusWidth": 16, + "signalLoading": "multi", + "ranksPerPackage": 1 + } + }, + ] +}
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
Patch Set 1:
This change is ready for review.
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
Patch Set 3:
This change is ready for review.
Hello build bot (Jenkins), Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#4).
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
util: Add spd_tools to generate SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 2,313 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/4
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
Patch Set 3: Code-Review-1
This will be gone over at least once more to remove any SPD fields that intel MRC does not care about before it is ready for merge.
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#5).
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
util: Add spd_tools to generate SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 2,302 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/5
Rob Barnes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
Patch Set 5:
(3 comments)
This change is ready for review.
https://review.coreboot.org/c/coreboot/+/44429/4/util/spd_tools/intel/ddr4/g... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/4/util/spd_tools/intel/ddr4/g... PS4, Line 7: "bankGroups": 4, Should be 2 banks for 512Mb x 16.
https://review.coreboot.org/c/coreboot/+/44429/4/util/spd_tools/intel/ddr4/g... PS4, Line 24: "pageSize": 4, Some data sheets state "Page size = 2COLBITS × ORG/8". Can we derive page size this way?
https://review.coreboot.org/c/coreboot/+/44429/4/util/spd_tools/intel/ddr4/g... PS4, Line 38: "pageSize": 2, Page size should be 2KB (4 512B). Perhaps the format for this attribute should be 512B, 1KB or 2KB.
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
Patch Set 12:
(41 comments)
This change is ready for review.
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... File util/spd_tools/intel/ddr4/README.md:
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 51: `name`:
Name is not really under `attribs`. It is already captured on line 37 above.
Done
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 54: `"1600J", "1600K", "1600L", "1866L", "1866M", "1866N", "2133N", "2133P", : "2133R", "2400P", "2400R", "2400T", "2400U", "2666T", "2666U", "2666V", : "2666W", "2933V", "2933W", "2933Y", "2933AA", "3200W", "3200AA", "3200AC"`
Based on the values here, it looks like two things are being combined: […]
There are multiple traits that differ based on what you are calling "Min CL supported", including tAAmin, tRCDmin, tRPmin, tRASmin, tRCmin, tCKmin, tCKmax, and CASLatencies. Without this Speed Bin categorization that they use in the Speed Bin tables, how would the other values be determined?
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 59: `0, 2, 4` bank groups.
Doesn't DDR4 support only 2/4 bank groups? (Reference: Section 3. […]
It supports 0 bank groups.
Section 8.1.5 of JEDEC spec 4.1.2.L-5 R29 has 00 = 0 (no bank groups), 01 = 1 (2 bank groups), 10 = 2 (4 bank groups), and 11 = (reserved) as options for SPD byte 4.
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 62: `4, 8` banks per group.
Doesn't DDR4 support only 4 banks per group? (Reference: Section 3. […]
Section 8.1.5 of JEDEC spec 4.1.2.L-5 R29 has 00 = (4 banks), 01 = (8 banks), all others reserved as options for SPD byte 4.
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 65: 32
Is 32Gb really supported per die for DDR4?
Section 8.1.5 of JEDEC spec 4.1.2.L-5 R29 states that DDR4 SPD byte 4 supports options for 256 Mb all the way to 32 Gb.
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 65: 1,
Isn't the minimum capacity per die for DDR4 is 2Gb?
See above comment.
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 67: `pageSize`
I think this can be determined based on the deviceBusWidth i.e. […]
Excellent tip, I'll implement it.
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 73: 1, 2, 3, 4, 5, 6, 7, 8`
Doesn't DDR4 support only single or dual dies per package?
Section 8.1.7 of JEDEC spec 4.1.2.L-5 R29 has a setting for anywhere from a single die to 8 die.
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 75: Number of bits of the device's address bus.
Isn't this the column width / DQ width? And the valid values would be 4, 8 and 16?
Is device bus width not the same as DQ width? If not, what is the term that should be used for this attribute?
We won't be supporting 4-bit (would have to be a 4-tall stack on Volteer, we'll only support a 2-tall stack). The code currently only supports x8 and x16 as options, I will update this readme to match.
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 78: signalLoading`: Refers to loading on signals at the SDRAM balls. Loading on : certain signals (CKE, ODT, etc.) per specification of device stacking as : defined in JESD79-4CNumber of bits of the device's address bus. Valid values: : `"not specified", "single", "multi"`
My understanding is that DDR4 supports only single and dual die packages. […]
Will we support 3DS? If not, then you are correct, single die could only map to "not specified". so we could determine this based on die count.
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 89: `1, 2, 3, 4` package ranks.
Isn't only 1 and 2 supported here?
Section 8.1.13 of JEDEC spec 4.1.2.L-5 R29 has a setting for anywhere from 1 package ranks to 8 package ranks. My comment on line 83 states that rev 23 supported 4 package ranks, but I see in the newer R29 spec that it was updated to support 8 package ranks.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 31: PlatformJSL = 1
This is not required.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 91: 1: 0x2,
I don't think DDR4 supports this.
According to Table 18 in section 8.1.5 of the JESD 4.1.2.L-5 R29 spec, it supports 256Mb, 512Mb, and 1GB capacity per die, but I didn't include support for 256Mb or the 512Mb parts. Should I also not support or allow 1 Gb parts?
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 96: 32: 0x7,
This is not supported by DDR4.
Section 8.1.5 in Jedec Spec 4.1.2.L-5 R29 shows a "32Gb" option for "Total SDRAM capacity per die". Should I not allow a 32 Gb option?
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 101: density per physical channel
density per die?
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 104: Channel
die?
made it "DieCapacity"
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 141: const ( : /* SDRAM Configuration Types */ : SDRAMConfig256Mbx8 = 0 : SDRAMConfig512Mbx8 = 1 : SDRAMConfig1Gbx8 = 2 : SDRAMConfig2Gbx8 = 3 : SDRAMConfig128Mbx16 = 4 : SDRAMConfig256Mbx16 = 5 : SDRAMConfig512Mbx16 = 6 : SDRAMConfig1Gbx16 = 7 : )
Not used anywhere. I don't think this is required.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 154: /* SPEED Bin Grades */
+1. Most of the datasheets I read did not explicitly state the speed grade sub category. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 223: memAttributes
Rather than using memAttributes, I think we can use a structure with only the fields that have to be […]
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 225: TAAMinPs: 12500,
Do we really need to store this in the table? I think this can be calculated based on two things: […]
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 226: TRCDMinPs: 12500,
TRcd is the same as Taa for all combinations. Again, I don't think we need to store this separately.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 227: TRPMinPs: 12500,
Same for Trp as well. It is the same as Taa.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 229: TRCMinPs
Trc is just the sum of Taa and TRAS. So, it does not need to be stored separately.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 230: TCKMinPs
TckMin is calculated using speed bin. i.e. 2/speed.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 468: 8: 1 << 4,
DDR4 supports 4 banks only. This table is not really required.
JEDEC spec 4.1.2.L-5 R29, section 8.1.5 shows SPD options for [5:4] 00 (4 banks) and [5:4] 01 (8 banks)
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 472: 0: 0 << 6,
DDR4 does not support this.
JEDEC spec 4.1.2.L-5 R29, section 8.1.5 shows SPD options for bank group bits [7:6] : 00 (no bank groups), 01 (2 bank groups), 10 (4 bank groups)
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 490: densityGbx8x16ChannelToRowColumnEncoding
What about x4?
We do not support x4 as it would require too many pieces of ddr4.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 495: encodePackage
encodePackageType?
encodePackageType() is the one that encodes the entire SPD byte and is defined below. This function only encodes what the 4.1.2.L-5 R29 spec calls bit 7, "Primary SDRAM Package Type", but since they named the bit the same as the entire byte, I shorted the bit name in this case and used encodePackage().
Do you have a better suggestion for a name?
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 518: var signalLoadingEncode = map[string]byte { : "not specified": 0, : "single": 1, : "multi": 2, : } :
This is not required. If die count is 1, then "not specified", else "multi".
Now that decision has been made to not support 3DS< that is true. I removed SignalLoading required json parameters.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 533: encodePackage
This is called here as well as in encodeDiesPerPackage.
Removed encodeDiesPerPackage().
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 539: (bitWidthPerDevice / 8)
This is not really correct. For 32, it is 3 and not 4. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 649: Per Table 68 of Jedec spec 4.1.1.L-5R29 v103,
I think that is just an example. We need to be looking at Table 169, 170 in JESD79-4c. […]
I will update this. Leaving this comment unresolved until I do.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 725: 3DS
Isn't 3DS used only in soldered DIMM and not for memory down?
We will not support 3DS.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 732: Per Table 70 of Jedec spec 4.1.1.L-5R29 v103,
Same as above.
I will update this. Leaving this comment unresolved until I do.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1165: TGL
What about other platforms?
First version of this tool only supports TGL. Once format of tool is approved and initial version of tool merged, additional platforms could be added.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1374: bankGroups != 0
This is not correct.
The Jedec DDR4 SPD Spec 4.1.2.L-5 R29, section 8.1.5 has a bit setting option for bits 7:6 that includes a setting option for "no bank groups". Should I not allow support or allow "no bank groups"?
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1381: && banksPerGroup != 8
This is not correct.
The Jedec DDR4 SPD Spec 4.1.2.L-5 R29, section 8.1.5 has a bit setting option for bits 5:3 that include "00 = 4 banks, 01 = 8 banks, all others reserved". Should I not support or allow 8 banks per group?
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1388: switch capacityPerDieGb {
Instead of switch: […]
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1413: dieCount <= 8
I don't think there can be more than 2 dies.
The SPD spec options support up to 8. Should I limit support of this tool to 2 die max?
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1420: width != 8
I think 4 is valid too?
Yes, x4 is valid, but they would have to stack too many DDR4 parts to use x4 parts (16 DDR4 parts soldered down), so the tool doesn't support it as an option. Should it?
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1434: ranks <= 4
Isn't this limited to 2?
Section 8.1.13 of SPD spec shows options in bits 5:3 that support from 1 to 8 package ranks, inclusive. Originally, I was thinking that max ranks per package seems to be 2 (from the DDR4 part spec sheets I've seen), but if they were stacked 2-high, I was thinking we could get 4. But thinking about it more, they would need to connect the ranks for the stacked parts such that the two stacked parts shared the same 2 ranks, so I think you are correct that we would likely not see ranks > 2.
I reduced upper bound to ranks <= 2.
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
Patch Set 15:
(10 comments)
This change is ready for review.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 96: 32: 0x7,
Same comment as above.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 468: 8: 1 << 4,
From JESD79-4C: "The DDR4 SDRAM is a high-speed dynamic random-access memory internally configured a […]
That means that the settings for the H5ANAG6NCMR-XN part (a x16 part) is incorrect in the global json file as it's listed with 4 bank groups and 4 banks per group with deviceBusWidth of 16.
If that is true, doesn't that mean that all x4/x8 parts have one bankGroups/banksPerGroup setting and all x16 parts have a second bankGroups/banksPerGroup, then we don't need to specify banks or bank groups as part of the json, we can determine that based on deviceBusWidth?
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 472: 0: 0 << 6,
Same as above.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 490: densityGbx8x16ChannelToRowColumnEncoding
Is that for TGL? I think its fine if we don't for now. But it should be documented. […]
Currently, validateDeviceBusWidth() only allows x8 and x16 as options, otherwise it returns error "Incorrect device bus width: 4"
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 495: encodePackage
encodePackageDeviceType?
Thanks. Done.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 649: Per Table 68 of Jedec spec 4.1.1.L-5R29 v103,
I will update this. Leaving this comment unresolved until I do.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 732: Per Table 70 of Jedec spec 4.1.1.L-5R29 v103,
I will update this. Leaving this comment unresolved until I do.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1374: bankGroups != 0
See comment above about banks and bank groups.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1381: && banksPerGroup != 8
Same as above.
Since it can only be 4, I've removed BanksPerGroup as a json parameter.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1413: dieCount <= 8
From JESD79-4C, it doesn't look like more than 2 dies are supported?
Done
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
Patch Set 15:
(9 comments)
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... File util/spd_tools/intel/ddr4/README.md:
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 54: `"1600J", "1600K", "1600L", "1866L", "1866M", "1866N", "2133N", "2133P", : "2133R", "2400P", "2400R", "2400T", "2400U", "2666T", "2666U", "2666V", : "2666W", "2933V", "2933W", "2933Y", "2933AA", "3200W", "3200AA", "3200AC"`
There are multiple traits that differ based on what you are calling "Min CL supported", including tA […]
Done
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 59: `0, 2, 4` bank groups.
It supports 0 bank groups. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 62: `4, 8` banks per group.
Section 8.1.5 of JEDEC spec 4.1.2. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 65: 32
Section 8.1.5 of JEDEC spec 4.1.2. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 65: 1,
See above comment.
Done
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 73: 1, 2, 3, 4, 5, 6, 7, 8`
Section 8.1.7 of JEDEC spec 4.1.2.L-5 R29 has a setting for anywhere from a single die to 8 die.
Done
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 75: Number of bits of the device's address bus.
Is device bus width not the same as DQ width? If not, what is the term that should be used for this […]
Done
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 78: signalLoading`: Refers to loading on signals at the SDRAM balls. Loading on : certain signals (CKE, ODT, etc.) per specification of device stacking as : defined in JESD79-4CNumber of bits of the device's address bus. Valid values: : `"not specified", "single", "multi"`
Will we support 3DS? If not, then you are correct, single die could only map to "not specified". […]
Done
https://review.coreboot.org/c/coreboot/+/44429/9/util/spd_tools/intel/ddr4/R... PS9, Line 89: `1, 2, 3, 4` package ranks.
Section 8.1.13 of JEDEC spec 4.1.2. […]
Done
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#16).
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
util: Add spd_tools to generate SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,962 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/16
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
Patch Set 16:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 468: 8: 1 << 4,
That means that the settings for the H5ANAG6NCMR-XN part (a x16 part) is incorrect in the global json file as it's listed with 4 bank groups and 4 banks per group with deviceBusWidth of 16.
Actually, it is correct because that part is a DDP part and so each die has 2 bank groups. Thus, it has a total of 4 bank groups.
If that is true, doesn't that mean that all x4/x8 parts have one bankGroups/banksPerGroup setting and all x16 parts have a second bankGroups/banksPerGroup, then we don't need to specify banks or bank groups as part of the json, we can determine that based on deviceBusWidth?
Based on section 2.8 from JESD79-4C, these are the combinations I see:
x4 - always has 4 bank groups and 4 banks per group x8 - always has 4 bank groups and 4 banks per group x16 SDP - always has 2 bank groups and 4 banks per group x16 DDP - always has 4 bank groups and 4 banks per group
So, to answer your question, yes, based on deviceBusWidth and # of dies, it is possible to calculate bank groups. # banks per group stays constant always. Does that make sense?
Rob Barnes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
Patch Set 16:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/16/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/16/util/spd_tools/intel/ddr4/... PS16, Line 30: "speedMbps": 3200, Mbps or MTps?
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#17).
Change subject: util: Add spd_tools to generate SPDs for TGL boards ......................................................................
util: Add spd_tools to generate SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,979 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/17
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#18).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,979 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/18
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#19).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,979 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/19
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 19:
(2 comments)
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1420: width != 8
Sounds okay. Good to have that documented.
It was documented in the README in that DeviceBusWidth's only valid options are 8 and 16. I added a "NOTE:" at that location in the readme to spell out that x4 parts are not supported by this tool.
https://review.coreboot.org/c/coreboot/+/44429/16/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/16/util/spd_tools/intel/ddr4/... PS16, Line 30: "speedMbps": 3200,
Mbps or MTps?
Good catch.
Rob Barnes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 19:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... PS19, Line 12: "CASLatencies": "9 10 11 12 13 14 15 16 17 19 19 20" 19 is listed twice.
Rob Barnes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 19:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/README.md:
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... PS19, Line 82: picosecond units, accept for "CASLatencies", which would be represented as a except
Rob Barnes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 19:
(2 comments)
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... PS19, Line 1133: func getCASLatencies(memAttribs *memAttributes) string { I suggest adding a validator to check if the override casLatencies matches the default casLatencies so we don't accumulate unnecessary overrides.
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... PS19, Line 1149: "9 10 11 12 13 14 15 16 17 18 19 20", nit: adding a comment with the index or speed bin would be helpful here.
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 19:
(22 comments)
https://review.coreboot.org/c/coreboot/+/44429/17/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/README.md:
https://review.coreboot.org/c/coreboot/+/44429/17/util/spd_tools/intel/ddr4/... PS17, Line 41: Intel : MRC just say SoC since this will be used by more than just Intel.
https://review.coreboot.org/c/coreboot/+/44429/17/util/spd_tools/intel/ddr4/... PS17, Line 80: Do To?
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 100: 61 61 is only for RFC2
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 134: 2000000 This is 2000000 because it is basically 2 * 1000000 where 1000000 is to convert from milliseconds to picoseconds. It might be helpful to have a comment here.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 227: var loading byte : : /* : * If die count = 1, signal loading = "not specified" = 0 : * If die count > 1, signal loading = "multi" = 2 : */ : if dies == 1 { : loading = 0 : } else { : loading = 1 : } : : return loading nit: This can be moved in encodeSignalLoadingFromDieCount() since it doesn't really do anything else.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 348: tRCD is same as tAA for all combinations This is not right. You already ensure that TRCDMinPs is set to TAAMinPs if no value provided for TRCDMinPs in json file. Here, you should be using convPsToMtbByte(memAttribs.TRCDMinPs)
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 353: /* tRCD is same as tAA for all combinations */ Same as above.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 444: error This function is always returning nil. So, is a return type really required?
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 452: error same here
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 460: error same here.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 468: error same here.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 503: error Same here.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 513: 4284 I see a value of 4.2ns in Table 169 which would be 4200ps. Is 4284 in a different part of the document?
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 514: 4284 From table 169 in JESD79-4C, this is 3.7ns
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 539: error Same comment as above about not requiring any return value for the next two functions.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 1101: CASSecondByte CASThirdByte
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 1112: CL_nRCD_nRP - <first_CL_in_speed_series> + <total_enties_prior> Do we really need this? It just seems more complicated than required.
It would be much easier to read having cases for each CL_nRCD_nRP under each speed grade: ``` switch memAttribs.SpeedMTps { case 1600: switch memAttribs.CL_nRCD_nRP { case 10: return "9 10 11 12" case 11: return "9 11 12" case 12: return "10 12" } case 1866: .... ```
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 1137: "9 11 12", There is one extra entry here which will result in this function returning wrong values for all the entries henceforth.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 1188: error All these functions returning nil can simply drop the return type.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 12: 9 10 11 12 13 14 15 16 17 19 19 20 Reposting comment from patchset#11:
I don't think this is correct. From the speed bin table at the end of the datasheet, it looks like this part supports all the CAS Latencies as mentioned in the spec. Also, the initial SPD that you had checked in for the part https://review.coreboot.org/c/coreboot/+/44272/1/src/mainboard/google/voltee... shows that all CAS Latencies are supported.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 24: 10 11 12 13 14 15 16 17 19 19 20 21 22 Where are these values coming from? I think this part also supports all the standard latencies for 3200 (22-22-22)
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 36: 9 10 11 12 13 14 15 16 17 19 19 20 same here.
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#20).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,979 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/20
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#21).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,952 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/21
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 21:
(20 comments)
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/README.md:
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... PS19, Line 82: picosecond units, accept for "CASLatencies", which would be represented as a
except
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 100: 61
61 is only for RFC2
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 134: 2000000
This is 2000000 because it is basically 2 * 1000000 where 1000000 is to convert from milliseconds to […]
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 227: var loading byte : : /* : * If die count = 1, signal loading = "not specified" = 0 : * If die count > 1, signal loading = "multi" = 2 : */ : if dies == 1 { : loading = 0 : } else { : loading = 1 : } : : return loading
nit: This can be moved in encodeSignalLoadingFromDieCount() since it doesn't really do anything else […]
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 348: tRCD is same as tAA for all combinations
This is not right. […]
Agreed. It was left over from a prior implementation before I realized it should probably be overridable. Fixed.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 353: /* tRCD is same as tAA for all combinations */
Same as above.
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 444: error
This function is always returning nil. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 452: error
same here
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 460: error
same here.
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 468: error
same here.
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 503: error
Same here.
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 513: 4284
I see a value of 4.2ns in Table 169 which would be 4200ps. […]
tRRD_S(1K) = Max(4nCK,4.2ns), where CK=1.071, so max = 4 * 1.071 = 4.284ns
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 514: 4284
From table 169 in JESD79-4C, this is 3. […]
Thanks for the catch !! I was looking at the wrong table value on this, should not have been 4284. It should be Max(4nCK,3.7ns) = 4 * 0.937 = 3.748nS
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 539: error
Same comment as above about not requiring any return value for the next two functions.
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 1101: CASSecondByte
CASThirdByte
Great catch !
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 1112: CL_nRCD_nRP - <first_CL_in_speed_series> + <total_enties_prior>
Do we really need this? It just seems more complicated than required. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 1137: "9 11 12",
There is one extra entry here which will result in this function returning wrong values for all the […]
I went through entire table to comment it based on Rob's review request, found that and another issue in the table in doing so. I since abandoned the comments requested by Rob in lieu of the alternate approach of switches of switches, which no longer required the comments.
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 1188: error
All these functions returning nil can simply drop the return type.
Done
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... PS19, Line 1133: func getCASLatencies(memAttribs *memAttributes) string {
I suggest adding a validator to check if the override casLatencies matches the default casLatencies […]
Good suggestion.
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... PS19, Line 1149: "9 10 11 12 13 14 15 16 17 18 19 20",
nit: adding a comment with the index or speed bin would be helpful here.
Good suggestion. Done.
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#22).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,967 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/22
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 22:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... PS19, Line 1133: func getCASLatencies(memAttribs *memAttributes) string {
Good suggestion.
Done
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#23).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,968 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/23
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#24).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,968 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/24
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#25).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,968 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/25
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#26).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,968 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/26
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 26: Code-Review+1
(5 comments)
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 513: 4284
tRRD_S(1K) = Max(4nCK,4.2ns), where CK=1.071, so max = 4 * 1.071 = 4. […]
Ah okay. But, what if Tck is provided in JSON file? Shouldnt 4 * tCK be calculated by the tool to decide whether to use that or the fixed value provided in the spec?
Basically something like:
speedToTRRDSMinPsOneKPageSize = map[int]int { 1600: 5000, 1866: 4200, 2133: 3700, 2400: 3300, 2666: 3000, 2933: 2700, 3200: 2500 }
speedToTRRDSMinPsTwoKPageSize = map[int]int { 1600: 6000, 1866: 5300, 2133: 5300, 2400: 5300, 2666: 5300, 2933: 5300, 3200: 5300 }
func getTRRDSMinPs(memAttribs *memAttributes) int { var tRRDFixed int var tRRDFromTck int
switch pageSizefromBusWidthEncoding[memAttribs.DeviceBusWidth] { case 1: tRRDFixed = speedToTRRDSMinPsOneKPageSize[memAttribs.SpeedMTps] case 2: tRRDFixed = speedToTRRDSMinPsTwoKPageSize[memAttribs.SpeedMTps] default: tRRDFixed = 0 }
tRRDFromTck = 4 * memAttribs.tckMinPs
if tRRDFixed < tRRDFromTck { return tRRDFromTck } else { return tRRDFixed } }
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... PS26, Line 265: case 4: : width = 0 This is not really supported, right?
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... PS26, Line 530: nit: extra blank line not required.
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... PS26, Line 537: nit: extra blank line not required.
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... PS26, Line 12: 9 10 11 12 13 14 15 16 17 18 19 20 Please see comments on patchset 18 and 11.
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#27).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 1,976 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/27
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 26:
(9 comments)
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 513: 4284
Ah okay. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... PS26, Line 265: case 4: : width = 0
This is not really supported, right?
No, it's not. I'll remove it.
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... PS26, Line 530:
nit: extra blank line not required.
Done
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... PS26, Line 537:
nit: extra blank line not required.
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 13: "signalLoading": "not specified",
See my comment on the README on patchset 9. Signal loading can be derived from package type i.e. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 15: 9 10 11 12 13 14 15 16 17 19 19 20
I don't think this is correct. […]
The speed bin 3200AA is SUPPOSED to support 9 thru 22 and 24. The spec for this part said it only supported those listed above (i.e. it doesn't support 21, 22, or 24, even though it's binned as a 22-22-22 3200AA part, so the default setting is overridden here (see page 3 of the part spec sheet here : https://drive.google.com/corp/drive/folders/177abEFOZkA9iLEMJMXMj2WHKBCr9966...)
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 25: "pageSize": "2KB",
Please see my comment on patchset 9. I don't think we need this separate attribute. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 30: 10 11 12 13 14 15 16 17 19 19 20 21 22
Where are these values coming from? I think this part also supports all the standard latencies for 3 […]
see comment above, they're from the part spec sheet.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 45: 9 10 11 12 13 14 15 16 17 19 19 20
same here as above.
see comment above
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 28:
(1 comment)
This change is ready for review.
https://review.coreboot.org/c/coreboot/+/44429/28/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/28/util/spd_tools/intel/ddr4/... PS28, Line 476: tRRDLFromTck = 4 * memAttribs.TCKMinPs : : if tRRDLFixed < tRRDLFromTck { : return tRRDLFromTck : } else { : return tRRDLFixed : } : Technically, I think this should go into the updateTRRDLMin() to make sure that if a user specified a TRRDLMin, we still probably want to make sure that it follows the MAX rule for tRRDLMin. But then again, if for some reason a max value was not correct, we would need the ability to override it without changing override value. Same for the others.
Furquan, what do you think?
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 28:
(2 comments)
https://review.coreboot.org/c/coreboot/+/44429/28/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/28/util/spd_tools/intel/ddr4/... PS28, Line 476: tRRDLFromTck = 4 * memAttribs.TCKMinPs : : if tRRDLFixed < tRRDLFromTck { : return tRRDLFromTck : } else { : return tRRDLFixed : } :
Technically, I think this should go into the updateTRRDLMin() to make sure that if a user specified […]
Yeah I think if there is an override present, we will want to honor that. I am fine if you want to move this to updateTRRDLMin() to ensure that the json file does not have mistakes. And if there really arises a situation where we have to ignore the formula, we can update the tool.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 15: 9 10 11 12 13 14 15 16 17 19 19 20
The speed bin 3200AA is SUPPOSED to support 9 thru 22 and 24. […]
Are you referring to the line "Programmable CAS latency 9, 10... and 20 supported". I think there is something missing. From the table "Operating Frequency" I see that there are different grades for the same part name. I am not sure if the above sentence really applies to -XN part. Also pages 37 onwards, it covers the "Standard Speed Bins" where in 3200 22-22-22 seems to support all the CLs as outlined by JEDEC spec.
Can you please get a confirmation from Catherine and/or ODM to ensure what CLs are really supported? I also checked the sample SPDs provided by ODM here: https://b.corp.google.com/issues/161772961#comment16 and it looks like at least both Hynix parts here support all the standard CLs for 3200 22-22-22 grade.
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#29).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 2,006 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/29
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 29:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/28/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/28/util/spd_tools/intel/ddr4/... PS28, Line 476: tRRDLFromTck = 4 * memAttribs.TCKMinPs : : if tRRDLFixed < tRRDLFromTck { : return tRRDLFromTck : } else { : return tRRDLFixed : } :
Yeah I think if there is an override present, we will want to honor that. […]
Done
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 29: Code-Review+2
Only pending comment is to ensure that the CAS Latencies for the parts added are correct. I know you have an outstanding question for the ODM. Once we hear back, we should update the latencies if required.
Rob Barnes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 29:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1134: SPDIndexManufacturerPartNumberStartByte = 329 Why not fix the CRC too? Perhaps nobody checks it in practice, but someone might.
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 29:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/29/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_part_id.go:
PS29: We should drop "intel" from the path i.e. move util/spd_tools/intel/ddr4 to util/spd_tools/ddr4. Same for lp4x.
Rob Barnes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 29:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/29/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/29/util/spd_tools/intel/ddr4/... PS29, Line 192: return bg << 6 I don't think this is right. 2 bank groups = 1 << 6, 4 bank groups = 2 << 6.
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 29: -Code-Review
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/29/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/29/util/spd_tools/intel/ddr4/... PS29, Line 192: return bg << 6
I don't think this is right. 2 bank groups = 1 << 6, 4 bank groups = 2 << 6.
That's right!
Rob Barnes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 29:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 30: 10 11 12 13 14 15 16 17 19 19 20 21 22
see comment above, they're from the part spec sheet.
On page 363 I see "10-22, 24"
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#30).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 2,015 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/30
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 30:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/29/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/29/util/spd_tools/intel/ddr4/... PS29, Line 192: return bg << 6
That's right!
Done
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#31).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-3.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 8 files changed, 2,014 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/31
Nick Vaccaro has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 32:
(1 comment)
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 30: 10 11 12 13 14 15 16 17 19 19 20 21 22
On page 363 I see "10-22, 24"
I can't find the spot where I got this from, but I do see what Rob pointed out on page 363 where it does show that the part supports all standard supported CL settings for 3200AA (22-22-22) bin. Catherine commented that "this part doesn't support CL=21" at https://b.corp.google.com/issues/161772961#comment11. There was a mixup with mem part docs from ODM early on, this info may have been from the previous (wrong) docs.
Rob Barnes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 32: Code-Review+1
Hello build bot (Jenkins), Furquan Shaikh, Ravishankar Sarawadi, Rob Barnes, Patrick Rudolph,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44429
to look at the new patch set (#33).
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com --- A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 7 files changed, 1,980 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/44429/33
Rob Barnes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 33: Code-Review+1
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 33: Code-Review+2
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 33:
(17 comments)
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/README.md:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 101:
Just curious: Do we really need all these optional attributes defined right away? If some or most of […]
Done
https://review.coreboot.org/c/coreboot/+/44429/17/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/README.md:
https://review.coreboot.org/c/coreboot/+/44429/17/util/spd_tools/intel/ddr4/... PS17, Line 41: Intel : MRC
just say SoC since this will be used by more than just Intel.
Done
https://review.coreboot.org/c/coreboot/+/44429/17/util/spd_tools/intel/ddr4/... PS17, Line 80: Do
To?
Done
https://review.coreboot.org/c/coreboot/+/44429/29/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_part_id.go:
PS29:
We should drop "intel" from the path i.e. move util/spd_tools/intel/ddr4 to util/spd_tools/ddr4. […]
I will address this as a follow-up.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/gen_spd.go:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 91: 1: 0x2,
The JEDEC SPD spec definitions get used by more than just DDR4. […]
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 468: 8: 1 << 4,
That means that the settings for the H5ANAG6NCMR-XN part (a x16 part) is incorrect in the global j […]
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 1134: SPDIndexManufacturerPartNumberStartByte = 329
Why not fix the CRC too? Perhaps nobody checks it in practice, but someone might.
We can add that as follow-up. Currently, LP4x also ignores the CRC field. We can add it if required later on.
https://review.coreboot.org/c/coreboot/+/44429/4/util/spd_tools/intel/ddr4/g... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/4/util/spd_tools/intel/ddr4/g... PS4, Line 7: "bankGroups": 4,
Should be 2 banks for 512Mb x 16.
This field is dropped in latest patchset.
https://review.coreboot.org/c/coreboot/+/44429/4/util/spd_tools/intel/ddr4/g... PS4, Line 24: "pageSize": 4,
Some data sheets state "Page size = 2COLBITS × ORG/8". […]
Done.
https://review.coreboot.org/c/coreboot/+/44429/4/util/spd_tools/intel/ddr4/g... PS4, Line 38: "pageSize": 2,
Page size should be 2KB (4 512B). Perhaps the format for this attribute should be 512B, 1KB or 2KB.
This field is dropped in latest patchset.
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 15: 9 10 11 12 13 14 15 16 17 19 19 20
Are you referring to the line "Programmable CAS latency 9, 10... and 20 supported". […]
Done
https://review.coreboot.org/c/coreboot/+/44429/11/util/spd_tools/intel/ddr4/... PS11, Line 45: 9 10 11 12 13 14 15 16 17 19 19 20
see comment above
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 12: 9 10 11 12 13 14 15 16 17 19 19 20
Reposting comment from patchset#11: […]
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 24: 10 11 12 13 14 15 16 17 19 19 20 21 22
Where are these values coming from? I think this part also supports all the standard latencies for 3 […]
Done
https://review.coreboot.org/c/coreboot/+/44429/18/util/spd_tools/intel/ddr4/... PS18, Line 36: 9 10 11 12 13 14 15 16 17 19 19 20
same here.
Done
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/19/util/spd_tools/intel/ddr4/... PS19, Line 12: "CASLatencies": "9 10 11 12 13 14 15 16 17 19 19 20"
19 is listed twice.
Done
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... File util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt:
https://review.coreboot.org/c/coreboot/+/44429/26/util/spd_tools/intel/ddr4/... PS26, Line 12: 9 10 11 12 13 14 15 16 17 18 19 20
Please see comments on patchset 18 and 11.
Done
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
Patch Set 33:
I am landing this change as is and 1 comment to move the tool out of intel/ sub-directory will be resolved as follow-up.
Furquan Shaikh has submitted this change. ( https://review.coreboot.org/c/coreboot/+/44429 )
Change subject: util: Add spd_tools to generate DDR4 SPDs for TGL boards ......................................................................
util: Add spd_tools to generate DDR4 SPDs for TGL boards
Serial Presence Detect (SPD) data for memory modules is used by Memory Reference Code (MRC) for training the memory. This SPD data is typically obtained from part vendors but has to be massaged to format it correctly as per JEDEC and MRC expectations. There have been numerous times in the past where the SPD data used is not always correct.
In order to reduce the manual effort of creating SPDs and generating DRAM IDs, this change adds tools for generating SPD files for DDR4 memory used in memory down configurations on Intel Tiger Lake (TGL) based platforms. These tools generate SPDs following JESD79-4C and Jedec "4.1.2.L-5 R29 v103" specification.
Two tools are provided: * gen_spd.go: Generates de-duplicated SPD files using a global memory part list provided by the mainboard in JSON format. Additionally, generates a SPD manifest file (in CSV format) with information about what memory part from the global list uses which of the generated SPD files.
* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 memory parts used by the board. Takes as input list of memory parts used by the board (with one memory part on each line) and the SPD manifest file generated by gen_spd.go. Generates Makefile.inc for integrating the generated SPD files in the coreboot build.
BUG=b:160157545
Change-Id: I263f936b332520753a6791c8d892fc148cb6f103 Signed-off-by: Nick Vaccaro nvaccaro@google.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/44429 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Rob Barnes robbarnes@google.com Reviewed-by: Furquan Shaikh furquan@google.com --- A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex A src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex A src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt A util/spd_tools/intel/ddr4/README.md A util/spd_tools/intel/ddr4/gen_part_id.go A util/spd_tools/intel/ddr4/gen_spd.go A util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt 7 files changed, 1,980 insertions(+), 0 deletions(-)
Approvals: build bot (Jenkins): Verified Furquan Shaikh: Looks good to me, approved Rob Barnes: Looks good to me, but someone else must approve
diff --git a/src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex b/src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex new file mode 100644 index 0000000..32d141f --- /dev/null +++ b/src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-1.hex @@ -0,0 +1,32 @@ +23 11 0C 03 45 21 00 08 00 00 00 00 02 03 00 00 +00 00 05 06 F8 FF 02 00 6E 6E 6E 11 00 6E F0 0A +20 08 00 05 00 F0 2B 34 28 00 78 00 14 3C 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 9C B5 00 00 00 00 BC 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 20 20 20 20 20 20 20 +20 20 20 20 20 20 20 20 20 20 20 20 20 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex b/src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex new file mode 100644 index 0000000..15e4d3f --- /dev/null +++ b/src/soc/intel/tigerlake/spd/ddr4/ddr4-spd-2.hex @@ -0,0 +1,32 @@ +23 11 0C 03 85 21 91 08 00 00 00 00 02 03 00 00 +00 00 05 06 F8 FF 02 00 6E 6E 6E 11 00 6E F0 0A +20 08 00 05 00 F0 2B 34 28 00 78 00 14 3C 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 9C B5 00 00 00 00 BC 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 20 20 20 20 20 20 20 +20 20 20 20 20 20 20 20 20 20 20 20 20 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt b/src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt new file mode 100644 index 0000000..22fce5c --- /dev/null +++ b/src/soc/intel/tigerlake/spd/ddr4/spd_manifest.generated.txt @@ -0,0 +1,3 @@ +H5AN8G6NDJR-XNC,ddr4-spd-1.hex +MT40A512M16TB-062E:J,ddr4-spd-1.hex +H5ANAG6NCMR-XNC,ddr4-spd-2.hex diff --git a/util/spd_tools/intel/ddr4/README.md b/util/spd_tools/intel/ddr4/README.md new file mode 100644 index 0000000..31e326d --- /dev/null +++ b/util/spd_tools/intel/ddr4/README.md @@ -0,0 +1,275 @@ +# DDR4 SPD tools README + +Tools for generating SPD files for DDR4 memory used in memory down +configurations on Intel Tiger Lake (TGL) based +platforms. These tools generate SPDs following JESD79-4C +and Jedec 4.1.2.L-5 R29 v103 specifications. + +There are two tools provided that assist TGL based mainboards +to generate SPDs and Makefile to integrate these SPDs in coreboot +build. These tools can also be used to allocate DRAM IDs (configure +DRAM hardware straps) for any DDR4 memory part used by the board. + +* gen_spd.go: Generates de-duplicated SPD files using a global memory + part list provided by the mainboard in JSON format. Additionally, + generates a SPD manifest file(in CSV format) with information about + what memory part from the global list uses which of the generated + SPD files. + +* gen_part_id.go: Allocates DRAM strap IDs for different DDR4 + memory parts used by the board. Takes as input list of memory parts + used by the board (with one memory part on each line) and the SPD + manifest file generated by gen_spd.go. Generates Makefile.inc for + integrating the generated SPD files in the coreboot build. + +## Tool 1 - gen_spd.go + +This program takes as input: +* Pointer to directory where the generated SPD files and manifest will + be placed. +* JSON file containing a global list of memory parts with their + attributes as per the datasheet. This is the list of all known + DDR4 memory parts irrespective of their usage on the board. +* SoC platform name for which the SPDs are being generated. Currently + supported platform names are `TGL`. + +Input JSON file requires the following two fields for every memory part: +* `name`: Name of the memory part +* `attribs`: List of attributes of the memory part as per its + datasheet. These attributes match the part specifications and are + independent of any SoC expectations. Tool takes care of translating + the physical attributes of the memory part to match JEDEC and Intel + MRC expectations. + +`attribs` field further contains two types of sub-fields: +* Mandatory: These attributes have to be provided for a memory part. +* Optional: These attributes can be provided by memory part if it wants + to override the defaults. + +### Mandatory `attribs` + +* `speedMTps`: Maximum rate supported by the part in MT/s. Valid values: + `1600, 1866, 2133, 2400, 2666, 2933, 3200` MT/s. + +* `CL_nRCD_nRP`: Refers to CAS Latency specified for the part (find + "CL-nRCD-nRP" in the vendor spec for the DDR4 part). + +* `capacityPerDieGb`: Capacity per die in gigabits. Valid values: + `2, 4, 8, 16` Gb part. + +* `diesPerPackage`: Number of dies on the part. Valid values: + `1, 2` dies per package. + +* `deviceBusWidth`: Number of bits of the device's address bus. Valid values: + `8, 16` bit-wide bus. NOTE: Width of x4 is not supported by this tool. + +* `ranksPerPackage`: From Jedec doc 4_01_02_AnnexL-1R23: + “Package ranks per DIMM” refers to the collections of devices on the module + sharing common chip select signals (across the data width of the DIMM), + either from the edge connector for unbuffered modules or from the outputs of + a registering clock driver for RDIMMs and LRDIMMs.Number of bits of the + device's address bus. Valid values: + `1, 2` package ranks. + +### Optional `attribs` + +The following options are calculated by the tool based on the mandatory +attributes described for the part, but there may be cases where a default value +must be overridden, such as when a device appears to be 3200AA, but does not +support all of the CAS latencies typically supported by a speed bin 3200AA part. +Do deal with such a case, the variable can be overridden here and the tool will +use this value instead of calculating one. All values must be defined in +picosecond units, except for "CASLatencies", which would be represented as a +string like "9 10 11 12 14". + + * `TAAMinPs`: Defines the minimum CAS Latency. + Table 48 of Jedec doc 4_01_02_AnnexL-5R29 lists tAAmin for each speed grade. + + * `TRASMinPs`: Refers to the minimum active to precharge delay time. + Table 55 of Jedec doc 4_01_02_AnnexL-5R29 lists tRPmin for each speed grade. + + * `TCKMinPs`: Refers to the minimum clock cycle time. + Table 42 of Jedec doc 4_01_02_AnnexL-5R29 lists tCKmin for each speed grade. + + * `TCKMaxPs`:Refers to the minimum clock cycle time. + Table 44 of Jedec doc 4_01_02_AnnexL-5R29 lists tCKmin for each speed grade. + + * `TRFC1MinPs`: Refers to the minimum refresh recovery delay time. + Table 59 of Jedec doc 4_01_02_AnnexL-5R29 lists tRFC1min for each page size. + + * `TRFC2MinPs`: Refers to the minimum refresh recovery delay time. + Table 61 of Jedec doc 4_01_02_AnnexL-5R29 lists tRFC2min for each page size. + + * `TRFC4MinPs`: Refers to the minimum refresh recovery delay time. + Table 63 of Jedec doc 4_01_02_AnnexL-5R29 lists tRFC4min for each page size. + + * `TFAWMinPs`:: Refers to the minimum four activate window delay time. + Table 66 of Jedec doc 4_01_02_AnnexL-5R29 lists tFAWmin for each speed grade + and page size combination. + + * `TRRDSMinPs`: Refers to the minimum activate to activate delay time to + different bank groups. + Table 68 of Jedec doc 4_01_02_AnnexL-5R29 lists tRRD_Smin for each speed grade + and page size combination. + + * `TRRDLMinPs`: Refers to the minimum activate to activate delay time to the + same bank group. + Table 70 of Jedec doc 4_01_02_AnnexL-5R29 lists tRRD_Lmin for each speed grade + and page size combination. + + * `TCCDLMinPs`: Refers to the minimum CAS to CAS delay time to same bank group. + Table 72 of Jedec doc 4_01_02_AnnexL-5R29 lists tCCD_Lmin for each speed grade. + + * `TWRMinPs`: Refers to the minimum write recovery time. + Table 75 of Jedec doc 4_01_02_AnnexL-5R29 lists tWRmin for each ddr4 type. + + * `TWTRSMinPs`: Refers to minimum write to read time to different bank group. + Table 78 of Jedec doc 4_01_02_AnnexL-5R29 lists tWTR_Smin for each ddr4 type. + + * `TWTRLMinPs`: Refers to minimum write to read time to same bank group. + Table 80 of Jedec doc 4_01_02_AnnexL-5R29 lists tWTR_Lmin for each ddr4 type. + + * `CASLatencies`: Refers to the CAS latencies supported by the part. + The speed bin tables in the back of Jedec doc 4_01_02_AnnexL-5R29 define the + standard CAS latencies that a speed bin part is supposed to support. + In cases where a part does not support all of the CAS latencies listed in the + speed bin tables, this entry should be used to override the default settings. + +### Example JSON file +``` +{ + "parts": [ + { + "name": "MEMORY_PART_A", + "attribs": { + "speedMTps": 3200, + "CL_nRCD_nRP": 22 + "capacityPerDieGb": 8, + "diesPerPackage": 2, + "deviceBusWidth": 16, + "ranksPerPackage": 1, + } + }, + { + "name": "MEMORY_PART_B", + "attribs": { + "speedMTps": 3200, + "CL_nRCD_nRP": 22 + "capacityPerDieGb": 8, + "diesPerPackage": 1, + "deviceBusWidth": 16, + "ranksPerPackage": 2, + "casLatencies": "9 10 11 12 13 14 15 16 17 18 19 20", + "tCKMaxPs": "1250" + } + } + ] +} +``` + +### Output + +This tool generates the following files using the global list of +memory parts in JSON format as described above: + * De-duplicated SPDs required for the different memory parts. These + SPD files are named (ddr4-spd-1.hex, ddr4-spd-2.hex, and so on) + and placed in the directory provided as an input to the tool. + * CSV file representing which of the deduplicated SPD files is used + by which memory part. This file is named as + `spd_manifest.generated.txt` and placed in the directory provided + as an input to the tool along with the generated SPD + files. Example CSV file: + ``` + MEMORY_PART_A, ddr4-spd-1.hex + MEMORY_PART_B, ddr4-spd-2.hex + MEMORY_PART_C, ddr4-spd-3.hex + MEMORY_PART_D, ddr4-spd-2.hex + MEMORY_PART_E, ddr4-spd-2.hex + ``` + +## Tool 2 - gen_part_id.go + +This program takes as input: +* Pointer to directory where the SPD files and the manifest file + `spd_manifest.generated.txt` (in CSV format) are placed by + gen_spd.go +* File containing list of memory parts used by the board. Each line of + the file is supposed to contain one memory part `name` as present in + the global list of memory parts provided to gen_spd.go +* Pointer to directory where the generated Makefile.inc should be + placed by the tool. + +### Output + +This program provides the following: + +* Prints out the list of DRAM hardware strap IDs that should be + allocated to each memory part listed in the input file. +* Makefile.inc is generated in the provided directory to integrate + SPDs generated by gen_spd.go with the coreboot build for the board. +* dram_id.generated.txt is generated in the same directory as + Makefile. This contains the part IDs assigned to the different + memory parts. (Useful to integrate in board schematics). + +Sample output (dram_id.generated.txt): +``` +DRAM Part Name ID to assign +MEMORY_PART_A 0 (0000) +MEMORY_PART_B 1 (0001) +MEMORY_PART_C 2 (0010) +MEMORY_PART_D 1 (0001) +``` + +Sample Makefile.inc: +``` +## SPDX-License-Identifier: GPL-2.0-or-later +## This is an auto-generated file. Do not edit!! + +SPD_SOURCES = +SPD_SOURCES += ddr4-spd-1.hex # ID = 0(0b0000) Parts = MEMORY_PART_A +SPD_SOURCES += ddr4-spd-2.hex # ID = 1(0b0001) Parts = MEMORY_PART_B, MEMORY_PART_D +SPD_SOURCES += ddr4-spd-3.hex # ID = 2(0b0010) Parts = MEMORY_PART_C +``` + +### Note of caution + +This program assigns DRAM IDs using the order of DRAM part names +provided in the input file. Thus, when adding a new memory part to the +list, it should always go to the end of the input text file. This +guarantees that the memory parts that were already assigned IDs do not +change. + +## How to build the tools? +``` +# go build gen_spd.go +# go build gen_part_id.go +``` + +## How to use the tools? +``` +# ./gen_spd <spd_dir> <mem_parts_list_json> <platform> +# ./gen_part_id <spd_dir> <makefile_dir> <mem_parts_used_file> +``` + +## Example Usage +``` +# ./gen_spd ../../../../src/soc/intel/tigerlake/spd/ddr4 ./global_ddr4_mem_parts.json.txt 'TGL' + +``` + +### Need to add a new memory part for a board? + +* If the memory part is not present in the global list of memory + parts, then add the memory part name and attributes as per the + datasheet to the file containing the global list. + * Use `gen_spd.go` with input as the file containing the global list + of memory parts to generate de-duplicated SPDs. + * If a new SPD file is generated, use `git add` to add it to the + tree and push a CL for review. +* Update the file containing memory parts used by board (variant) to + add the new memory part name at the end of the file. + * Use gen_part_id.go providing it pointer to the location where SPD + files are stored and file containing the list of memory parts used + by the board(variant). + * Use `git add` to add `Makefile.inc` and `dram_id.generated.txt` + with updated changes and push a CL for review. diff --git a/util/spd_tools/intel/ddr4/gen_part_id.go b/util/spd_tools/intel/ddr4/gen_part_id.go new file mode 100644 index 0000000..f67b4a9 --- /dev/null +++ b/util/spd_tools/intel/ddr4/gen_part_id.go @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +package main + +import ( + "encoding/csv" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" +) + +/* + * This program allocates DRAM strap IDs for different parts that are being used by the variant. + * + * It expects the following inputs: + * Pointer to SPD directory. This is the location where SPD files and SPD Manifest generated by + * gen_spd.go are placed. + * Pointer to Makefile directory. Makefile.inc generated by this program is placed in this + * location. + * Text file containing a list of memory parts names used by the board. Each line in the file + * is expected to have one memory part name. + */ +const ( + SPDManifestFileName = "spd_manifest.generated.txt" + MakefileName = "Makefile.inc" + DRAMIdFileName = "dram_id.generated.txt" +) + +func usage() { + fmt.Printf("\nUsage: %s <spd_dir> <makefile_dir> <mem_parts_used_file>\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(" makefile_dir = Directory path where generated Makefile.inc should be placed\n") + fmt.Printf(" mem_parts_used_file = File containing list of memory parts used by the board\n\n\n") +} + +func checkArgs() error { + + for _, arg := range os.Args[1:] { + if _, err := os.Stat(arg); err != nil { + return err + } + } + + return nil +} + +/* + * Read input file that contains list of memory part names used by the variant (one on a line) + * and split into separate strings for each part name. + */ +func readParts(memPartsUsedFileName string) ([]string, error) { + lines, err := ioutil.ReadFile(memPartsUsedFileName) + if err != nil { + return nil, err + } + str := string(lines) + parts := strings.Split(str, "\n") + + return parts, nil +} + +/* + * Read SPD manifest file(CSV) generated by gen_spd program and generate two maps: + * 1. Part to SPD Map : This maps global memory part name to generated SPD file name + * 2. SPD to Index Map: This generates a map of deduplicated SPD file names to index assigned to + * that SPD. This function sets index for all SPDs to -1. This index gets + * updated as part of genPartIdInfo() depending upon the SPDs actually used + * by the variant. + */ +func readSPDManifest(SPDDirName string) (map[string]string, map[string]int, error) { + f, err := os.Open(filepath.Join(SPDDirName, SPDManifestFileName)) + if err != nil { + return nil, nil, err + } + defer f.Close() + r := csv.NewReader(f) + + partToSPDMap := make(map[string]string) + SPDToIndexMap := make(map[string]int) + + for { + fields, err := r.Read() + + if err == io.EOF { + break + } + + if err != nil { + return nil, nil, err + } + + if len(fields) != 2 { + return nil, nil, fmt.Errorf("CSV file is incorrectly formatted") + } + + partToSPDMap[fields[0]] = fields[1] + SPDToIndexMap[fields[1]] = -1 + } + + return partToSPDMap, SPDToIndexMap, nil +} + +/* Print information about memory part used by variant and ID assigned to it. */ +func appendPartIdInfo(s *string, partName string, index int) { + *s += fmt.Sprintf("%-30s %d (%04b)\n", partName, index, int64(index)) +} + +type partIds struct { + SPDFileName string + memParts string +} + +/* + * For each part used by variant, check if the SPD (as per the manifest) already has an ID + * assigned to it. If yes, then add the part name to the list of memory parts supported by the + * SPD entry. If not, then assign the next ID to the SPD file and add the part name to the + * list of memory parts supported by the SPD entry. + * + * Returns list of partIds that contains spdFileName and supported memory parts for each + * assigned ID. + */ +func genPartIdInfo(parts []string, partToSPDMap map[string]string, SPDToIndexMap map[string]int, makefileDirName string) ([]partIds, error) { + partIdList := []partIds{} + curId := 0 + var s string + + s += fmt.Sprintf("%-30s %s\n", "DRAM Part Name", "ID to assign") + + for _, p := range parts { + if p == "" { + continue + } + + SPDFileName,ok := partToSPDMap[p] + if !ok { + return nil, fmt.Errorf("Failed to find part ", p, " in SPD Manifest. Please add the part to global part list and regenerate SPD Manifest") + } + + index := SPDToIndexMap[SPDFileName] + if index != -1 { + partIdList[index].memParts += ", " + p + appendPartIdInfo(&s, p, index) + continue + } + + SPDToIndexMap[SPDFileName] = curId + + appendPartIdInfo(&s, p, curId) + entry := partIds{SPDFileName: SPDFileName, memParts: p} + partIdList = append(partIdList, entry) + + curId++ + } + + fmt.Printf("%s", s) + err := ioutil.WriteFile(filepath.Join(makefileDirName, DRAMIdFileName), []byte(s), 0644) + + return partIdList, err +} + +var generatedCodeLicense string = "## SPDX-License-Identifier: GPL-2.0-or-later" +var autoGeneratedInfo string = "## This is an auto-generated file. Do not edit!!" + +/* + * This function generates Makefile.inc under the variant directory path and adds assigned SPDs + * to SPD_SOURCES. + */ +func genMakefile(partIdList []partIds, makefileDirName string) error { + var s string + + s += fmt.Sprintf("%s\n%s\n\n", generatedCodeLicense, autoGeneratedInfo) + s += fmt.Sprintf("MEMORY_TYPE = ddr4\n\n") + s += fmt.Sprintf("SPD_SOURCES =\n") + + for i := 0; i < len(partIdList); i++ { + s += fmt.Sprintf("SPD_SOURCES += %s ", partIdList[i].SPDFileName) + s += fmt.Sprintf(" # ID = %d(0b%04b) ", i, int64(i)) + s += fmt.Sprintf(" Parts = %04s\n", partIdList[i].memParts) + } + + return ioutil.WriteFile(filepath.Join(makefileDirName, MakefileName), []byte(s), 0644) +} + +func main() { + if len(os.Args) != 4 { + usage() + log.Fatal("Incorrect number of arguments") + } + + SPDDir, MakefileDir, MemPartsUsedFile := os.Args[1], os.Args[2], os.Args[3] + + partToSPDMap, SPDToIndexMap, err := readSPDManifest(SPDDir) + if err != nil { + log.Fatal(err) + } + + parts, err := readParts(MemPartsUsedFile) + if err != nil { + log.Fatal(err) + } + + partIdList, err := genPartIdInfo(parts, partToSPDMap, SPDToIndexMap, MakefileDir) + if err != nil { + log.Fatal(err) + } + + if err := genMakefile(partIdList, MakefileDir); err != nil { + log.Fatal(err) + } +} diff --git a/util/spd_tools/intel/ddr4/gen_spd.go b/util/spd_tools/intel/ddr4/gen_spd.go new file mode 100644 index 0000000..5adadc9 --- /dev/null +++ b/util/spd_tools/intel/ddr4/gen_spd.go @@ -0,0 +1,1386 @@ +/* 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 DDR4 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 +) + +var platformMap = map[string]int { + "TGL": PlatformTGL, +} + +var currPlatform int + +type memAttributes struct { + /* Primary attributes - must be provided by JSON file for each part */ + SpeedMTps int + CL_nRCD_nRP int + CapacityPerDieGb int + DiesPerPackage int + DeviceBusWidth int + RanksPerPackage int + + /* + * All the following parameters are optional and required only if the part requires + * special parameters as per the datasheet. + */ + /* Timing parameters */ + TAAMinPs int + TRCDMinPs int + TRPMinPs int + TRASMinPs int + TRCMinPs int + TCKMinPs int + TCKMaxPs int + TRFC1MinPs int + TRFC2MinPs int + TRFC4MinPs int + TFAWMinPs int + TRRDLMinPs int + TRRDSMinPs int + TCCDLMinPs int + TWRMinPs int + TWTRLMinPs int + TWTRSMinPs int + + /* CAS */ + CASLatencies string + CASFirstByte byte + CASSecondByte byte + CASThirdByte byte + CASFourthByte byte +} + +/* This encodes the density in Gb to SPD low nibble value as per JESD 4.1.2.L-5 R29 */ +var densityGbToSPDEncoding = map[int]byte { + 2: 0x3, + 4: 0x4, + 8: 0x5, + 16: 0x6, +} + +/* + * Tables 4 thru Table 7 from JESD79-4C. + * Maps density per die to row-column encoding for a device with x8/x16 + * physical channel. + */ +var densityGbx8x16DieCapacityToRowColumnEncoding = map[int]byte { + 2: 0x11, /* 14 rows, 10 columns */ + 4: 0x19, /* 15 rows, 10 columns */ + 8: 0x21, /* 16 rows, 10 columns */ + 16: 0x29, /* 17 rows, 10 columns */ +} + +/* + * Tables 169 & 170 in the JESD79-4C spec + * Maps die density to refresh timings. This is the same for x8 and x16 + * devices. + */ + +/* maps die density to rcf1 timing in pico seconds */ +var tRFC1Encoding = map[int]int { + 2: 160000, + 4: 260000, + 8: 350000, + 16: 550000, +} + +/* maps die density to rcf2 timing in pico seconds */ +var tRFC2Encoding = map[int]int { + 2: 110000, + 4: 160000, + 8: 260000, + 16: 350000, +} + +/* maps die density to rcf4 timing in pico seconds */ +var tRFC4Encoding = map[int]int { + 2: 90000, + 4: 110000, + 8: 160000, + 16: 260000, +} + +func getTRCMinPs(memAttribs *memAttributes) int { + return memAttribs.TAAMinPs + memAttribs.TRASMinPs +} + +func getDefaultTCKMinPs(memAttribs *memAttributes) int { + /* value 2000000 = 2 * 1000000, where 1000000 is to convert mS to pS */ + return 2000000 / memAttribs.SpeedMTps +} + +type speedBinAttributes struct { + TRASMinPs int + TCKMaxPs int +} + +var speedBinToSPDEncoding = map[int]speedBinAttributes { + 1600: { + TRASMinPs: 35000, + TCKMaxPs: 1500, + }, + 1866: { + TRASMinPs: 34000, + TCKMaxPs: 1250, + }, + 2133: { + TRASMinPs: 33000, + TCKMaxPs: 1071, + }, + 2400: { + TRASMinPs: 32000, + TCKMaxPs: 937, + }, + 2666: { + TRASMinPs: 32000, + TCKMaxPs: 833, + }, + 2933: { + TRASMinPs: 32000, + TCKMaxPs: 750, + }, + 3200: { + TRASMinPs: 32000, + TCKMaxPs: 682, + }, +} + +func getBankGroups(memAttribs *memAttributes) byte { + var bg byte + + switch memAttribs.DeviceBusWidth { + case 8: + bg = 4 + case 16: + if memAttribs.DiesPerPackage == 1 { + bg = 2 /* x16 SDP has 2 bank groups */ + } else { + bg = 4 /* x16 DDP has 4 bank groups */ + } + } + + return bg +} + +func encodeBankGroups(bg byte) byte { + var val byte + + switch bg { + case 2: + val = 1 + case 4: + val = 2 + } + + return val << 6 +} + +func encodeDensityBanks(memAttribs *memAttributes) byte { + var b byte + + b = densityGbToSPDEncoding[memAttribs.CapacityPerDieGb] + b |= encodeBankGroups(getBankGroups(memAttribs)) + /* No need to encode banksPerGroup.it's always 4 ([4:5] = 0) */ + + return b +} + +func encodeSdramAddressing(memAttribs *memAttributes) byte { + var b byte + + b = densityGbx8x16DieCapacityToRowColumnEncoding[memAttribs.CapacityPerDieGb] + + return b +} + +func encodePackageDeviceType(dies int) byte { + var b byte + + if dies > 1 { + /* If more than one die, then this is a non-monolithic device. */ + b = 1 + } else { + /* If only single die, then this is a monolithic device. */ + b = 0 + } + + return b << 7 +} + +func encodeSignalLoadingFromDieCount(dies int) byte { + var loading byte + + /* + * If die count = 1, signal loading = "not specified" = 0 + * If die count > 1, signal loading = "multi" = 2 + */ + if dies == 1 { + loading = 0 + } else { + loading = 1 + } + + return loading +} + +func encodeDiesPerPackage(dies int) byte { + var b byte + + b = encodePackageDeviceType(dies) /* Monolithic / Non-monolithic device */ + b |= (byte(dies) - 1) << 4 + + return b +} + +func encodePackageType(memAttribs *memAttributes) byte { + var b byte + + b = encodeDiesPerPackage(memAttribs.DiesPerPackage) + b |= encodeSignalLoadingFromDieCount(memAttribs.DiesPerPackage) + + return b +} + +func encodeDataWidth(bitWidthPerDevice int) byte { + var width byte + + switch bitWidthPerDevice { + case 8: + width = 1 + case 16: + width = 2 + } + + return width +} + +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.DeviceBusWidth) + b |= encodeRanks(memAttribs.RanksPerPackage) + + return b +} + +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 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 encodeTAAMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TAAMinPs) +} + +func encodeTAAMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TAAMinPs) +} + +func encodeTRCDMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TRCDMinPs) +} + +func encodeTRCDMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TRCDMinPs) +} + +func encodeTRPMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TRPMinPs) +} + +func encodeTRCMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TRCMinPs) +} + +func encodeTRPMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TRPMinPs) +} + +func encodeTRASRCMinMSNs(memAttribs *memAttributes) byte { + var b byte + + b = byte((convPsToMtb(memAttribs.TRASMinPs) >> 4) & 0xf0) + b |= byte((convPsToMtb(memAttribs.TRCMinPs) >> 8) & 0x0f) + + return b +} + +func encodeTRASMinLsb(memAttribs *memAttributes) byte { + return byte(convPsToMtb(memAttribs.TRASMinPs) & 0xff) +} + +func encodeTRCMinLsb(memAttribs *memAttributes) byte { + return byte(convPsToMtb(memAttribs.TRCMinPs) & 0xff) +} + +var pageSizefromBusWidthEncoding = map[int]int { + 8: 1, + 16: 2, +} + +/* + * Per Table 69 & Table 70 of Jedec JESD79-4C + * tFAW timing is based on : + * Speed bin and page size + */ +func getTFAWMinPs(memAttribs *memAttributes) int { + var tFAWFixed int + + if pageSizefromBusWidthEncoding[memAttribs.DeviceBusWidth] == 1 { + switch memAttribs.SpeedMTps { + case 1600: + tFAWFixed = 25000 + case 1866: + tFAWFixed = 23000 + default: + tFAWFixed = 21000 + } + } else if pageSizefromBusWidthEncoding[memAttribs.DeviceBusWidth] == 2 { + switch memAttribs.SpeedMTps { + case 1600: + tFAWFixed = 35000 + default: + tFAWFixed = 30000 + } + } + + return tFAWFixed +} + +/* Update settings based on data sheet (json) supplied memory attributes */ + +func updateTFAWMin(memAttribs *memAttributes) { + var tFAWFromTck int + + if memAttribs.TFAWMinPs == 0 { + memAttribs.TFAWMinPs = getTFAWMinPs(memAttribs) + } + + switch pageSizefromBusWidthEncoding[memAttribs.DeviceBusWidth] { + case 1: + tFAWFromTck = 20 * memAttribs.TCKMinPs + case 2: + tFAWFromTck = 28 * memAttribs.TCKMinPs + } + + if memAttribs.TFAWMinPs < tFAWFromTck { + memAttribs.TFAWMinPs = tFAWFromTck + } +} + +func updateTRFC1Min(memAttribs *memAttributes) { + if memAttribs.TRFC1MinPs == 0 { + memAttribs.TRFC1MinPs = tRFC1Encoding[memAttribs.CapacityPerDieGb] + } +} + +func updateTRFC2Min(memAttribs *memAttributes) { + if memAttribs.TRFC2MinPs == 0 { + memAttribs.TRFC2MinPs = tRFC2Encoding[memAttribs.CapacityPerDieGb] + } +} + +func updateTRFC4Min(memAttribs *memAttributes) { + if memAttribs.TRFC4MinPs == 0 { + memAttribs.TRFC4MinPs = tRFC4Encoding[memAttribs.CapacityPerDieGb] + } +} + +func getTRRDLMinPs(memAttribs *memAttributes) int { + var tRRDLFixed int + + /* + * Per JESD79-4C Tables 169 & 170, tRRD_L is based on : + * Speed bin and page size + */ + switch pageSizefromBusWidthEncoding[memAttribs.DeviceBusWidth] { + case 1: + switch memAttribs.SpeedMTps { + case 1600: + tRRDLFixed = 6000 + default: + tRRDLFixed = 5300 + } + case 2: + switch memAttribs.SpeedMTps { + case 1600: + tRRDLFixed = 7500 + default: + tRRDLFixed = 6400 + } + } + + return tRRDLFixed +} + +func updateTRRDLMin(memAttribs *memAttributes) { + var tRRDLFromTck int + + if memAttribs.TRRDLMinPs == 0 { + memAttribs.TRRDLMinPs= getTRRDLMinPs(memAttribs) + } + + tRRDLFromTck = 4 * memAttribs.TCKMinPs + + if memAttribs.TRRDLMinPs < tRRDLFromTck { + memAttribs.TRRDLMinPs = tRRDLFromTck + } +} + +var speedToTRRDSMinPsOneKPageSize = map[int]int { + 1600: 5000, + 1866: 4200, + 2133: 3700, + 2400: 3300, + 2666: 3000, + 2933: 2700, + 3200: 2500, +} + +var speedToTRRDSMinPsTwoKPageSize = map[int]int { + 1600: 6000, + 1866: 5300, + 2133: 5300, + 2400: 5300, + 2666: 5300, + 2933: 5300, + 3200: 5300, +} + +func getTRRDSMinPs(memAttribs *memAttributes) int { + var tRRDFixed int + + switch pageSizefromBusWidthEncoding[memAttribs.DeviceBusWidth] { + case 1: + tRRDFixed = speedToTRRDSMinPsOneKPageSize[memAttribs.SpeedMTps] + case 2: + tRRDFixed = speedToTRRDSMinPsTwoKPageSize[memAttribs.SpeedMTps] + } + + return tRRDFixed +} + +func updateTRRDSMin(memAttribs *memAttributes) { + var tRRDFromTck int + + if memAttribs.TRRDSMinPs == 0 { + memAttribs.TRRDSMinPs = getTRRDSMinPs(memAttribs) + } + + tRRDFromTck = 4 * memAttribs.TCKMinPs + + if memAttribs.TRRDSMinPs < tRRDFromTck { + memAttribs.TRRDSMinPs = tRRDFromTck + } +} + +/* + * Per JESD79-4C Tables 169 and 170, + * tCCD_L is based on : + * Speed Bin + */ +func getTCCDLMinPs(memAttribs *memAttributes) int { + var tCCDLFixed int + + switch memAttribs.SpeedMTps { + case 1600: + tCCDLFixed = 6250 + case 1866: + tCCDLFixed = 5355 + case 2133: + tCCDLFixed = 5355 + default: + tCCDLFixed = 5000 + } + + return tCCDLFixed +} + +func updateTCCDLMin(memAttribs *memAttributes) { + var tCCDLFromTck int + + if memAttribs.TCCDLMinPs == 0 { + memAttribs.TCCDLMinPs = getTCCDLMinPs(memAttribs) + } + + tCCDLFromTck = 5 * memAttribs.TCKMinPs + + if memAttribs.TCCDLMinPs < tCCDLFromTck { + memAttribs.TCCDLMinPs = tCCDLFromTck + } +} + +func encodeTRFC1MinLsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(memAttribs.TRFC1MinPs) + + return byte(mtb & 0xff) +} + +func encodeTRFC1MinMsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(memAttribs.TRFC1MinPs) + + return byte((mtb >> 8) & 0xff) +} + +func encodeTRFC2MinLsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(memAttribs.TRFC2MinPs) + + return byte(mtb & 0xff) +} + +func encodeTRFC2MinMsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(memAttribs.TRFC2MinPs) + + return byte((mtb >> 8) & 0xff) +} + +func encodeTRFC4MinLsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(memAttribs.TRFC4MinPs) + + return byte(mtb & 0xff) +} + +func encodeTRFC4MinMsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(memAttribs.TRFC4MinPs) + + return byte((mtb >> 8) & 0xff) +} + +func encodeTFAWMinMSN(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(memAttribs.TFAWMinPs) + + return byte((mtb >> 8) & 0x0f) +} + +func encodeTFAWMinLsb(memAttribs *memAttributes) byte { + var mtb int + + mtb = convPsToMtb(memAttribs.TFAWMinPs) + + return byte(mtb & 0xff) +} + +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 encodeCASFourthByte(memAttribs *memAttributes) byte { + return memAttribs.CASFourthByte +} + +func encodeTRRDSMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TRRDSMinPs) +} + +func encodeTRRDSMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TRRDSMinPs) +} + +func encodeTRRDLMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TRRDLMinPs) +} + +func encodeTRRDLMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TRRDLMinPs) +} + +func encodeTCCDLMin(memAttribs *memAttributes) byte { + return convPsToMtbByte(memAttribs.TCCDLMinPs) +} + +func encodeTCCDLMinFineOffset(memAttribs *memAttributes) byte { + return convPsToFtbByte(memAttribs.TCCDLMinPs) +} + +func encodeTWRMinMSN(memAttribs *memAttributes) byte { + return byte((convPsToMtb(TimingValueTWRMinPs) >> 8) & 0x0f) +} + +func encodeTWRMinLsb(memAttribs *memAttributes) byte { + return byte(convPsToMtb(TimingValueTWRMinPs) & 0xff) +} + +func encodeTWTRMinMSNs(memAttribs *memAttributes) byte { + var b byte + + b = byte((convPsToMtb(memAttribs.TWTRLMinPs) >> 4) & 0xf0) + b |= byte((convPsToMtb(memAttribs.TWTRSMinPs) >> 8) & 0x0f) + + return b +} + +func encodeTWTRSMinLsb(memAttribs *memAttributes) byte { + return byte(convPsToMtb(memAttribs.TWTRSMinPs) & 0xff) +} + +func encodeTWTRLMinLsb(memAttribs *memAttributes) byte { + return byte(convPsToMtb(memAttribs.TWTRLMinPs) & 0xff) +} + +type SPDMemAttribFunc func (*memAttributes) byte +type SPDConvConstFunc func () byte + +type SPDAttribTableEntry struct { + constVal byte + getVal SPDMemAttribFunc +} + +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 + SPDIndexTRCDMin = 25 + SPDIndexTRPMin = 26 + SPDIndexTRASRCMinMSNs = 27 + SPDIndexTRASMinLsb = 28 + SPDIndexTRCMinLsb = 29 + SPDIndexTRFC1MinLsb = 30 + SPDIndexTRFC1MinMsb = 31 + SPDIndexTRFC2MinLsb = 32 + SPDIndexTRFC2MinMsb = 33 + SPDIndexTRFC4MinLsb = 34 + SPDIndexTRFC4MinMsb = 35 + SPDIndexTFAWMinMSN = 36 + SPDIndexTFAWMinLsb = 37 + SPDIndexTRRDSMin = 38 + SPDIndexTRRDLMin = 39 + SPDIndexTCCDLMin = 40 + SPDIndexTWRMinMSN = 41 + SPDIndexTWRMinLsb = 42 + SPDIndexTWTRMinMSNs = 43 + SPDIndexWTRSMinLsb = 44 + SPDIndexWTRLMinLsb = 45 + SPDIndexTCCDLMinFineOffset = 117 + SPDIndexTRRDLMinFineOffset = 118 + SPDIndexTRRDSMinFineOffset = 119 + SPDIndexTRCMinFineOffset = 120 + SPDIndexTRPMinFineOffset = 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 DDR4. + */ + SPDValueSize = 0x23 + + /* + * From JEDEC spec: Revision 1.1 + * Set to 0x11. + */ + SPDValueRevision = 0x11 + + /* DDR4 memory type = 0x0C */ + SPDValueMemoryType = 0x0C + + /* + * From JEDEC spec: + * Module Type [0:3] : + * 0 = Undefined + * 1 = RDIMM (width = 133.35 mm nom) + * 2 = UDIMM (width = 133.35 mm nom) + * 3 = SO-DIMM (width = 68.60 mm nom) + * 4 = LRDIMM (width = 133.35 mm nom) + * + * DDR4 on TGL uses SO-DIMM type for for both memory down and DIMM config. + * Set to 0x03. + */ + SPDValueModuleType = 0x03 + + /* + * 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: + * 2:0 Primary Bus Width in Bits = 011 (x64 always) + * Set to 0x03. + */ + SPDValueModuleBusWidth = 0x03 + + /* + * 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 + + /* As per JEDEC spec, unused digits of manufacturer part number are left as blank. */ + SPDValueManufacturerPartNumberBlank = 0x20 + +) + +const ( + /* + * As per Table 75 of Jedec spec 4.1.20-L-5 R29 v103: + * tWRMin = 15nS for all DDR4 Speed Bins + * Set to 15000 pS + */ + TimingValueTWRMinPs = 15000 + + /* + * As per Table 78 of Jedec spec 4.1.20-L-5 R29 v103: + * tWTR_SMin = 2.5nS for all DDR4 Speed Bins + * Set to 2500 pS + */ + TimingValueTWTRSMinPs = 2500 + + /* + * As per Table 80 of Jedec spec 4.1.20-L-5 R29 v103: + * tWTR_LMin = 7.5 nS for all DDR4 Speed Bins + * Set to 7500 pS + */ + TimingValueTWTRLMinPs = 7500 +) + +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: { constVal: SPDValueModuleBusWidth }, + SPDIndexTimebases: { constVal: SPDValueTimebases }, + SPDIndexTCKMin: { getVal: encodeTCKMin }, + SPDIndexTCKMinFineOffset: { getVal: encodeTCKMinFineOffset }, + SPDIndexTCKMax: { getVal: encodeTCKMax }, + SPDIndexTCKMaxFineOffset: { getVal: encodeTCKMaxFineOffset }, + SPDIndexCASFirstByte: { getVal: encodeCASFirstByte }, + SPDIndexCASSecondByte: { getVal: encodeCASSecondByte }, + SPDIndexCASThirdByte: { getVal: encodeCASThirdByte }, + SPDIndexCASFourthByte: { getVal: encodeCASFourthByte }, + SPDIndexTAAMin: { getVal: encodeTAAMin }, + SPDIndexTAAMinFineOffset: { getVal: encodeTAAMinFineOffset }, + SPDIndexTRCDMin: { getVal: encodeTRCDMin }, + SPDIndexTRCDMinFineOffset: { getVal: encodeTRCDMinFineOffset }, + SPDIndexTRPMin: { getVal: encodeTRPMin }, + SPDIndexTRPMinFineOffset: { getVal: encodeTRPMinFineOffset }, + SPDIndexTRASRCMinMSNs: { getVal: encodeTRASRCMinMSNs }, + SPDIndexTRASMinLsb: { getVal: encodeTRASMinLsb }, + SPDIndexTRCMinLsb: { getVal: encodeTRCMinLsb }, + SPDIndexTRCMinFineOffset: { getVal: encodeTRCMinFineOffset }, + SPDIndexTRFC1MinLsb: { getVal: encodeTRFC1MinLsb }, + SPDIndexTRFC1MinMsb: { getVal: encodeTRFC1MinMsb }, + SPDIndexTRFC2MinLsb: { getVal: encodeTRFC2MinLsb }, + SPDIndexTRFC2MinMsb: { getVal: encodeTRFC2MinMsb }, + SPDIndexTRFC4MinLsb: { getVal: encodeTRFC4MinLsb }, + SPDIndexTRFC4MinMsb: { getVal: encodeTRFC4MinMsb }, + SPDIndexTFAWMinMSN: { getVal: encodeTFAWMinMSN }, + SPDIndexTFAWMinLsb: { getVal: encodeTFAWMinLsb }, + SPDIndexTRRDSMin: { getVal: encodeTRRDSMin }, + SPDIndexTRRDSMinFineOffset: { getVal: encodeTRRDSMinFineOffset }, + SPDIndexTRRDLMin: { getVal: encodeTRRDLMin }, + SPDIndexTRRDLMinFineOffset: { getVal: encodeTRRDLMinFineOffset }, + SPDIndexTCCDLMin: { getVal: encodeTCCDLMin }, + SPDIndexTCCDLMinFineOffset: { getVal: encodeTCCDLMinFineOffset }, + SPDIndexTWRMinMSN: { getVal: encodeTWRMinMSN }, + SPDIndexTWRMinLsb: { getVal: encodeTWRMinLsb }, + SPDIndexTWTRMinMSNs: { getVal: encodeTWTRMinMSNs }, + SPDIndexWTRSMinLsb: { getVal: encodeTWTRSMinLsb }, + SPDIndexWTRLMinLsb: { getVal: encodeTWTRLMinLsb }, +} + +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("ddr4-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 validateSpeedMTps(speedBin int) error { + if _, ok := speedBinToSPDEncoding[speedBin]; ok == false { + return fmt.Errorf("Incorrect speed bin: DDR4-", speedBin) + } + return nil +} + +func validateCapacityPerDie(capacityPerDieGb int) error { + if _, ok := densityGbToSPDEncoding[capacityPerDieGb]; ok == false { + return fmt.Errorf("Incorrect capacity per die: ", capacityPerDieGb) + } + return nil +} + +func validateDiesPerPackage(dieCount int) error { + if dieCount >= 1 && dieCount <= 2 { + return nil + } + return fmt.Errorf("Incorrect dies per package count: ", dieCount) +} + +func validateDeviceBusWidth(width int) error { + if width != 8 && width != 16 { + return fmt.Errorf("Incorrect device bus width: ", width) + } + return nil +} + +func validateRanksPerPackage(ranks int) error { + if ranks >= 1 && ranks <= 2 { + return nil + } + return fmt.Errorf("Incorrect package ranks: ", ranks) +} + + +func validateCASLatency(CL int) error { + if CL >= 10 && CL <= 24 && CL != 23 { + return nil + } + return fmt.Errorf("Incorrect CAS latency: ", CL) +} + +/* +1) validate memory parts +2) remove any fields that Intel does not care about +*/ + +/* verify the supplied CAS Latencies supported does not match default */ +func verifySupportedCASLatencies(part *memPart) error { + if part.Attribs.CASLatencies == getDefaultCASLatencies(&part.Attribs) { + return fmt.Errorf("CASLatencies for %s already matches default,\nPlease remove CASLatencies override line from the %s part attributes in the global part list and regenerate SPD Manifest", part.Name, part.Name) + } + + return nil +} + +func validateMemoryParts(memParts *memParts) error { + for i := 0; i < len(memParts.MemParts); i++ { + if err := validateSpeedMTps(memParts.MemParts[i].Attribs.SpeedMTps); err != nil { + return err + } + if err := validateCapacityPerDie(memParts.MemParts[i].Attribs.CapacityPerDieGb); err != nil { + return err + } + if err := validateDiesPerPackage(memParts.MemParts[i].Attribs.DiesPerPackage); err != nil { + return err + } + if err := validateDeviceBusWidth(memParts.MemParts[i].Attribs.DeviceBusWidth); err != nil { + return err + } + if err := validateRanksPerPackage(memParts.MemParts[i].Attribs.RanksPerPackage); err != nil { + return err + } + if err := validateCASLatency(memParts.MemParts[i].Attribs.CL_nRCD_nRP); err != nil { + return err + } + /* If CAS Latency was supplied, make sure it doesn't match default value */ + if len(memParts.MemParts[i].Attribs.CASLatencies) != 0 { + if err := verifySupportedCASLatencies(&memParts.MemParts[i]); err != nil { + return err + } + } + } + + return nil +} + +const ( + /* First Byte */ + CAS9 = 1 << 2 + CAS10 = 1 << 3 + CAS11 = 1 << 4 + CAS12 = 1 << 5 + CAS13 = 1 << 6 + CAS14 = 1 << 7 + /* Second Byte */ + CAS15 = 1 << 0 + CAS16 = 1 << 1 + CAS17 = 1 << 2 + CAS18 = 1 << 3 + CAS19 = 1 << 4 + CAS20 = 1 << 5 + CAS21 = 1 << 6 + CAS22 = 1 << 7 + /* Third Byte */ + CAS24 = 1 << 1 +) + +func encodeLatencies(latency int, memAttribs *memAttributes) error { + switch latency { + case 9: + memAttribs.CASFirstByte |= CAS9 + case 10: + memAttribs.CASFirstByte |= CAS10 + case 11: + memAttribs.CASFirstByte |= CAS11 + case 12: + memAttribs.CASFirstByte |= CAS12 + case 13: + memAttribs.CASFirstByte |= CAS13 + case 14: + memAttribs.CASFirstByte |= CAS14 + case 15: + memAttribs.CASSecondByte |= CAS15 + case 16: + memAttribs.CASSecondByte |= CAS16 + case 17: + memAttribs.CASSecondByte |= CAS17 + case 18: + memAttribs.CASSecondByte |= CAS18 + case 19: + memAttribs.CASSecondByte |= CAS19 + case 20: + memAttribs.CASSecondByte |= CAS20 + case 21: + memAttribs.CASSecondByte |= CAS21 + case 22: + memAttribs.CASSecondByte |= CAS22 + case 24: + memAttribs.CASThirdByte |= CAS24 + default: + fmt.Errorf("Incorrect CAS Latency: ", latency) + } + + return nil +} + +/* Default CAS Latencies from Speed Bin tables in JEDS79-4C */ +func getDefaultCASLatencies(memAttribs *memAttributes) string { + var str string + + switch memAttribs.SpeedMTps { + case 1600: + switch memAttribs.CL_nRCD_nRP { + case 10: + str = "9 10 11 12" + case 11: + str = "9 11 12" + case 12: + str = "10 12" + } + case 1866: + switch memAttribs.CL_nRCD_nRP { + case 12: + str = "9 10 12 13 14" + case 13: + str = "9 11 12 13 14" + case 14: + str = "10 12 14" + } + case 2133: + switch memAttribs.CL_nRCD_nRP { + case 14: + str = "9 10 12 14 15 16" + case 15: + str = "9 11 12 13 14 15 16" + case 16: + str = "10 12 14 16" + } + case 2400: + switch memAttribs.CL_nRCD_nRP { + case 15: + str = "9 10 12 14 15 16 17 18" + case 16: + str = "9 11 12 13 14 15 16 17 18" + case 17: + str = "10 11 12 13 14 15 16 17 18" + case 18: + str = "10 12 14 16 18" + } + case 2666: + switch memAttribs.CL_nRCD_nRP { + case 17: + str = "9 10 11 12 13 14 15 16 17 18 19 20" + case 18: + str = "9 10 11 12 13 14 15 16 17 18 19 20" + case 19: + str = "10 11 12 13 14 15 16 17 18 19 20" + case 20: + str = "10 12 14 16 18 20" + } + case 2933: + switch memAttribs.CL_nRCD_nRP { + case 19: + str = "9 10 11 12 13 14 15 16 17 18 19 20 21 22" + case 20: + str = "10 11 12 13 14 15 16 17 18 19 20 21 22" + case 21: + str = "10 11 12 13 14 15 16 17 18 19 20 21 22" + case 22: + str = "10 12 14 16 18 20 22" + } + case 3200: + switch memAttribs.CL_nRCD_nRP { + case 20: + str = "9 10 11 12 13 14 15 16 17 18 19 20 21 22 24" + case 22: + str = "10 11 12 13 14 15 16 17 18 19 20 21 22 24" + case 24: + str = "10 12 14 16 18 20 22 24" + } + } + + return str +} + +func updateCAS(memAttribs *memAttributes) error { + if len(memAttribs.CASLatencies) == 0 { + memAttribs.CASLatencies = getDefaultCASLatencies(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 getTAAMinPs(memAttribs *memAttributes) int { + return (memAttribs.CL_nRCD_nRP * 2000000) / memAttribs.SpeedMTps +} + +func updateTAAMin(memAttribs *memAttributes) { + if memAttribs.TAAMinPs == 0 { + memAttribs.TAAMinPs = getTAAMinPs(memAttribs) + } +} + +func updateTRCDMin(memAttribs *memAttributes) { + /* tRCDmin is same as tAAmin for all cases */ + if memAttribs.TRCDMinPs == 0 { + memAttribs.TRCDMinPs = getTAAMinPs(memAttribs) + } +} + +func updateTRPMin(memAttribs *memAttributes) { + /* tRPmin is same as tAAmin for all cases */ + if memAttribs.TRPMinPs == 0 { + memAttribs.TRPMinPs = getTAAMinPs(memAttribs) + } +} + +func updateTRASMin(memAttribs *memAttributes) { + if memAttribs.TRASMinPs == 0 { + memAttribs.TRASMinPs = speedBinToSPDEncoding[memAttribs.SpeedMTps].TRASMinPs + } +} + + +func updateTRCMin(memAttribs *memAttributes) { + if memAttribs.TRCMinPs == 0 { + memAttribs.TRCMinPs = getTRCMinPs(memAttribs) + } +} + +func updateTCK(memAttribs *memAttributes) { + if memAttribs.TCKMinPs == 0 { + memAttribs.TCKMinPs = getDefaultTCKMinPs(memAttribs) + } + if memAttribs.TCKMaxPs == 0 { + memAttribs.TCKMaxPs = speedBinToSPDEncoding[memAttribs.SpeedMTps].TCKMaxPs + } +} + +func updateTWRMin(memAttribs *memAttributes) { + if memAttribs.TWRMinPs == 0 { + memAttribs.TWRMinPs = TimingValueTWRMinPs + } +} + +func updateTWTRMin(memAttribs *memAttributes) { + if memAttribs.TWTRLMinPs == 0 { + memAttribs.TWTRLMinPs = TimingValueTWTRLMinPs + } + if memAttribs.TWTRSMinPs == 0 { + memAttribs.TWTRSMinPs = TimingValueTWTRSMinPs + } +} + +func updateMemoryAttributes(memAttribs *memAttributes) { + updateTCK(memAttribs) + updateTAAMin(memAttribs) + updateTRCDMin(memAttribs) + updateTRPMin(memAttribs) + updateTRASMin(memAttribs) + updateTRCMin(memAttribs) + updateTWRMin(memAttribs) + updateTWTRMin(memAttribs) + updateCAS(memAttribs) + updateTRFC1Min(memAttribs) + updateTRFC2Min(memAttribs) + updateTRFC4Min(memAttribs) + updateTCCDLMin(memAttribs) + updateTRRDSMin(memAttribs) + updateTRRDLMin(memAttribs) + updateTFAWMin(memAttribs) +} + +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++ { + updateMemoryAttributes(&memParts.MemParts[i].Attribs) + 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) + } +} diff --git a/util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt b/util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt new file mode 100644 index 0000000..4e9c7c8 --- /dev/null +++ b/util/spd_tools/intel/ddr4/global_ddr4_mem_parts.json.txt @@ -0,0 +1,37 @@ +{ + "parts": [ + { + "name": "H5AN8G6NDJR-XNC", + "attribs": { + "speedMTps": 3200, + "CL_nRCD_nRP": 22, + "capacityPerDieGb": 8, + "diesPerPackage": 1, + "deviceBusWidth": 16, + "ranksPerPackage": 1 + } + }, + { + "name": "MT40A512M16TB-062E:J", + "attribs": { + "speedMTps": 3200, + "CL_nRCD_nRP": 22, + "capacityPerDieGb": 8, + "diesPerPackage": 1, + "deviceBusWidth": 16, + "ranksPerPackage": 1 + } + }, + { + "name": "H5ANAG6NCMR-XNC", + "attribs": { + "speedMTps": 3200, + "CL_nRCD_nRP": 22, + "capacityPerDieGb": 8, + "diesPerPackage": 2, + "deviceBusWidth": 16, + "ranksPerPackage": 1 + } + } + ] +}