diff options
-rw-r--r-- | util/spd_tools/README.md | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/util/spd_tools/README.md b/util/spd_tools/README.md new file mode 100644 index 0000000000..5be666bde4 --- /dev/null +++ b/util/spd_tools/README.md @@ -0,0 +1,495 @@ +# SPD tools + +A set of tools to generate SPD files for platforms with memory down +configurations. + +The memory technologies currently supported are: + +* LPDDR4x - based on the JESD209-4C spec and Intel recommendations + (docs #616599, #610202, #634730). +* DDR4 - based on the JESD79-4C and Jedec 4.1.2.L-5 R29 v103 specs. + +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. + +## Tool 1 - `spd_gen` + +This program takes the following inputs: + +* A JSON file containing a global list of memory parts with their attributes + as per the datasheet. This is the list of all known memory parts for the + given memory technology. +* The memory technology for which to generate the SPDs, e.g. "lp4x". + +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: + +* Mandatory: These attributes must be provided for each memory part. +* Optional: These attributes may be provided for a memory part in order to + override the defaults. + +The attributes are different for each memory technology. + +### LP4x attributes + +#### Mandatory + +* `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. + +#### Optional + +* `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: + + * 6Gb : 280ns + * 8Gb : 280ns + * 12Gb: 380ns + * 16Gb: 380ns + +* `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: + + * 6Gb : 140ns + * 8Gb : 140ns + * 12Gb: 190ns + * 16Gb: 190ns + +* `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): + + * 4267 Mbps: 468ps + * 3733 Mbps: 535ps + * 3200 Mbps: 625ps + +* `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: + + * 4267: `"6 10 14 20 24 28 32 36"`. + * 3733: `"6 10 14 20 24 28 32"`. + * 3200: `"6 10 14 20 24 28"`. + +#### Example `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" + } + }, + ] +} +``` + +### DDR4 attributes + +#### Mandatory + +* `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. + +#### Optional + +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. + +#### Example `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 + } + }, + ] +} +``` + +### Output + +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 + ``` + +## Tool 2 - `part_id_gen` + +This program takes the following inputs: + +* The SoC platform which the board is based on, e.g. ADL. +* The memory technology used by the board, e.g. lp4x. +* The path to the directory where the generated Makefile.inc should be placed. +* A CSV file containing a list of the memory parts used by the board, with an + optional fixed ID for each part. NOTE: Only assign a fixed ID if required + for legacy reasons. + +Example of a CSV file using fixed IDs: + +``` +K4AAG165WA-BCWE,1 +MT40A512M16TB-062E:J +MT40A1G16KD-062E:E +K4A8G165WC-BCWE +H5AN8G6NDJR-XNC,8 +H5ANAG6NCMR-XNC +``` + +Explanation: This will ensure that the SPDs for K4AAG165WA-BCWE and +H5AN8G6NDJR-XNC are assigned to IDs 1 and 8 respectively. The SPDs for 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. + +### Output + +The `part_id_gen` tool outputs the following: + +* It prints the DRAM hardware strap ID which should be allocated to each + memory part in the input file. +* It generates a `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. +* It generates a `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) +``` + +### Note of caution + +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. + +## How to build the tools? + +``` +make clean -C util/spd_tools +make -C util/spd_tools +``` + +## How to use the 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 +``` + +### Need to add a new memory part for a board? + +* 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. + + * Use `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. + * Upload the new SPD (if one is created) and the manifest changes for + review. + +* Update the file containing the memory parts used by board (variant), by + adding the new memory part name at the end of the file. + + * Use `part_id_gen` to update the variant's `Makefile.inc` and + `dram_id.generated.txt` with the new part. + * Upload the changes to `Makefile.inc` and `dram_id.generated.txt` for + review. |