3 A set of tools to generate SPD files for platforms with memory down
6 The memory technologies currently supported are:
8 * LPDDR4x - based on the JESD209-4C spec and Intel recommendations
9 (docs #616599, #610202, #634730).
10 * DDR4 - based on the JESD79-4C and Jedec 4.1.2.L-5 R29 v103 specs.
11 * LPDDR5/5X - based on the LPDDR5 spec JESD209-5B, the SPD spec SPD4.1.2.M-2
12 (the LPDDR3/4 spec is used since JEDEC has not released an SPD spec for
13 LPDDR5), and Intel recommendations in advisory #616599.
15 There are two tools provided to assist with generating SPDs and Makefiles to
16 integrate into the coreboot build. These tools can also be used to allocate DRAM
17 IDs (configure DRAM hardware straps) for any memory part used by a board.
19 * `spd_gen`: This tool generates de-duplicated SPD files using a global memory
20 part list. It also generates a CSV manifest file which maps each memory part
21 in the global list to one of the generated SPD files. For each supported
22 memory technology, multiple sets of SPDs are generated. Each set corresponds
23 to a set of SoC platforms with different SPD requirements, e.g. due to
24 different expectations in the memory training code. Another CSV manifest
25 maps each supported platform to one of these sets.
26 * `part_id_gen`: This tool allocates DRAM strap IDs for the different memory
27 parts used by a board. It takes as input a CSV file of the memory parts used
28 with optional fixed IDs. It generates a Makefile.mk which is used to
29 integrate the SPD files generated by `spd_gen` into the coreboot build.
33 This program takes the following inputs:
35 * Path to a JSON file containing a global list of memory parts with their
36 attributes as per the datasheet. This is the list of all known memory parts
37 for the given memory technology.
39 * The memory technology for which to generate the SPDs,
45 The input JSON file requires the following two fields for every memory part:
47 * `name`: The name of the memory part.
48 * `attribs`: A list of the memory part's attributes, as per its datasheet.
49 These attributes match the part specifications and are independent of any
50 SoC expectations. The tool takes care of translating the physical attributes
51 of the memory part to match JEDEC spec and memory traning code expectations.
53 The `attribs` field further contains two types of sub-field:
55 * Mandatory: These attributes must be provided for each memory part.
56 * Optional: These attributes may be provided for a memory part in order to
57 override the defaults.
59 The attributes are different for each memory technology.
65 * `densityPerChannelGb`: Density in Gb of the physical channel.
67 * `banks`: Number of banks per physical channel. This is typically 8 for
70 * `channelsPerDie`: Number of physical channels per die. Valid values: `1, 2,
71 4`. For a part with x16 bit width, number of channels per die is 1 or 2. For
72 a part with x8 bit width, number of channels can be 2 or 4 (4 is basically
73 when two dual-channel byte mode devices are combined as shown in Figure 3 in
76 * `diesPerPackage`: Number of physical dies in each SDRAM package. As per
77 JESD209-4C, "Standard LPDDR4 package ballmaps allocate one ZQ ball per die."
78 Thus, number of diesPerPackage is the number of ZQ balls on the package.
80 * `bitWidthPerChannel`: Width of each physical channel. Valid values: `8, 16`
83 * `ranksPerChannel`: Number of ranks per physical channel. Valid values: `1,
84 2`. If the channels across multiple dies share the same DQ/DQS pins but use
85 a separate CS, then ranks is 2 else it is 1.
87 * `speedMbps`: Maximum data rate supported by the part in Mbps. Valid values:
88 `3200, 3733, 4267` Mbps.
92 * `trfcabNs`: Minimum Refresh Recovery Delay Time (tRFCab) for all banks in
93 nanoseconds. As per JESD209-4C, this is dependent on the density per
94 channel. Default values used:
101 * `trfcpbNs`: Minimum Refresh Recovery Delay Time (tRFCab) per bank in
102 nanoseconds. As per JESD209-4C, this is dependent on the density per
103 channel. Default values used:
110 * `trpabMinNs`: Minimum Row Precharge Delay Time (tRPab) for all banks in
111 nanoseconds. As per JESD209-4C, this is max(21ns, 4nck) which defaults to
114 * `trppbMinNs`: Minimum Row Precharge Delay Time (tRPpb) per bank in
115 nanoseconds. As per JESD209-4C, this is max(18ns, 4nck) which defaults to
118 * `tckMinPs`: SDRAM minimum cycle time (tckMin) value in picoseconds. This is
119 typically calculated based on the `speedMbps` attribute. `(1 / speedMbps) *
120 2`. Default values used(taken from JESD209-4C):
126 * `tckMaxPs`: SDRAM maximum cycle time (tckMax) value in picoseconds. Default
127 value used: `31875ps`. As per JESD209-4C, TCKmax should be 100ns (100000ps)
128 for all speed grades. But the SPD byte to encode this field is only 1 byte.
129 Hence, the maximum value that can be encoded is 31875ps.
131 * `taaMinPs`: Minimum CAS Latency Time(taaMin) in picoseconds. This value
132 defaults to nck * tckMin, where nck is minimum CAS latency.
134 * `trcdMinNs`: Minimum RAS# to CAS# Delay Time (tRCDmin) in nanoseconds. As
135 per JESD209-4C, this is max(18ns, 4nck) which defaults to `18ns`.
137 * `casLatencies`: List of CAS latencies supported by the part. This is
138 dependent on the attrib `speedMbps`. Default values used:
140 * 4267: `"6 10 14 20 24 28 32 36"`.
141 * 3733: `"6 10 14 20 24 28 32"`.
142 * 3200: `"6 10 14 20 24 28"`.
144 #### Example `memory_parts.json`
150 "name": "MT53D512M64D4NW-046 WT:F",
152 "densityPerChannelGb": 8,
156 "bitWidthPerChannel": 16,
157 "ranksPerChannel": 1,
162 "name": "NT6AP256T32AV-J1",
164 "densityPerChannelGb": 4,
168 "bitWidthPerChannel": 16,
169 "ranksPerChannel": 1,
172 "casLatencies": "14 20 24 28 32 36"
183 * `speedMTps`: Maximum rate supported by the part in MT/s. Valid values:
184 `1600, 1866, 2133, 2400, 2666, 2933, 3200` MT/s.
186 * `CL_nRCD_nRP`: Refers to CAS Latency specified for the part (find
187 "CL-nRCD-nRP" in the vendor spec for the DDR4 part).
189 * `capacityPerDieGb`: Capacity per die in gigabits. Valid values: `2, 4, 8,
192 * `diesPerPackage`: Number of dies on the part. Valid values: `1, 2` dies per
195 * `packageBusWidth`: Number of bits of the device's address bus. Valid values:
196 `8, 16` bit-wide bus. NOTE: Width of x4 is not supported by this tool.
198 * `ranksPerPackage`: From Jedec doc 4_01_02_AnnexL-1R23: “Package ranks per
199 DIMM” refers to the collections of devices on the module sharing common chip
200 select signals (across the data width of the DIMM), either from the edge
201 connector for unbuffered modules or from the outputs of a registering clock
202 driver for RDIMMs and LRDIMMs.Number of bits of the device's address bus.
203 Valid values: `1, 2` package ranks.
207 The following options are calculated by the tool based on the mandatory
208 attributes described for the part, but there may be cases where a default value
209 must be overridden, such as when a device appears to be 3200AA, but does not
210 support all of the CAS latencies typically supported by a speed bin 3200AA part.
211 To deal with such a case, the variable can be overridden here and the tool will
212 use this value instead of calculating one. All values must be defined in
213 picosecond units, except for "CASLatencies", which would be represented as a
214 string like "9 10 11 12 14".
216 * `TAAMinPs`: Defines the minimum CAS Latency. Table 48 of Jedec doc
217 4_01_02_AnnexL-5R29 lists tAAmin for each speed grade.
219 * `TRASMinPs`: Refers to the minimum active to precharge delay time. Table 55
220 of Jedec doc 4_01_02_AnnexL-5R29 lists tRPmin for each speed grade.
222 * `TCKMinPs`: Refers to the minimum clock cycle time. Table 42 of Jedec doc
223 4_01_02_AnnexL-5R29 lists tCKmin for each speed grade.
225 * `TCKMaxPs`:Refers to the minimum clock cycle time. Table 44 of Jedec doc
226 4_01_02_AnnexL-5R29 lists tCKmin for each speed grade.
228 * `TRFC1MinPs`: Refers to the minimum refresh recovery delay time. Table 59 of
229 Jedec doc 4_01_02_AnnexL-5R29 lists tRFC1min for each page size.
231 * `TRFC2MinPs`: Refers to the minimum refresh recovery delay time. Table 61 of
232 Jedec doc 4_01_02_AnnexL-5R29 lists tRFC2min for each page size.
234 * `TRFC4MinPs`: Refers to the minimum refresh recovery delay time. Table 63 of
235 Jedec doc 4_01_02_AnnexL-5R29 lists tRFC4min for each page size.
237 * `TFAWMinPs`:: Refers to the minimum four activate window delay time. Table
238 66 of Jedec doc 4_01_02_AnnexL-5R29 lists tFAWmin for each speed grade and
239 page size combination.
241 * `TRRDSMinPs`: Refers to the minimum activate to activate delay time to
242 different bank groups. Table 68 of Jedec doc 4_01_02_AnnexL-5R29 lists
243 tRRD_Smin for each speed grade and page size combination.
245 * `TRRDLMinPs`: Refers to the minimum activate to activate delay time to the
246 same bank group. Table 70 of Jedec doc 4_01_02_AnnexL-5R29 lists tRRD_Lmin
247 for each speed grade and page size combination.
249 * `TCCDLMinPs`: Refers to the minimum CAS to CAS delay time to same bank
250 group. Table 72 of Jedec doc 4_01_02_AnnexL-5R29 lists tCCD_Lmin for each
253 * `TWRMinPs`: Refers to the minimum write recovery time. Table 75 of Jedec doc
254 4_01_02_AnnexL-5R29 lists tWRmin for each ddr4 type.
256 * `TWTRSMinPs`: Refers to minimum write to read time to different bank group.
257 Table 78 of Jedec doc 4_01_02_AnnexL-5R29 lists tWTR_Smin for each ddr4
260 * `TWTRLMinPs`: Refers to minimum write to read time to same bank group. Table
261 80 of Jedec doc 4_01_02_AnnexL-5R29 lists tWTR_Lmin for each ddr4 type.
263 * `CASLatencies`: Refers to the CAS latencies supported by the part. The speed
264 bin tables in the back of Jedec doc 4_01_02_AnnexL-5R29 define the standard
265 CAS latencies that a speed bin part is supposed to support. In cases where a
266 part does not support all of the CAS latencies listed in the speed bin
267 tables, this entry should be used to override the default settings.
269 #### Example `memory_parts.json`
275 "name": "K4A8G165WC-BCWE",
279 "capacityPerDieGb": 8,
281 "packageBusWidth": 16,
286 "name": "MT40A1G16KD-062E:E",
290 "capacityPerDieGb": 16,
292 "packageBusWidth": 16,
293 "ranksPerPackage": 1,
294 "TRFC1MinPs": 350000,
295 "TRFC2MinPs": 260000,
307 * `densityPerDieGb`: Density per die in Gb. Valid values: `4, 6, 8, 12, 16,
310 * `diesPerPackage`: Number of physical dies in each SDRAM package. Valid
311 values: `2, 4, 8` dies per package.
313 * `bitWidthPerChannel`: Width of each physical channel. Valid values: `8, 16`
316 * `ranksPerChannel`: Number of ranks per physical channel. Valid values: `1,
317 2`. If the channels across multiple dies share the same DQ/DQS pins but use
318 a separate CS, then ranks is 2 else it is 1.
320 * `speedMbps`: Maximum data rate supported by the part in Mbps. Valid values:
325 * `lp5x`: If this is an LP5X part. SPD format is identical for LP5/5X aside
326 from the memory type byte.
328 * `trfcabNs`: Minimum Refresh Recovery Delay Time (tRFCab) for all banks in
329 nanoseconds. As per JESD209-5B, this is dependent on the density per die.
340 * `trfcpbNs`: Minimum Refresh Recovery Delay Time (tRFCpb) per bank in
341 nanoseconds. As per JESD209-5B, this is dependent on the density per die.
352 * `trpabMinNs`: Minimum Row Precharge Delay Time (tRPab) for all banks in
353 nanoseconds. As per JESD209-5B, this is max(21ns, 2nCK), which defaults to
356 * `trppbMinNs`: Minimum Row Precharge Delay Time (tRPpb) per bank in
357 nanoseconds. As per JESD209-5B, this is max(18ns, 2nCK) which defaults to
360 * `tckMinPs`: SDRAM minimum cycle time (tCKmin) value in picoseconds. LPDDR5
361 has two clocks: the command/addrees clock (CK) and the data clock (WCK).
362 They are related by the WCK:CK ratio, which can be either 4:1 or 2:1. For
363 LPDDR5, tCKmin is the CK period, which can be calculated from the
364 `speedMbps` attribute and the WCK:CK ratio as follows: `tCKmin = 1 /
365 (speedMbps / 2 / WCK:CK)`. The default values used are for a 4:1 WCK:CK
371 * `taaMinPs`: Minimum CAS Latency Time(tAAmin) in picoseconds. This value
372 defaults to nck * tCKmin, where nck is maximum CAS latency, and is
373 determined from the `speedMbps` attribute as per JESD209-5B:
378 * `trcdMinNs`: Minimum RAS# to CAS# Delay Time (tRCDmin) in nanoseconds. As
379 per JESD209-5B, this is max(18ns, 2nCK) which defaults to `18 ns`.
381 #### Example `memory_parts.json`
387 "name": "MT62F1G32D4DR-031 WT:B",
389 "densityPerDieGb": 8,
391 "bitWidthPerChannel": 16,
392 "ranksPerChannel": 2,
402 The `spd_gen` tool generates the directory structure shown below. The inputs to
403 the tool are the `memory_parts.json` files, and all other files are generated.
411 |_ platforms_manifest.generated.txt
413 |_parts_spd_manifest.generated.txt
424 |_ platforms_manifest.generated.txt
426 |_parts_spd_manifest.generated.txt
436 The files generated are:
438 * `spd-X.hex`: Deduplicated SPDs for all the memory parts in the input JSON
441 * `parts_spd_manifest.generated.txt`: A CSV file mapping each memory part to
442 one of the deduplicated SPD files. E.g.
445 H9HCNNNBKMMLXR-NEE,spd-1.hex
446 H9HCNNNFAMMLXR-NEE,spd-2.hex
447 K4U6E3S4AA-MGCL,spd-1.hex
448 K4UBE3D4AA-MGCL,spd-3.hex
449 MT53E1G32D2NP-046 WT:A,spd-4.hex
452 * `platforms_manifest.generated.txt`: A CSV file mapping each platform to the
453 SPD set used by that platform. E.g.
462 ## Tool 2 - `part_id_gen`
464 This program takes the following 4 inputs:
466 * 1) The SoC platform which the board is based on, e.g. ADL.
467 * 2) The memory technology used by the board, One of ddr4, lp4x, or lp5.
468 * 3) The path to the directory where the generated Makefile.mk should be placed.
469 * 4) A CSV file containing a list of the memory parts used by the board, with an
470 optional fixed or exclusive ID for each part and an optional SPD override file.
471 A fixed ID is simply an integer and it ensure that part (and any that share the
472 same SPD) will be assigned that ID. An exclusive ID is prefixed with `*` and ensures
473 that only parts with the same exclusive ID will be assigned that ID, even if they would
474 otherwise share the same ID. When using an SPD override file, the file will be searched
475 for in the directory where mem_parts_used is located, if it is not found there then it
476 will be searched for in the appropriate default spd directory.
478 NOTE: Only assign a fixed/exclusive ID if required for legacy reasons.
480 Example of a CSV file using fixed and exclusive IDs, and SPD file overrides:
489 H9HCNNNCPMMLXR-NEE,,H9HCNNNCPMMLXR-NEE.hex
490 H54G56CYRBX247,4,H54G56CYRBX247.hex
493 Explanation: This will ensure that the SPDs for K4AAG165WA-BCWE and
494 H5AN8G6NDJR-XNC are assigned to IDs 1 and 8 respectively. H5ANAG6NCMR-XNC
495 will be assigned ID 9 and no other part will be assigned ID 9 even if it
496 shares the same SPD. The SPDs for all other memory parts will be assigned to
497 the first compatible ID. Assigning fixed/exclusive IDs may result in duplicate
498 SPD entries or gaps in the ID mapping.
502 The `part_id_gen` tool outputs the following:
504 * It prints the DRAM hardware strap ID which should be allocated to each
505 memory part in the input file.
506 * It generates a `Makefile.mk` in the given directory. This is used to
507 integrate the SPD files generated by `spd_gen` with the coreboot build for
509 * It generates a `dram_id.generated.txt` in the same directory as the
510 `Makefile.mk`. This lists the part IDs assigned to each memory part, and is
511 useful for itegration with the board schematics.
513 Sample `Makefile.mk`:
516 # SPDX-License-Identifier: GPL-2.0-or-later
517 # This is an auto-generated file. Do not edit!!
519 # 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
522 SPD_SOURCES += spd/lp4x/set-0/spd-1.hex # ID = 0(0b0000) Parts = K4U6E3S4AA-MGCR, H9HCNNNBKMMLXR-NEE
523 SPD_SOURCES += spd/lp4x/set-0/spd-3.hex # ID = 1(0b0001) Parts = K4UBE3D4AA-MGCR
524 SPD_SOURCES += spd/lp4x/set-0/spd-4.hex # ID = 2(0b0010) Parts = MT53E1G32D2NP-046 WT:A
527 NOTE: Empty entries may be required if there is a gap created by a memory part
530 Sample `dram_id.generated.txt`:
533 # SPDX-License-Identifier: GPL-2.0-or-later
534 # This is an auto-generated file. Do not edit!!
536 # 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
538 DRAM Part Name ID to assign
539 K4U6E3S4AA-MGCR 0 (0000)
540 K4UBE3D4AA-MGCR 1 (0001)
541 H9HCNNNBKMMLXR-NEE 0 (0000)
542 MT53E1G32D2NP-046 WT:A 2 (0010)
547 The `part_id_gen` tool assigns DRAM IDs based on the order of the part names in
548 the input file. Thus, when adding a new memory part to the list, it should
549 always go at the end of the file. This guarantees that the memory parts that
550 were already assigned IDs do not change.
552 ## How to build the tools?
555 make clean -C util/spd_tools
556 make -C util/spd_tools
559 ## How to use the tools?
566 util/spd_tools/bin/spd_gen <mem_parts_list_json> <mem_technology>
572 util/spd_tools/bin/spd_gen spd/ddr4/memory_parts.json ddr4
573 util/spd_tools/bin/spd_gen spd/lp4x/memory_parts.json lp4x
574 util/spd_tools/bin/spd_gen spd/lp5/memory_parts.json lp5
582 util/spd_tools/bin/part_id_gen <platform> <mem_technology> <makefile_dir> <mem_parts_used_file>
588 util/spd_tools/bin/part_id_gen \
591 src/mainboard/google/brya/variants/felwinter/memory \
592 src/mainboard/google/brya/variants/felwinter/memory/mem_parts_used.txt
595 ### Need to add a new memory part for a board?
597 * If the memory part is not present in the global list of memory parts for
598 that memory technology (e.g. `spd/lp4x/memory_parts.json`), then add the
599 memory part name and attributes as per the datasheet.
601 * Use `spd_gen` to regenerate all the SPD files and manifests for that
602 memory technology. Either a new SPD file will be generated for the new
603 part, or an existing one will be reused.
604 * Upload the new SPD (if one is created) and the manifest changes for
607 * Update the file containing the memory parts used by board (variant), by
608 adding the new memory part name at the end of the file.
610 * Use `part_id_gen` to update the variant's `Makefile.mk` and
611 `dram_id.generated.txt` with the new part.
612 * Upload the changes to `Makefile.mk` and `dram_id.generated.txt` for
615 ## How to add support for a new memory technology
617 ### 1. Gather the SPD requirements
619 To generate SPDs for the new memory technology, information is needed about the
620 list of bytes in the SPD and how the value of each byte should be determined.
621 This information usually comes from a combination of:
623 * The JEDEC spec for the memory technology, e.g. JESD209-5B for LPDDR5.
624 * The JEDEC SPD spec for the memory technology, e.g. SPD4.1.2.M-2 for LPDDR3/4
625 (also used for LP4x and LP5).
626 * Platform-specific requirements. SoC vendors often don't follow the JEDEC
627 specs exactly. E.g. the memory training code may expect certain SPD bytes to
628 encode a different value to what is stated in the spec. So for each SoC
629 platform using the new memory technology, any platform-specific requirements
632 ### 2. Implement support in spd_tools
634 Support for the new memory technology needs to be added to both the `spd_gen`
635 and `part_id_gen` tools.
639 Adding support to `spd_gen` requires implementing the logic to generate SPDs for
640 the new memory technology. The changes required are:
642 * Add the new memory technology to the `memTechMap` in `spd_gen/spd_gen.go`.
643 * Add a new file `spd_gen/<mem_tech>.go`. This file will contain all the logic
644 for generating SPDs for the new memory technology. It needs to implement the
645 `memTech` interface defined in `spd_gen/spd_gen.go`. The interface functions
646 are documented inline. Examples of how the interface is implemented for
647 existing memory technologies can be found in the `spd_gen/` directory, e.g.
648 `lp4x.go`, `ddr4.go`, `lp5.go`. While not strictly necessary, it is
649 recommended to follow the overall structure of these existing files when
650 adding a new memory technology.
654 The `part_id_gen` tool is memory technology-agnostic, so the only change
657 * Add the new memory technology to the `supportedMemTechs` list in
658 `part_id_gen/part_id_gen.go`.