2020-08-13 02:02:49 +02:00
|
|
|
# DDR4 SPD tools README
|
|
|
|
|
2020-08-14 23:23:05 +02:00
|
|
|
Tools for generating SPD files for DDR4 memory used in platforms with
|
|
|
|
memory down configuration. These tools generate SPDs following JESD79-4C
|
2020-08-13 02:02:49 +02:00
|
|
|
and Jedec 4.1.2.L-5 R29 v103 specifications.
|
|
|
|
|
2020-08-14 23:23:05 +02:00
|
|
|
There are two tools provided that assist with generating SPDs and Makefiles
|
|
|
|
to integrate 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.
|
2020-08-13 02:02:49 +02:00
|
|
|
|
|
|
|
* 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
|
2020-08-14 17:40:04 +02:00
|
|
|
memory parts used by the board. Takes as input a list of memory parts
|
|
|
|
used (in CSV format) by the board with optional fixed ids and the SPD
|
2020-08-13 02:02:49 +02:00
|
|
|
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
|
2020-08-14 23:23:05 +02:00
|
|
|
supported platform names are `TGL`, `PCO` and `PLK`.
|
2020-08-13 02:02:49 +02:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
2020-08-27 20:44:38 +02:00
|
|
|
* `packageBusWidth`: Number of bits of the device's address bus. Valid values:
|
2020-08-13 02:02:49 +02:00
|
|
|
`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,
|
2020-08-27 20:44:38 +02:00
|
|
|
"packageBusWidth": 16,
|
2020-08-13 02:02:49 +02:00
|
|
|
"ranksPerPackage": 1,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "MEMORY_PART_B",
|
|
|
|
"attribs": {
|
|
|
|
"speedMTps": 3200,
|
|
|
|
"CL_nRCD_nRP": 22
|
|
|
|
"capacityPerDieGb": 8,
|
|
|
|
"diesPerPackage": 1,
|
2020-08-27 20:44:38 +02:00
|
|
|
"packageBusWidth": 16,
|
2020-08-13 02:02:49 +02:00
|
|
|
"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
|
2020-08-21 01:19:44 +02:00
|
|
|
`ddr4_spd_manifest.generated.txt` and placed in the directory provided
|
2020-08-13 02:02:49 +02:00
|
|
|
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
|
2020-08-21 01:19:44 +02:00
|
|
|
`ddr4_spd_manifest.generated.txt` (in CSV format) are placed by
|
2020-08-13 02:02:49 +02:00
|
|
|
gen_spd.go
|
2020-08-14 17:40:04 +02:00
|
|
|
* CSV file containing list of memory parts used by the board and optional
|
|
|
|
fixed id. 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.
|
|
|
|
Optionally a fixed id may also be assigned to the part if required.
|
|
|
|
NOTE: Only assign a fixed ID if required for legacy reasons.
|
|
|
|
|
2020-08-13 02:02:49 +02:00
|
|
|
* Pointer to directory where the generated Makefile.inc should be
|
|
|
|
placed by the tool.
|
|
|
|
|
2020-08-14 17:40:04 +02:00
|
|
|
Sample input (mem_parts_used_file.txt):
|
|
|
|
```
|
|
|
|
K4AAG165WA-BCWE,1
|
|
|
|
MT40A512M16TB-062E:J
|
|
|
|
MT40A1G16KD-062E:E
|
|
|
|
K4A8G165WC-BCWE
|
|
|
|
H5AN8G6NDJR-XNC,8
|
|
|
|
H5ANAG6NCMR-XNC
|
|
|
|
```
|
|
|
|
NOTE: This will ensure SPDs compatible with K4AAG165WA-BCWE and H5AN8G6NDJR-XNC
|
|
|
|
are assigned to ID 1 and 8 respectively. All other memory parts will be
|
|
|
|
assigned to the first compatible ID. Assigning fixed IDs may result in
|
|
|
|
duplicate SPD entries or gaps in the ID mapping.
|
|
|
|
|
2020-08-13 02:02:49 +02:00
|
|
|
### 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
|
2020-08-14 17:40:04 +02:00
|
|
|
SPD_SOURCES += ddr4-spd-empty.hex # ID = 2(0b0010)
|
2020-08-13 02:02:49 +02:00
|
|
|
SPD_SOURCES += ddr4-spd-3.hex # ID = 2(0b0010) Parts = MEMORY_PART_C
|
|
|
|
```
|
2020-08-14 17:40:04 +02:00
|
|
|
NOTE: Empty entries may be required if there is a gap created by a memory part
|
|
|
|
with a fixed id.
|
2020-08-13 02:02:49 +02:00
|
|
|
|
|
|
|
### 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.
|