A set of tools to generate SPD files for platforms with memory down configurations.
The memory technologies currently supported are:
There are two tools provided to assist with generating SPDs and Makefiles to integrate into the coreboot build. These tools can also be used to allocate DRAM IDs (configure DRAM hardware straps) for any memory part used by a board.
spd_gen
: This tool generates de-duplicated SPD files using a global memory part list. It also generates a CSV manifest file which maps each memory part in the global list to one of the generated SPD files. For each supported memory technology, multiple sets of SPDs are generated. Each set corresponds to a set of SoC platforms with different SPD requirements, e.g. due to different expectations in the memory training code. Another CSV manifest maps each supported platform to one of these sets.part_id_gen
: This tool allocates DRAM strap IDs for the different memory parts used by a board. It takes as input a CSV file of the memory parts used with optional fixed IDs. It generates a Makefile.inc which is used to integrate the SPD files generated by spd_gen
into the coreboot build.spd_gen
This program takes the following inputs:
The input JSON file requires the following two fields for every memory part:
name
: The name of the memory part.attribs
: A list of the memory part's attributes, as per its datasheet. These attributes match the part specifications and are independent of any SoC expectations. The tool takes care of translating the physical attributes of the memory part to match JEDEC spec and memory traning code expectations.The attribs
field further contains two types of sub-field:
The attributes are different for each memory technology.
densityPerChannelGb
: Density in Gb of the physical channel.
banks
: Number of banks per physical channel. This is typically 8 for LPDDR4x memory parts.
channelsPerDie
: Number of physical channels per die. Valid values: 1, 2, 4
. For a part with x16 bit width, number of channels per die is 1 or 2. For a part with x8 bit width, number of channels can be 2 or 4 (4 is basically when two dual-channel byte mode devices are combined as shown in Figure 3 in JESD209-4C).
diesPerPackage
: Number of physical dies in each SDRAM package. As per JESD209-4C, "Standard LPDDR4 package ballmaps allocate one ZQ ball per die." Thus, number of diesPerPackage is the number of ZQ balls on the package.
bitWidthPerChannel
: Width of each physical channel. Valid values: 8, 16
bits.
ranksPerChannel
: Number of ranks per physical channel. Valid values: 1, 2
. If the channels across multiple dies share the same DQ/DQS pins but use a separate CS, then ranks is 2 else it is 1.
speedMbps
: Maximum data rate supported by the part in Mbps. Valid values: 3200, 3733, 4267
Mbps.
trfcabNs
: Minimum Refresh Recovery Delay Time (tRFCab) for all banks in nanoseconds. As per JESD209-4C, this is dependent on the density per channel. Default values used:
trfcpbNs
: Minimum Refresh Recovery Delay Time (tRFCab) per bank in nanoseconds. As per JESD209-4C, this is dependent on the density per channel. Default values used:
trpabMinNs
: Minimum Row Precharge Delay Time (tRPab) for all banks in nanoseconds. As per JESD209-4C, this is max(21ns, 4nck) which defaults to 21ns
.
trppbMinNs
: Minimum Row Precharge Delay Time (tRPpb) per bank in nanoseconds. As per JESD209-4C, this is max(18ns, 4nck) which defaults to 18ns
.
tckMinPs
: SDRAM minimum cycle time (tckMin) value in picoseconds. This is typically calculated based on the speedMbps
attribute. (1 / speedMbps) * 2
. Default values used(taken from JESD209-4C):
tckMaxPs
: SDRAM maximum cycle time (tckMax) value in picoseconds. Default value used: 31875ps
. As per JESD209-4C, TCKmax should be 100ns (100000ps) for all speed grades. But the SPD byte to encode this field is only 1 byte. Hence, the maximum value that can be encoded is 31875ps.
taaMinPs
: Minimum CAS Latency Time(taaMin) in picoseconds. This value defaults to nck * tckMin, where nck is minimum CAS latency.
trcdMinNs
: Minimum RAS# to CAS# Delay Time (tRCDmin) in nanoseconds. As per JESD209-4C, this is max(18ns, 4nck) which defaults to 18ns
.
casLatencies
: List of CAS latencies supported by the part. This is dependent on the attrib speedMbps
. Default values used:
"6 10 14 20 24 28 32 36"
."6 10 14 20 24 28 32"
."6 10 14 20 24 28"
.memory_parts.json
{ "parts": [ { "name": "MT53D512M64D4NW-046 WT:F", "attribs": { "densityPerChannelGb": 8, "banks": 8, "channelsPerDie": 2, "diesPerPackage": 2, "bitWidthPerChannel": 16, "ranksPerChannel": 1, "speedMbps": 4267 } }, { "name": "NT6AP256T32AV-J1", "attribs": { "densityPerChannelGb": 4, "banks": 8, "channelsPerDie": 2, "diesPerPackage": 1, "bitWidthPerChannel": 16, "ranksPerChannel": 1, "speedMbps": 4267, "tckMaxPs": 1250, "casLatencies": "14 20 24 28 32 36" } }, ] }
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.
packageBusWidth
: 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.
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. To 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.
memory_parts.json
{ "parts": [ { "name": "K4A8G165WC-BCWE", "attribs": { "speedMTps": 3200, "CL_nRCD_nRP": 22, "capacityPerDieGb": 8, "diesPerPackage": 1, "packageBusWidth": 16, "ranksPerPackage": 1 } }, { "name": "MT40A1G16KD-062E:E", "attribs": { "speedMTps": 3200, "CL_nRCD_nRP": 22, "capacityPerDieGb": 16, "diesPerPackage": 1, "packageBusWidth": 16, "ranksPerPackage": 1, "TRFC1MinPs": 350000, "TRFC2MinPs": 260000, "TRFC4MinPs": 160000 } }, ] }
densityPerDieGb
: Density per die in Gb. Valid values: 4, 6, 8, 12, 16, 24, 32
Gb per die.
diesPerPackage
: Number of physical dies in each SDRAM package. Valid values: 2, 4, 8
dies per package.
bitWidthPerChannel
: Width of each physical channel. Valid values: 8, 16
bits.
ranksPerChannel
: Number of ranks per physical channel. Valid values: 1, 2
. If the channels across multiple dies share the same DQ/DQS pins but use a separate CS, then ranks is 2 else it is 1.
speedMbps
: Maximum data rate supported by the part in Mbps. Valid values: 5500, 6400
Mbps.
trfcabNs
: Minimum Refresh Recovery Delay Time (tRFCab) for all banks in nanoseconds. As per JESD209-5B, this is dependent on the density per die. Default values used:
trfcpbNs
: Minimum Refresh Recovery Delay Time (tRFCpb) per bank in nanoseconds. As per JESD209-5B, this is dependent on the density per die. Default values used:
trpabMinNs
: Minimum Row Precharge Delay Time (tRPab) for all banks in nanoseconds. As per JESD209-5B, this is max(21ns, 2nCK), which defaults to 21 ns
.
trppbMinNs
: Minimum Row Precharge Delay Time (tRPpb) per bank in nanoseconds. As per JESD209-5B, this is max(18ns, 2nCK) which defaults to 18 ns
.
tckMinPs
: SDRAM minimum cycle time (tCKmin) value in picoseconds. LPDDR5 has two clocks: the command/addrees clock (CK) and the data clock (WCK). They are related by the WCK:CK ratio, which can be either 4:1 or 2:1. For LPDDR5, tCKmin is the CK period, which can be calculated from the speedMbps
attribute and the WCK:CK ratio as follows: tCKmin = 1 / (speedMbps / 2 / WCK:CK)
. The default values used are for a 4:1 WCK:CK ratio:
taaMinPs
: Minimum CAS Latency Time(tAAmin) in picoseconds. This value defaults to nck * tCKmin, where nck is maximum CAS latency, and is determined from the speedMbps
attribute as per JESD209-5B:
trcdMinNs
: Minimum RAS# to CAS# Delay Time (tRCDmin) in nanoseconds. As per JESD209-5B, this is max(18ns, 2nCK) which defaults to 18 ns
.
memory_parts.json
{ "parts": [ { "name": "MT62F1G32D4DR-031 WT:B", "attribs": { "densityPerDieGb": 8, "diesPerPackage": 4, "bitWidthPerChannel": 16, "ranksPerChannel": 2, "speedMbps": 6400 } }, ] }
The spd_gen
tool generates the directory structure shown below. The inputs to the tool are the memory_parts.json
files, and all other files are generated.
spd | |_ lp4x | |_ memory_parts.json |_ platforms_manifest.generated.txt |_ set-0 |_parts_spd_manifest.generated.txt |_spd-1.hex |_spd-2.hex |_... |_ set-1 |_... |_... | |_ ddr4 | |_ memory_parts.json |_ platforms_manifest.generated.txt |_ set-0 |_parts_spd_manifest.generated.txt |_spd-1.hex |_spd-2.hex |_... |_ set-1 |_... |_... |_...
The files generated are:
spd-X.hex
: Deduplicated SPDs for all the memory parts in the input JSON file.
parts_spd_manifest.generated.txt
: A CSV file mapping each memory part to one of the deduplicated SPD files. E.g.
H9HCNNNBKMMLXR-NEE,spd-1.hex H9HCNNNFAMMLXR-NEE,spd-2.hex K4U6E3S4AA-MGCL,spd-1.hex K4UBE3D4AA-MGCL,spd-3.hex MT53E1G32D2NP-046 WT:A,spd-4.hex
platforms_manifest.generated.txt
: A CSV file mapping each platform to the SPD set used by that platform. E.g.
TGL,set-0 ADL,set-0 JSL,set-1 CZN,set-1
part_id_gen
This program takes the following inputs:
*
and ensures that only parts withExample of a CSV file using fixed and exclusive IDs:
K4AAG165WA-BCWE,1 MT40A512M16TB-062E:J MT40A1G16KD-062E:E K4A8G165WC-BCWE H5AN8G6NDJR-XNC,8 H5ANAG6NCMR-XNC,*9
Explanation: This will ensure that the SPDs for K4AAG165WA-BCWE and H5AN8G6NDJR-XNC are assigned to IDs 1 and 8 respectively. H5ANAG6NCMR-XNC will be assigned ID 9 and no other part will be assigned ID 9 even if it shares the same SPD. The SPDs for all other memory parts will be assigned to the first compatible ID. Assigning fixed/exclusive IDs may result in duplicate SPD entries or gaps in the ID mapping.
The part_id_gen
tool outputs the following:
Makefile.inc
in the given directory. This is used to integrate the SPD files generated by spd_gen
with the coreboot build for the board.dram_id.generated.txt
in the same directory as the Makefile.inc
. This lists the part IDs assigned to each memory part, and is useful for itegration with the board schematics.Sample Makefile.inc
:
# SPDX-License-Identifier: GPL-2.0-or-later # This is an auto-generated file. Do not edit!! # Generated by: # util/spd_tools/bin/part_id_gen ADL lp4x src/mainboard/google/brya/variants/felwinter/memory src/mainboard/google/brya/variants/felwinter/memory/mem_parts_used.txt SPD_SOURCES = SPD_SOURCES += spd/lp4x/set-0/spd-1.hex # ID = 0(0b0000) Parts = K4U6E3S4AA-MGCR, H9HCNNNBKMMLXR-NEE SPD_SOURCES += spd/lp4x/set-0/spd-3.hex # ID = 1(0b0001) Parts = K4UBE3D4AA-MGCR SPD_SOURCES += spd/lp4x/set-0/spd-4.hex # ID = 2(0b0010) Parts = MT53E1G32D2NP-046 WT:A
NOTE: Empty entries may be required if there is a gap created by a memory part with a fixed ID.
Sample dram_id.generated.txt
:
# SPDX-License-Identifier: GPL-2.0-or-later # This is an auto-generated file. Do not edit!! # Generated by: # util/spd_tools/bin/part_id_gen ADL lp4x src/mainboard/google/brya/variants/felwinter/memory src/mainboard/google/brya/variants/felwinter/memory/mem_parts_used.txt DRAM Part Name ID to assign K4U6E3S4AA-MGCR 0 (0000) K4UBE3D4AA-MGCR 1 (0001) H9HCNNNBKMMLXR-NEE 0 (0000) MT53E1G32D2NP-046 WT:A 2 (0010)
The part_id_gen
tool assigns DRAM IDs based on the order of the part names in the input file. Thus, when adding a new memory part to the list, it should always go at the end of the file. This guarantees that the memory parts that were already assigned IDs do not change.
make clean -C util/spd_tools make -C util/spd_tools
spd_gen
Usage:
util/spd_tools/bin/spd_gen <mem_parts_list_json> <mem_technology>
Example:
util/spd_tools/bin/spd_gen spd/lp4x/memory_parts.json lp4x
part_id_gen
Usage:
util/spd_tools/bin/part_id_gen <platform> <mem_technology> <makefile_dir> <mem_parts_used_file>
Example:
util/spd_tools/bin/part_id_gen \ ADL \ lp4x \ src/mainboard/google/brya/variants/felwinter/memory \ src/mainboard/google/brya/variants/felwinter/memory/mem_parts_used.txt
If the memory part is not present in the global list of memory parts for that memory technology (e.g. spd/lp4x/memory_parts.json
), then add the memory part name and attributes as per the datasheet.
spd_gen
to regenerate all the SPD files and manifests for that memory technology. Either a new SPD file will be generated for the new part, or an existing one will be reused.Update the file containing the memory parts used by board (variant), by adding the new memory part name at the end of the file.
part_id_gen
to update the variant's Makefile.inc
and dram_id.generated.txt
with the new part.Makefile.inc
and dram_id.generated.txt
for review.To generate SPDs for the new memory technology, information is needed about the list of bytes in the SPD and how the value of each byte should be determined. This information usually comes from a combination of:
Support for the new memory technology needs to be added to both the spd_gen
and part_id_gen
tools.
spd_gen
Adding support to spd_gen
requires implementing the logic to generate SPDs for the new memory technology. The changes required are:
memTechMap
in spd_gen/spd_gen.go
.spd_gen/<mem_tech>.go
. This file will contain all the logic for generating SPDs for the new memory technology. It needs to implement the memTech
interface defined in spd_gen/spd_gen.go
. The interface functions are documented inline. Examples of how the interface is implemented for existing memory technologies can be found in the spd_gen/
directory, e.g. lp4x.go
, ddr4.go
, lp5.go
. While not strictly necessary, it is recommended to follow the overall structure of these existing files when adding a new memory technology.part_id_gen
The part_id_gen
tool is memory technology-agnostic, so the only change required is:
supportedMemTechs
list in part_id_gen/part_id_gen.go
.